Estructura inicial del proyecto

This commit is contained in:
2026-06-02 16:57:08 +00:00
commit 8b306b9afc
9864 changed files with 1435687 additions and 0 deletions

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { Logger } from "@azure/msal-common/browser";
import { InteractionType } from "../utils/BrowserConstants.js";
import {
EventCallbackFunction,
EventError,
EventMessage,
EventPayload,
} from "./EventMessage.js";
import { EventType } from "./EventType.js";
import { createGuid } from "../utils/BrowserUtils.js";
const BROADCAST_CHANNEL_NAME = "msal.broadcast.event";
export class EventHandler {
// Callback for subscribing to events
private eventCallbacks: Map<
string,
[EventCallbackFunction, Array<EventType>]
>;
private logger: Logger;
private broadcastChannel?: BroadcastChannel;
constructor(logger?: Logger) {
this.eventCallbacks = new Map();
this.logger = logger || new Logger({});
if (typeof BroadcastChannel !== "undefined") {
this.broadcastChannel = new BroadcastChannel(
BROADCAST_CHANNEL_NAME
);
}
this.invokeCrossTabCallbacks = this.invokeCrossTabCallbacks.bind(this);
}
/**
* Adds event callbacks to array
* @param callback - callback to be invoked when an event is raised
* @param eventTypes - list of events that this callback will be invoked for, if not provided callback will be invoked for all events
* @param callbackId - Identifier for the callback, used to locate and remove the callback when no longer required
*/
addEventCallback(
callback: EventCallbackFunction,
eventTypes?: Array<EventType>,
callbackId?: string
): string | null {
if (typeof window !== "undefined") {
const id = callbackId || createGuid();
if (this.eventCallbacks.has(id)) {
this.logger.error(
`Event callback with id: '${id}' is already registered. Please provide a unique id or remove the existing callback and try again.`,
""
);
return null;
}
this.eventCallbacks.set(id, [callback, eventTypes || []]);
this.logger.verbose(
`Event callback registered with id: '${id}'`,
""
);
return id;
}
return null;
}
/**
* Removes callback with provided id from callback array
* @param callbackId
*/
removeEventCallback(callbackId: string): void {
this.eventCallbacks.delete(callbackId);
this.logger.verbose(`Event callback '${callbackId}' removed.`, "");
}
/**
* Emits events by calling callback with event message
* @param eventType
* @param interactionType
* @param payload
* @param error
*/
emitEvent(
eventType: EventType,
correlationId: string,
interactionType?: InteractionType,
payload?: EventPayload,
error?: EventError
): void {
const message: EventMessage = {
eventType: eventType,
interactionType: interactionType || null,
payload: payload || null,
error: error || null,
correlationId: correlationId,
timestamp: Date.now(),
};
switch (eventType) {
case EventType.LOGIN_SUCCESS:
case EventType.LOGOUT_SUCCESS:
case EventType.ACTIVE_ACCOUNT_CHANGED:
// Send event to other open tabs / MSAL instances on same domain
this.broadcastChannel?.postMessage(message);
}
// Emit event to callbacks registered in this instance
this.invokeCallbacks(message);
}
/**
* Invoke registered callbacks
* @param message
*/
private invokeCallbacks(message: EventMessage): void {
this.eventCallbacks.forEach(
(
[callback, eventTypes]: [
EventCallbackFunction,
Array<EventType>
],
callbackId: string
) => {
if (
eventTypes.length === 0 ||
eventTypes.includes(message.eventType)
) {
this.logger.verbose(
`Emitting event to callback '${callbackId}': '${message.eventType}'`,
""
);
callback.apply(null, [message]);
}
}
);
}
/**
* Wrapper around invokeCallbacks to handle broadcast events received from other tabs/instances
* @param event
*/
private invokeCrossTabCallbacks(event: MessageEvent): void {
const message = event.data as EventMessage;
this.invokeCallbacks(message);
}
/**
* Listen for events broadcasted from other tabs/instances
*/
subscribeCrossTab(): void {
this.broadcastChannel?.addEventListener(
"message",
this.invokeCrossTabCallbacks
);
}
/**
* Unsubscribe from broadcast events
*/
unsubscribeCrossTab(): void {
this.broadcastChannel?.removeEventListener(
"message",
this.invokeCrossTabCallbacks
);
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { AuthError, AccountInfo } from "@azure/msal-common/browser";
import { EventType } from "./EventType.js";
import {
InteractionStatus,
InteractionType,
} from "../utils/BrowserConstants.js";
import { PopupRequest } from "../request/PopupRequest.js";
import { RedirectRequest } from "../request/RedirectRequest.js";
import { SilentRequest } from "../request/SilentRequest.js";
import { SsoSilentRequest } from "../request/SsoSilentRequest.js";
import { EndSessionRequest } from "../request/EndSessionRequest.js";
import { AuthenticationResult } from "../response/AuthenticationResult.js";
export type EventMessage = {
eventType: EventType;
interactionType: InteractionType | null;
payload: EventPayload;
error: EventError;
correlationId: string;
timestamp: number;
};
export type PopupEvent = {
popupWindow: Window;
};
/**
* Payload for the BrokerConnectionEstablished event
*/
export type BrokerConnectionEvent = {
/**
* The origin of the broker that is connected to the client
*/
pairwiseBrokerOrigin: string;
};
export type EventPayload =
| AccountInfo
| PopupRequest
| RedirectRequest
| SilentRequest
| SsoSilentRequest
| EndSessionRequest
| AuthenticationResult
| PopupEvent
| BrokerConnectionEvent
| null;
export type EventError = AuthError | Error | null;
export type EventCallbackFunction = (message: EventMessage) => void;
export class EventMessageUtils {
/**
* Gets interaction status from event message
* @param message
* @param currentStatus
*/
static getInteractionStatusFromEvent(
message: EventMessage,
currentStatus?: InteractionStatus
): InteractionStatus | null {
switch (message.eventType) {
case EventType.ACQUIRE_TOKEN_START:
if (
message.interactionType === InteractionType.Redirect ||
message.interactionType === InteractionType.Popup
) {
return InteractionStatus.AcquireToken;
}
break;
case EventType.HANDLE_REDIRECT_START:
return InteractionStatus.HandleRedirect;
case EventType.LOGOUT_START:
return InteractionStatus.Logout;
case EventType.LOGOUT_END:
if (
currentStatus &&
currentStatus !== InteractionStatus.Logout
) {
// Prevent this event from clearing any status other than logout
break;
}
return InteractionStatus.None;
case EventType.HANDLE_REDIRECT_END:
if (
currentStatus &&
currentStatus !== InteractionStatus.HandleRedirect
) {
// Prevent this event from clearing any status other than handleRedirect
break;
}
return InteractionStatus.None;
case EventType.ACQUIRE_TOKEN_SUCCESS:
case EventType.ACQUIRE_TOKEN_FAILURE:
case EventType.RESTORE_FROM_BFCACHE:
if (
message.interactionType === InteractionType.Redirect ||
message.interactionType === InteractionType.Popup
) {
if (
currentStatus &&
currentStatus !== InteractionStatus.AcquireToken
) {
// Prevent this event from clearing any status other than acquireToken
break;
}
return InteractionStatus.None;
}
break;
default:
break;
}
return null;
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
export const EventType = {
INITIALIZE_START: "msal:initializeStart",
INITIALIZE_END: "msal:initializeEnd",
ACTIVE_ACCOUNT_CHANGED: "msal:activeAccountChanged",
LOGIN_SUCCESS: "msal:loginSuccess",
ACQUIRE_TOKEN_START: "msal:acquireTokenStart",
BROKERED_REQUEST_START: "msal:brokeredRequestStart",
ACQUIRE_TOKEN_SUCCESS: "msal:acquireTokenSuccess",
BROKERED_REQUEST_SUCCESS: "msal:brokeredRequestSuccess",
ACQUIRE_TOKEN_FAILURE: "msal:acquireTokenFailure",
BROKERED_REQUEST_FAILURE: "msal:brokeredRequestFailure",
ACQUIRE_TOKEN_NETWORK_START: "msal:acquireTokenFromNetworkStart",
HANDLE_REDIRECT_START: "msal:handleRedirectStart",
HANDLE_REDIRECT_END: "msal:handleRedirectEnd",
POPUP_OPENED: "msal:popupOpened",
LOGOUT_START: "msal:logoutStart",
LOGOUT_SUCCESS: "msal:logoutSuccess",
LOGOUT_FAILURE: "msal:logoutFailure",
LOGOUT_END: "msal:logoutEnd",
RESTORE_FROM_BFCACHE: "msal:restoreFromBFCache",
BROKER_CONNECTION_ESTABLISHED: "msal:brokerConnectionEstablished",
} as const;
export type EventType = (typeof EventType)[keyof typeof EventType];