@nativelement/capacitor-msal-entra 0.0.0-stage → 1.0.1

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.
@@ -0,0 +1,202 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+ var msalBrowser = require('@azure/msal-browser');
5
+
6
+ const MsalAuth = core.registerPlugin('MsalAuth', {
7
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MsalAuthWeb()),
8
+ });
9
+
10
+ const CONFIG_PATH = 'assets/msal_config.json';
11
+ /**
12
+ * Web/PWA implementation backed by `@azure/msal-browser`, kept behind the
13
+ * same `MsalAuthPlugin` contract the native iOS/Android implementations use
14
+ * so callers (see `home.page.ts`, `auth.interceptor.ts`) don't need
15
+ * platform-specific branches.
16
+ *
17
+ * Interactive sign-in/sign-out use msal-browser's *redirect* APIs
18
+ * (`loginRedirect`/`logoutRedirect`), not popups. Microsoft's own MSAL.js
19
+ * guidance is that popups are "unreliable in Safari and mobile browsers due
20
+ * to popup blocker and gesture constraints," while redirect is "the most
21
+ * reliable interaction type across browsers, including Safari and mobile
22
+ * browsers" - the deciding factor for a PWA target.
23
+ *
24
+ * The tradeoff: `loginRedirect()`/`logoutRedirect()` navigate the browser
25
+ * away before their promises would otherwise resolve, so `signIn()` and
26
+ * `signOut({ clearBrowserSession: true })` below deliberately never resolve
27
+ * on web - unlike native, where the OS browser overlay returns control to
28
+ * the same JS context. The signed-in result is instead recovered on the
29
+ * *next* page load, once `handleRedirectPromise()` has processed it during
30
+ * initialization (see `createInstance()`). Callers must not block UI on
31
+ * `signIn()`'s promise settling on web; they should instead call
32
+ * `getAccount()` on app startup to pick up a just-completed redirect.
33
+ */
34
+ class MsalAuthWeb extends core.WebPlugin {
35
+ constructor() {
36
+ super(...arguments);
37
+ this.initPromise = null;
38
+ }
39
+ async signIn(options) {
40
+ var _a;
41
+ const pca = await this.getInstance();
42
+ try {
43
+ await pca.loginRedirect({
44
+ scopes: (_a = options.scopes) !== null && _a !== void 0 ? _a : [],
45
+ domainHint: options.domainHint,
46
+ prompt: options.prompt,
47
+ });
48
+ }
49
+ catch (error) {
50
+ throw this.rejection('SIGN_IN_FAILED', this.messageOf(error));
51
+ }
52
+ // Unreachable in practice: loginRedirect() above navigates the page away
53
+ // first. Nothing after this point runs in this JS context.
54
+ return new Promise(() => undefined);
55
+ }
56
+ async acquireTokenSilent(options) {
57
+ var _a, _b;
58
+ const pca = await this.getInstance();
59
+ const account = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0];
60
+ if (!account) {
61
+ throw this.rejection('UI_REQUIRED', 'No cached account - call signIn() first.');
62
+ }
63
+ try {
64
+ const result = await pca.acquireTokenSilent({ account, scopes: (_b = options.scopes) !== null && _b !== void 0 ? _b : [] });
65
+ return this.toResult(result);
66
+ }
67
+ catch (error) {
68
+ if (error instanceof msalBrowser.InteractionRequiredAuthError) {
69
+ throw this.rejection('UI_REQUIRED', error.message);
70
+ }
71
+ throw this.rejection('SILENT_FAILED', this.messageOf(error));
72
+ }
73
+ }
74
+ async getAccount() {
75
+ var _a, _b;
76
+ const pca = await this.getInstance();
77
+ const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : null;
78
+ return { value: account ? this.toAccountInfo(account) : null };
79
+ }
80
+ async signOut(options) {
81
+ var _a, _b;
82
+ const pca = await this.getInstance();
83
+ const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : undefined;
84
+ try {
85
+ if (options === null || options === void 0 ? void 0 : options.clearBrowserSession) {
86
+ // Ends the Entra browser SSO session too, not just the local cache -
87
+ // like signIn() above, this navigates away and never returns here.
88
+ await pca.logoutRedirect({ account });
89
+ return new Promise(() => undefined);
90
+ }
91
+ // Local-only sign-out: clears this account's cached tokens without any
92
+ // network call or navigation, matching native signOut()'s default
93
+ // "local cache only" behavior.
94
+ await pca.clearCache({ account });
95
+ }
96
+ catch (error) {
97
+ throw this.rejection('SIGN_OUT_FAILED', this.messageOf(error));
98
+ }
99
+ }
100
+ async getInstance() {
101
+ if (!this.initPromise) {
102
+ // Memoize per page load, but let a failed attempt be retried instead
103
+ // of permanently poisoning every later call with the same rejection.
104
+ this.initPromise = this.createInstance().catch((error) => {
105
+ this.initPromise = null;
106
+ throw error;
107
+ });
108
+ }
109
+ return this.initPromise;
110
+ }
111
+ async createInstance() {
112
+ var _a, _b, _c;
113
+ const config = await this.loadConfig();
114
+ const redirectUri = (_a = config.redirect_uri) !== null && _a !== void 0 ? _a : window.location.origin;
115
+ const pca = await msalBrowser.createStandardPublicClientApplication({
116
+ auth: {
117
+ clientId: config.client_id,
118
+ authority: config.authority_url,
119
+ knownAuthorities: (_b = config.known_authorities) !== null && _b !== void 0 ? _b : [],
120
+ redirectUri,
121
+ postLogoutRedirectUri: (_c = config.post_logout_redirect_uri) !== null && _c !== void 0 ? _c : redirectUri,
122
+ },
123
+ cache: {
124
+ // localStorage (not the sessionStorage default) so a signed-in user
125
+ // stays signed in across app relaunches/tab closes, matching native
126
+ // MSAL's persistent Keychain/EncryptedSharedPreferences cache - the
127
+ // PWA equivalent of "not native" would otherwise re-prompt every
128
+ // fresh tab, unlike iOS/Android.
129
+ cacheLocation: msalBrowser.BrowserCacheLocation.LocalStorage,
130
+ },
131
+ });
132
+ // Must run exactly once per page load, before any other account-reading
133
+ // call - this is what completes the loginRedirect()/logoutRedirect()
134
+ // round trip from the previous page load, if one is in flight. A failure
135
+ // here (e.g. the user denied consent on the Entra page) shouldn't break
136
+ // the whole plugin instance - it's swallowed so getAccount() simply comes
137
+ // back null and the app can prompt sign-in again, mirroring how a
138
+ // rejected native signIn() call leaves the app just as unauthenticated.
139
+ try {
140
+ const redirectResult = await pca.handleRedirectPromise();
141
+ if (redirectResult === null || redirectResult === void 0 ? void 0 : redirectResult.account) {
142
+ pca.setActiveAccount(redirectResult.account);
143
+ }
144
+ }
145
+ catch (error) {
146
+ console.warn('[MsalAuthWeb] handleRedirectPromise() failed', error);
147
+ }
148
+ return pca;
149
+ }
150
+ async loadConfig() {
151
+ const help = `Add a web msal_config.json at "${CONFIG_PATH}" (e.g. src/assets/msal_config.json in an Ionic/Angular app) - see the plugin README's "Web / PWA setup" section.`;
152
+ let response;
153
+ try {
154
+ response = await fetch(CONFIG_PATH);
155
+ }
156
+ catch (error) {
157
+ throw this.rejection('NOT_INITIALIZED', `Could not load ${CONFIG_PATH}: ${this.messageOf(error)}. ${help}`);
158
+ }
159
+ if (!response.ok) {
160
+ throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} returned HTTP ${response.status}. ${help}`);
161
+ }
162
+ const config = (await response.json());
163
+ if (!config.client_id || !config.authority_url) {
164
+ throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} is missing client_id or authority_url. ${help}`);
165
+ }
166
+ return config;
167
+ }
168
+ toResult(result) {
169
+ var _a, _b;
170
+ return {
171
+ accessToken: result.accessToken,
172
+ idToken: result.idToken,
173
+ expiresOn: result.expiresOn ? result.expiresOn.getTime() : Date.now(),
174
+ // Local MSAL account identifier, not the raw `oid` claim - matches the
175
+ // native implementations' accountId semantics (see definitions.ts).
176
+ accountId: (_b = (_a = result.account) === null || _a === void 0 ? void 0 : _a.homeAccountId) !== null && _b !== void 0 ? _b : '',
177
+ scopes: result.scopes,
178
+ };
179
+ }
180
+ toAccountInfo(account) {
181
+ var _a, _b;
182
+ return {
183
+ accountId: account.homeAccountId,
184
+ username: (_a = account.username) !== null && _a !== void 0 ? _a : null,
185
+ idTokenClaims: (_b = account.idTokenClaims) !== null && _b !== void 0 ? _b : null,
186
+ };
187
+ }
188
+ rejection(code, message) {
189
+ return Object.assign(new Error(message), { code });
190
+ }
191
+ messageOf(error) {
192
+ return error instanceof Error ? error.message : String(error);
193
+ }
194
+ }
195
+
196
+ var web = /*#__PURE__*/Object.freeze({
197
+ __proto__: null,
198
+ MsalAuthWeb: MsalAuthWeb
199
+ });
200
+
201
+ exports.MsalAuth = MsalAuth;
202
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst MsalAuth = registerPlugin('MsalAuth', {\n web: () => import('./web').then((m) => new m.MsalAuthWeb()),\n});\nexport * from './definitions';\nexport { MsalAuth };\n","import { WebPlugin } from '@capacitor/core';\nimport { BrowserCacheLocation, InteractionRequiredAuthError, createStandardPublicClientApplication, } from '@azure/msal-browser';\nconst CONFIG_PATH = 'assets/msal_config.json';\n/**\n * Web/PWA implementation backed by `@azure/msal-browser`, kept behind the\n * same `MsalAuthPlugin` contract the native iOS/Android implementations use\n * so callers (see `home.page.ts`, `auth.interceptor.ts`) don't need\n * platform-specific branches.\n *\n * Interactive sign-in/sign-out use msal-browser's *redirect* APIs\n * (`loginRedirect`/`logoutRedirect`), not popups. Microsoft's own MSAL.js\n * guidance is that popups are \"unreliable in Safari and mobile browsers due\n * to popup blocker and gesture constraints,\" while redirect is \"the most\n * reliable interaction type across browsers, including Safari and mobile\n * browsers\" - the deciding factor for a PWA target.\n *\n * The tradeoff: `loginRedirect()`/`logoutRedirect()` navigate the browser\n * away before their promises would otherwise resolve, so `signIn()` and\n * `signOut({ clearBrowserSession: true })` below deliberately never resolve\n * on web - unlike native, where the OS browser overlay returns control to\n * the same JS context. The signed-in result is instead recovered on the\n * *next* page load, once `handleRedirectPromise()` has processed it during\n * initialization (see `createInstance()`). Callers must not block UI on\n * `signIn()`'s promise settling on web; they should instead call\n * `getAccount()` on app startup to pick up a just-completed redirect.\n */\nexport class MsalAuthWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.initPromise = null;\n }\n async signIn(options) {\n var _a;\n const pca = await this.getInstance();\n try {\n await pca.loginRedirect({\n scopes: (_a = options.scopes) !== null && _a !== void 0 ? _a : [],\n domainHint: options.domainHint,\n prompt: options.prompt,\n });\n }\n catch (error) {\n throw this.rejection('SIGN_IN_FAILED', this.messageOf(error));\n }\n // Unreachable in practice: loginRedirect() above navigates the page away\n // first. Nothing after this point runs in this JS context.\n return new Promise(() => undefined);\n }\n async acquireTokenSilent(options) {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0];\n if (!account) {\n throw this.rejection('UI_REQUIRED', 'No cached account - call signIn() first.');\n }\n try {\n const result = await pca.acquireTokenSilent({ account, scopes: (_b = options.scopes) !== null && _b !== void 0 ? _b : [] });\n return this.toResult(result);\n }\n catch (error) {\n if (error instanceof InteractionRequiredAuthError) {\n throw this.rejection('UI_REQUIRED', error.message);\n }\n throw this.rejection('SILENT_FAILED', this.messageOf(error));\n }\n }\n async getAccount() {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : null;\n return { value: account ? this.toAccountInfo(account) : null };\n }\n async signOut(options) {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : undefined;\n try {\n if (options === null || options === void 0 ? void 0 : options.clearBrowserSession) {\n // Ends the Entra browser SSO session too, not just the local cache -\n // like signIn() above, this navigates away and never returns here.\n await pca.logoutRedirect({ account });\n return new Promise(() => undefined);\n }\n // Local-only sign-out: clears this account's cached tokens without any\n // network call or navigation, matching native signOut()'s default\n // \"local cache only\" behavior.\n await pca.clearCache({ account });\n }\n catch (error) {\n throw this.rejection('SIGN_OUT_FAILED', this.messageOf(error));\n }\n }\n async getInstance() {\n if (!this.initPromise) {\n // Memoize per page load, but let a failed attempt be retried instead\n // of permanently poisoning every later call with the same rejection.\n this.initPromise = this.createInstance().catch((error) => {\n this.initPromise = null;\n throw error;\n });\n }\n return this.initPromise;\n }\n async createInstance() {\n var _a, _b, _c;\n const config = await this.loadConfig();\n const redirectUri = (_a = config.redirect_uri) !== null && _a !== void 0 ? _a : window.location.origin;\n const pca = await createStandardPublicClientApplication({\n auth: {\n clientId: config.client_id,\n authority: config.authority_url,\n knownAuthorities: (_b = config.known_authorities) !== null && _b !== void 0 ? _b : [],\n redirectUri,\n postLogoutRedirectUri: (_c = config.post_logout_redirect_uri) !== null && _c !== void 0 ? _c : redirectUri,\n },\n cache: {\n // localStorage (not the sessionStorage default) so a signed-in user\n // stays signed in across app relaunches/tab closes, matching native\n // MSAL's persistent Keychain/EncryptedSharedPreferences cache - the\n // PWA equivalent of \"not native\" would otherwise re-prompt every\n // fresh tab, unlike iOS/Android.\n cacheLocation: BrowserCacheLocation.LocalStorage,\n },\n });\n // Must run exactly once per page load, before any other account-reading\n // call - this is what completes the loginRedirect()/logoutRedirect()\n // round trip from the previous page load, if one is in flight. A failure\n // here (e.g. the user denied consent on the Entra page) shouldn't break\n // the whole plugin instance - it's swallowed so getAccount() simply comes\n // back null and the app can prompt sign-in again, mirroring how a\n // rejected native signIn() call leaves the app just as unauthenticated.\n try {\n const redirectResult = await pca.handleRedirectPromise();\n if (redirectResult === null || redirectResult === void 0 ? void 0 : redirectResult.account) {\n pca.setActiveAccount(redirectResult.account);\n }\n }\n catch (error) {\n console.warn('[MsalAuthWeb] handleRedirectPromise() failed', error);\n }\n return pca;\n }\n async loadConfig() {\n const help = `Add a web msal_config.json at \"${CONFIG_PATH}\" (e.g. src/assets/msal_config.json in an Ionic/Angular app) - see the plugin README's \"Web / PWA setup\" section.`;\n let response;\n try {\n response = await fetch(CONFIG_PATH);\n }\n catch (error) {\n throw this.rejection('NOT_INITIALIZED', `Could not load ${CONFIG_PATH}: ${this.messageOf(error)}. ${help}`);\n }\n if (!response.ok) {\n throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} returned HTTP ${response.status}. ${help}`);\n }\n const config = (await response.json());\n if (!config.client_id || !config.authority_url) {\n throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} is missing client_id or authority_url. ${help}`);\n }\n return config;\n }\n toResult(result) {\n var _a, _b;\n return {\n accessToken: result.accessToken,\n idToken: result.idToken,\n expiresOn: result.expiresOn ? result.expiresOn.getTime() : Date.now(),\n // Local MSAL account identifier, not the raw `oid` claim - matches the\n // native implementations' accountId semantics (see definitions.ts).\n accountId: (_b = (_a = result.account) === null || _a === void 0 ? void 0 : _a.homeAccountId) !== null && _b !== void 0 ? _b : '',\n scopes: result.scopes,\n };\n }\n toAccountInfo(account) {\n var _a, _b;\n return {\n accountId: account.homeAccountId,\n username: (_a = account.username) !== null && _a !== void 0 ? _a : null,\n idTokenClaims: (_b = account.idTokenClaims) !== null && _b !== void 0 ? _b : null,\n };\n }\n rejection(code, message) {\n return Object.assign(new Error(message), { code });\n }\n messageOf(error) {\n return error instanceof Error ? error.message : String(error);\n }\n}\n"],"names":["registerPlugin","WebPlugin","InteractionRequiredAuthError","createStandardPublicClientApplication","BrowserCacheLocation"],"mappings":"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"}
package/dist/plugin.js ADDED
@@ -0,0 +1,204 @@
1
+ var capacitorMsalEntraPlugin = (function (exports, core, msalBrowser) {
2
+ 'use strict';
3
+
4
+ const MsalAuth = core.registerPlugin('MsalAuth', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MsalAuthWeb()),
6
+ });
7
+
8
+ const CONFIG_PATH = 'assets/msal_config.json';
9
+ /**
10
+ * Web/PWA implementation backed by `@azure/msal-browser`, kept behind the
11
+ * same `MsalAuthPlugin` contract the native iOS/Android implementations use
12
+ * so callers (see `home.page.ts`, `auth.interceptor.ts`) don't need
13
+ * platform-specific branches.
14
+ *
15
+ * Interactive sign-in/sign-out use msal-browser's *redirect* APIs
16
+ * (`loginRedirect`/`logoutRedirect`), not popups. Microsoft's own MSAL.js
17
+ * guidance is that popups are "unreliable in Safari and mobile browsers due
18
+ * to popup blocker and gesture constraints," while redirect is "the most
19
+ * reliable interaction type across browsers, including Safari and mobile
20
+ * browsers" - the deciding factor for a PWA target.
21
+ *
22
+ * The tradeoff: `loginRedirect()`/`logoutRedirect()` navigate the browser
23
+ * away before their promises would otherwise resolve, so `signIn()` and
24
+ * `signOut({ clearBrowserSession: true })` below deliberately never resolve
25
+ * on web - unlike native, where the OS browser overlay returns control to
26
+ * the same JS context. The signed-in result is instead recovered on the
27
+ * *next* page load, once `handleRedirectPromise()` has processed it during
28
+ * initialization (see `createInstance()`). Callers must not block UI on
29
+ * `signIn()`'s promise settling on web; they should instead call
30
+ * `getAccount()` on app startup to pick up a just-completed redirect.
31
+ */
32
+ class MsalAuthWeb extends core.WebPlugin {
33
+ constructor() {
34
+ super(...arguments);
35
+ this.initPromise = null;
36
+ }
37
+ async signIn(options) {
38
+ var _a;
39
+ const pca = await this.getInstance();
40
+ try {
41
+ await pca.loginRedirect({
42
+ scopes: (_a = options.scopes) !== null && _a !== void 0 ? _a : [],
43
+ domainHint: options.domainHint,
44
+ prompt: options.prompt,
45
+ });
46
+ }
47
+ catch (error) {
48
+ throw this.rejection('SIGN_IN_FAILED', this.messageOf(error));
49
+ }
50
+ // Unreachable in practice: loginRedirect() above navigates the page away
51
+ // first. Nothing after this point runs in this JS context.
52
+ return new Promise(() => undefined);
53
+ }
54
+ async acquireTokenSilent(options) {
55
+ var _a, _b;
56
+ const pca = await this.getInstance();
57
+ const account = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0];
58
+ if (!account) {
59
+ throw this.rejection('UI_REQUIRED', 'No cached account - call signIn() first.');
60
+ }
61
+ try {
62
+ const result = await pca.acquireTokenSilent({ account, scopes: (_b = options.scopes) !== null && _b !== void 0 ? _b : [] });
63
+ return this.toResult(result);
64
+ }
65
+ catch (error) {
66
+ if (error instanceof msalBrowser.InteractionRequiredAuthError) {
67
+ throw this.rejection('UI_REQUIRED', error.message);
68
+ }
69
+ throw this.rejection('SILENT_FAILED', this.messageOf(error));
70
+ }
71
+ }
72
+ async getAccount() {
73
+ var _a, _b;
74
+ const pca = await this.getInstance();
75
+ const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : null;
76
+ return { value: account ? this.toAccountInfo(account) : null };
77
+ }
78
+ async signOut(options) {
79
+ var _a, _b;
80
+ const pca = await this.getInstance();
81
+ const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : undefined;
82
+ try {
83
+ if (options === null || options === void 0 ? void 0 : options.clearBrowserSession) {
84
+ // Ends the Entra browser SSO session too, not just the local cache -
85
+ // like signIn() above, this navigates away and never returns here.
86
+ await pca.logoutRedirect({ account });
87
+ return new Promise(() => undefined);
88
+ }
89
+ // Local-only sign-out: clears this account's cached tokens without any
90
+ // network call or navigation, matching native signOut()'s default
91
+ // "local cache only" behavior.
92
+ await pca.clearCache({ account });
93
+ }
94
+ catch (error) {
95
+ throw this.rejection('SIGN_OUT_FAILED', this.messageOf(error));
96
+ }
97
+ }
98
+ async getInstance() {
99
+ if (!this.initPromise) {
100
+ // Memoize per page load, but let a failed attempt be retried instead
101
+ // of permanently poisoning every later call with the same rejection.
102
+ this.initPromise = this.createInstance().catch((error) => {
103
+ this.initPromise = null;
104
+ throw error;
105
+ });
106
+ }
107
+ return this.initPromise;
108
+ }
109
+ async createInstance() {
110
+ var _a, _b, _c;
111
+ const config = await this.loadConfig();
112
+ const redirectUri = (_a = config.redirect_uri) !== null && _a !== void 0 ? _a : window.location.origin;
113
+ const pca = await msalBrowser.createStandardPublicClientApplication({
114
+ auth: {
115
+ clientId: config.client_id,
116
+ authority: config.authority_url,
117
+ knownAuthorities: (_b = config.known_authorities) !== null && _b !== void 0 ? _b : [],
118
+ redirectUri,
119
+ postLogoutRedirectUri: (_c = config.post_logout_redirect_uri) !== null && _c !== void 0 ? _c : redirectUri,
120
+ },
121
+ cache: {
122
+ // localStorage (not the sessionStorage default) so a signed-in user
123
+ // stays signed in across app relaunches/tab closes, matching native
124
+ // MSAL's persistent Keychain/EncryptedSharedPreferences cache - the
125
+ // PWA equivalent of "not native" would otherwise re-prompt every
126
+ // fresh tab, unlike iOS/Android.
127
+ cacheLocation: msalBrowser.BrowserCacheLocation.LocalStorage,
128
+ },
129
+ });
130
+ // Must run exactly once per page load, before any other account-reading
131
+ // call - this is what completes the loginRedirect()/logoutRedirect()
132
+ // round trip from the previous page load, if one is in flight. A failure
133
+ // here (e.g. the user denied consent on the Entra page) shouldn't break
134
+ // the whole plugin instance - it's swallowed so getAccount() simply comes
135
+ // back null and the app can prompt sign-in again, mirroring how a
136
+ // rejected native signIn() call leaves the app just as unauthenticated.
137
+ try {
138
+ const redirectResult = await pca.handleRedirectPromise();
139
+ if (redirectResult === null || redirectResult === void 0 ? void 0 : redirectResult.account) {
140
+ pca.setActiveAccount(redirectResult.account);
141
+ }
142
+ }
143
+ catch (error) {
144
+ console.warn('[MsalAuthWeb] handleRedirectPromise() failed', error);
145
+ }
146
+ return pca;
147
+ }
148
+ async loadConfig() {
149
+ const help = `Add a web msal_config.json at "${CONFIG_PATH}" (e.g. src/assets/msal_config.json in an Ionic/Angular app) - see the plugin README's "Web / PWA setup" section.`;
150
+ let response;
151
+ try {
152
+ response = await fetch(CONFIG_PATH);
153
+ }
154
+ catch (error) {
155
+ throw this.rejection('NOT_INITIALIZED', `Could not load ${CONFIG_PATH}: ${this.messageOf(error)}. ${help}`);
156
+ }
157
+ if (!response.ok) {
158
+ throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} returned HTTP ${response.status}. ${help}`);
159
+ }
160
+ const config = (await response.json());
161
+ if (!config.client_id || !config.authority_url) {
162
+ throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} is missing client_id or authority_url. ${help}`);
163
+ }
164
+ return config;
165
+ }
166
+ toResult(result) {
167
+ var _a, _b;
168
+ return {
169
+ accessToken: result.accessToken,
170
+ idToken: result.idToken,
171
+ expiresOn: result.expiresOn ? result.expiresOn.getTime() : Date.now(),
172
+ // Local MSAL account identifier, not the raw `oid` claim - matches the
173
+ // native implementations' accountId semantics (see definitions.ts).
174
+ accountId: (_b = (_a = result.account) === null || _a === void 0 ? void 0 : _a.homeAccountId) !== null && _b !== void 0 ? _b : '',
175
+ scopes: result.scopes,
176
+ };
177
+ }
178
+ toAccountInfo(account) {
179
+ var _a, _b;
180
+ return {
181
+ accountId: account.homeAccountId,
182
+ username: (_a = account.username) !== null && _a !== void 0 ? _a : null,
183
+ idTokenClaims: (_b = account.idTokenClaims) !== null && _b !== void 0 ? _b : null,
184
+ };
185
+ }
186
+ rejection(code, message) {
187
+ return Object.assign(new Error(message), { code });
188
+ }
189
+ messageOf(error) {
190
+ return error instanceof Error ? error.message : String(error);
191
+ }
192
+ }
193
+
194
+ var web = /*#__PURE__*/Object.freeze({
195
+ __proto__: null,
196
+ MsalAuthWeb: MsalAuthWeb
197
+ });
198
+
199
+ exports.MsalAuth = MsalAuth;
200
+
201
+ return exports;
202
+
203
+ })({}, capacitorExports, msal);
204
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst MsalAuth = registerPlugin('MsalAuth', {\n web: () => import('./web').then((m) => new m.MsalAuthWeb()),\n});\nexport * from './definitions';\nexport { MsalAuth };\n","import { WebPlugin } from '@capacitor/core';\nimport { BrowserCacheLocation, InteractionRequiredAuthError, createStandardPublicClientApplication, } from '@azure/msal-browser';\nconst CONFIG_PATH = 'assets/msal_config.json';\n/**\n * Web/PWA implementation backed by `@azure/msal-browser`, kept behind the\n * same `MsalAuthPlugin` contract the native iOS/Android implementations use\n * so callers (see `home.page.ts`, `auth.interceptor.ts`) don't need\n * platform-specific branches.\n *\n * Interactive sign-in/sign-out use msal-browser's *redirect* APIs\n * (`loginRedirect`/`logoutRedirect`), not popups. Microsoft's own MSAL.js\n * guidance is that popups are \"unreliable in Safari and mobile browsers due\n * to popup blocker and gesture constraints,\" while redirect is \"the most\n * reliable interaction type across browsers, including Safari and mobile\n * browsers\" - the deciding factor for a PWA target.\n *\n * The tradeoff: `loginRedirect()`/`logoutRedirect()` navigate the browser\n * away before their promises would otherwise resolve, so `signIn()` and\n * `signOut({ clearBrowserSession: true })` below deliberately never resolve\n * on web - unlike native, where the OS browser overlay returns control to\n * the same JS context. The signed-in result is instead recovered on the\n * *next* page load, once `handleRedirectPromise()` has processed it during\n * initialization (see `createInstance()`). Callers must not block UI on\n * `signIn()`'s promise settling on web; they should instead call\n * `getAccount()` on app startup to pick up a just-completed redirect.\n */\nexport class MsalAuthWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.initPromise = null;\n }\n async signIn(options) {\n var _a;\n const pca = await this.getInstance();\n try {\n await pca.loginRedirect({\n scopes: (_a = options.scopes) !== null && _a !== void 0 ? _a : [],\n domainHint: options.domainHint,\n prompt: options.prompt,\n });\n }\n catch (error) {\n throw this.rejection('SIGN_IN_FAILED', this.messageOf(error));\n }\n // Unreachable in practice: loginRedirect() above navigates the page away\n // first. Nothing after this point runs in this JS context.\n return new Promise(() => undefined);\n }\n async acquireTokenSilent(options) {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0];\n if (!account) {\n throw this.rejection('UI_REQUIRED', 'No cached account - call signIn() first.');\n }\n try {\n const result = await pca.acquireTokenSilent({ account, scopes: (_b = options.scopes) !== null && _b !== void 0 ? _b : [] });\n return this.toResult(result);\n }\n catch (error) {\n if (error instanceof InteractionRequiredAuthError) {\n throw this.rejection('UI_REQUIRED', error.message);\n }\n throw this.rejection('SILENT_FAILED', this.messageOf(error));\n }\n }\n async getAccount() {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : null;\n return { value: account ? this.toAccountInfo(account) : null };\n }\n async signOut(options) {\n var _a, _b;\n const pca = await this.getInstance();\n const account = (_b = (_a = pca.getActiveAccount()) !== null && _a !== void 0 ? _a : pca.getAllAccounts()[0]) !== null && _b !== void 0 ? _b : undefined;\n try {\n if (options === null || options === void 0 ? void 0 : options.clearBrowserSession) {\n // Ends the Entra browser SSO session too, not just the local cache -\n // like signIn() above, this navigates away and never returns here.\n await pca.logoutRedirect({ account });\n return new Promise(() => undefined);\n }\n // Local-only sign-out: clears this account's cached tokens without any\n // network call or navigation, matching native signOut()'s default\n // \"local cache only\" behavior.\n await pca.clearCache({ account });\n }\n catch (error) {\n throw this.rejection('SIGN_OUT_FAILED', this.messageOf(error));\n }\n }\n async getInstance() {\n if (!this.initPromise) {\n // Memoize per page load, but let a failed attempt be retried instead\n // of permanently poisoning every later call with the same rejection.\n this.initPromise = this.createInstance().catch((error) => {\n this.initPromise = null;\n throw error;\n });\n }\n return this.initPromise;\n }\n async createInstance() {\n var _a, _b, _c;\n const config = await this.loadConfig();\n const redirectUri = (_a = config.redirect_uri) !== null && _a !== void 0 ? _a : window.location.origin;\n const pca = await createStandardPublicClientApplication({\n auth: {\n clientId: config.client_id,\n authority: config.authority_url,\n knownAuthorities: (_b = config.known_authorities) !== null && _b !== void 0 ? _b : [],\n redirectUri,\n postLogoutRedirectUri: (_c = config.post_logout_redirect_uri) !== null && _c !== void 0 ? _c : redirectUri,\n },\n cache: {\n // localStorage (not the sessionStorage default) so a signed-in user\n // stays signed in across app relaunches/tab closes, matching native\n // MSAL's persistent Keychain/EncryptedSharedPreferences cache - the\n // PWA equivalent of \"not native\" would otherwise re-prompt every\n // fresh tab, unlike iOS/Android.\n cacheLocation: BrowserCacheLocation.LocalStorage,\n },\n });\n // Must run exactly once per page load, before any other account-reading\n // call - this is what completes the loginRedirect()/logoutRedirect()\n // round trip from the previous page load, if one is in flight. A failure\n // here (e.g. the user denied consent on the Entra page) shouldn't break\n // the whole plugin instance - it's swallowed so getAccount() simply comes\n // back null and the app can prompt sign-in again, mirroring how a\n // rejected native signIn() call leaves the app just as unauthenticated.\n try {\n const redirectResult = await pca.handleRedirectPromise();\n if (redirectResult === null || redirectResult === void 0 ? void 0 : redirectResult.account) {\n pca.setActiveAccount(redirectResult.account);\n }\n }\n catch (error) {\n console.warn('[MsalAuthWeb] handleRedirectPromise() failed', error);\n }\n return pca;\n }\n async loadConfig() {\n const help = `Add a web msal_config.json at \"${CONFIG_PATH}\" (e.g. src/assets/msal_config.json in an Ionic/Angular app) - see the plugin README's \"Web / PWA setup\" section.`;\n let response;\n try {\n response = await fetch(CONFIG_PATH);\n }\n catch (error) {\n throw this.rejection('NOT_INITIALIZED', `Could not load ${CONFIG_PATH}: ${this.messageOf(error)}. ${help}`);\n }\n if (!response.ok) {\n throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} returned HTTP ${response.status}. ${help}`);\n }\n const config = (await response.json());\n if (!config.client_id || !config.authority_url) {\n throw this.rejection('NOT_INITIALIZED', `${CONFIG_PATH} is missing client_id or authority_url. ${help}`);\n }\n return config;\n }\n toResult(result) {\n var _a, _b;\n return {\n accessToken: result.accessToken,\n idToken: result.idToken,\n expiresOn: result.expiresOn ? result.expiresOn.getTime() : Date.now(),\n // Local MSAL account identifier, not the raw `oid` claim - matches the\n // native implementations' accountId semantics (see definitions.ts).\n accountId: (_b = (_a = result.account) === null || _a === void 0 ? void 0 : _a.homeAccountId) !== null && _b !== void 0 ? _b : '',\n scopes: result.scopes,\n };\n }\n toAccountInfo(account) {\n var _a, _b;\n return {\n accountId: account.homeAccountId,\n username: (_a = account.username) !== null && _a !== void 0 ? _a : null,\n idTokenClaims: (_b = account.idTokenClaims) !== null && _b !== void 0 ? _b : null,\n };\n }\n rejection(code, message) {\n return Object.assign(new Error(message), { code });\n }\n messageOf(error) {\n return error instanceof Error ? error.message : String(error);\n }\n}\n"],"names":["registerPlugin","WebPlugin","InteractionRequiredAuthError","createStandardPublicClientApplication","BrowserCacheLocation"],"mappings":";;;AACK,UAAC,QAAQ,GAAGA,mBAAc,CAAC,UAAU,EAAE;IAC5C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,CAAC;;ICDD,MAAM,WAAW,GAAG,yBAAyB;IAC7C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACO,MAAM,WAAW,SAASC,cAAS,CAAC;IAC3C,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;IAC3B,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI;IAC/B,IAAI;IACJ,IAAI,MAAM,MAAM,CAAC,OAAO,EAAE;IAC1B,QAAQ,IAAI,EAAE;IACd,QAAQ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;IAC5C,QAAQ,IAAI;IACZ,YAAY,MAAM,GAAG,CAAC,aAAa,CAAC;IACpC,gBAAgB,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE;IACjF,gBAAgB,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9C,gBAAgB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtC,aAAa,CAAC;IACd,QAAQ;IACR,QAAQ,OAAO,KAAK,EAAE;IACtB,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzE,QAAQ;IACR;IACA;IACA,QAAQ,OAAO,IAAI,OAAO,CAAC,MAAM,SAAS,CAAC;IAC3C,IAAI;IACJ,IAAI,MAAM,kBAAkB,CAAC,OAAO,EAAE;IACtC,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;IAC5C,QAAQ,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,gBAAgB,EAAE,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IAC9G,QAAQ,IAAI,CAAC,OAAO,EAAE;IACtB,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,0CAA0C,CAAC;IAC3F,QAAQ;IACR,QAAQ,IAAI;IACZ,YAAY,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;IACvI,YAAY,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;IACxC,QAAQ;IACR,QAAQ,OAAO,KAAK,EAAE;IACtB,YAAY,IAAI,KAAK,YAAYC,wCAA4B,EAAE;IAC/D,gBAAgB,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;IAClE,YAAY;IACZ,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACxE,QAAQ;IACR,IAAI;IACJ,IAAI,MAAM,UAAU,GAAG;IACvB,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;IAC5C,QAAQ,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,gBAAgB,EAAE,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI;IAC3J,QAAQ,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE;IACtE,IAAI;IACJ,IAAI,MAAM,OAAO,CAAC,OAAO,EAAE;IAC3B,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;IAC5C,QAAQ,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,gBAAgB,EAAE,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,SAAS;IAChK,QAAQ,IAAI;IACZ,YAAY,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,mBAAmB,EAAE;IAC/F;IACA;IACA,gBAAgB,MAAM,GAAG,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;IACrD,gBAAgB,OAAO,IAAI,OAAO,CAAC,MAAM,SAAS,CAAC;IACnD,YAAY;IACZ;IACA;IACA;IACA,YAAY,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IAC7C,QAAQ;IACR,QAAQ,OAAO,KAAK,EAAE;IACtB,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1E,QAAQ;IACR,IAAI;IACJ,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;IAC/B;IACA;IACA,YAAY,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK;IACtE,gBAAgB,IAAI,CAAC,WAAW,GAAG,IAAI;IACvC,gBAAgB,MAAM,KAAK;IAC3B,YAAY,CAAC,CAAC;IACd,QAAQ;IACR,QAAQ,OAAO,IAAI,CAAC,WAAW;IAC/B,IAAI;IACJ,IAAI,MAAM,cAAc,GAAG;IAC3B,QAAQ,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;IACtB,QAAQ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE;IAC9C,QAAQ,MAAM,WAAW,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM;IAC9G,QAAQ,MAAM,GAAG,GAAG,MAAMC,iDAAqC,CAAC;IAChE,YAAY,IAAI,EAAE;IAClB,gBAAgB,QAAQ,EAAE,MAAM,CAAC,SAAS;IAC1C,gBAAgB,SAAS,EAAE,MAAM,CAAC,aAAa;IAC/C,gBAAgB,gBAAgB,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,iBAAiB,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,EAAE;IACrG,gBAAgB,WAAW;IAC3B,gBAAgB,qBAAqB,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,wBAAwB,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,WAAW;IAC1H,aAAa;IACb,YAAY,KAAK,EAAE;IACnB;IACA;IACA;IACA;IACA;IACA,gBAAgB,aAAa,EAAEC,gCAAoB,CAAC,YAAY;IAChE,aAAa;IACb,SAAS,CAAC;IACV;IACA;IACA;IACA;IACA;IACA;IACA;IACA,QAAQ,IAAI;IACZ,YAAY,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,qBAAqB,EAAE;IACpE,YAAY,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,cAAc,CAAC,OAAO,EAAE;IACxG,gBAAgB,GAAG,CAAC,gBAAgB,CAAC,cAAc,CAAC,OAAO,CAAC;IAC5D,YAAY;IACZ,QAAQ;IACR,QAAQ,OAAO,KAAK,EAAE;IACtB,YAAY,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,KAAK,CAAC;IAC/E,QAAQ;IACR,QAAQ,OAAO,GAAG;IAClB,IAAI;IACJ,IAAI,MAAM,UAAU,GAAG;IACvB,QAAQ,MAAM,IAAI,GAAG,CAAC,+BAA+B,EAAE,WAAW,CAAC,iHAAiH,CAAC;IACrL,QAAQ,IAAI,QAAQ;IACpB,QAAQ,IAAI;IACZ,YAAY,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC;IAC/C,QAAQ;IACR,QAAQ,OAAO,KAAK,EAAE;IACtB,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IACvH,QAAQ;IACR,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;IAC1B,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,EAAE,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/G,QAAQ;IACR,QAAQ,MAAM,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9C,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;IACxD,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,EAAE,WAAW,CAAC,wCAAwC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpH,QAAQ;IACR,QAAQ,OAAO,MAAM;IACrB,IAAI;IACJ,IAAI,QAAQ,CAAC,MAAM,EAAE;IACrB,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,OAAO;IACf,YAAY,WAAW,EAAE,MAAM,CAAC,WAAW;IAC3C,YAAY,OAAO,EAAE,MAAM,CAAC,OAAO;IACnC,YAAY,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;IACjF;IACA;IACA,YAAY,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,aAAa,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,EAAE;IAC7I,YAAY,MAAM,EAAE,MAAM,CAAC,MAAM;IACjC,SAAS;IACT,IAAI;IACJ,IAAI,aAAa,CAAC,OAAO,EAAE;IAC3B,QAAQ,IAAI,EAAE,EAAE,EAAE;IAClB,QAAQ,OAAO;IACf,YAAY,SAAS,EAAE,OAAO,CAAC,aAAa;IAC5C,YAAY,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI;IACnF,YAAY,aAAa,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,aAAa,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI;IAC7F,SAAS;IACT,IAAI;IACJ,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE;IAC7B,QAAQ,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;IAC1D,IAAI;IACJ,IAAI,SAAS,CAAC,KAAK,EAAE;IACrB,QAAQ,OAAO,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;IACrE,IAAI;IACJ;;;;;;;;;;;"}