@vertesia/ui 1.6.0-dev.20261004.085740Z → 1.6.0-dev.20261009.095813Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/lib/boot/vite.d.ts +3 -0
- package/lib/boot/vite.d.ts.map +1 -1
- package/lib/boot/vite.js +12 -0
- package/lib/boot/vite.js.map +1 -1
- package/lib/core/components/shadcn/button.d.ts +1 -0
- package/lib/core/components/shadcn/button.d.ts.map +1 -1
- package/lib/core/components/shadcn/button.js +2 -2
- package/lib/core/components/shadcn/button.js.map +1 -1
- package/lib/core/components/shadcn/selectBox.d.ts.map +1 -1
- package/lib/core/components/shadcn/selectBox.js +2 -2
- package/lib/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/core/components/shadcn/tabs.d.ts +2 -1
- package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/core/components/shadcn/tabs.js +6 -4
- package/lib/core/components/shadcn/tabs.js.map +1 -1
- package/lib/env/index.d.ts +9 -1
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +1 -1
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.js +16 -10
- package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts +7 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.js +17 -16
- package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +2 -253
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts +1 -3
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js +2 -8
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/agentMarkdownStyles.d.ts +4 -0
- package/lib/features/agent/chat/ModernAgentOutput/agentMarkdownStyles.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/agentMarkdownStyles.js +248 -0
- package/lib/features/agent/chat/ModernAgentOutput/agentMarkdownStyles.js.map +1 -0
- package/lib/features/media-viewer/ImagePanel.d.ts +1 -1
- package/lib/features/media-viewer/ImagePanel.d.ts.map +1 -1
- package/lib/features/media-viewer/ImagePanel.js +40 -10
- package/lib/features/media-viewer/ImagePanel.js.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.js +1 -1
- package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
- package/lib/i18n/locales/ar.json +15 -0
- package/lib/i18n/locales/de.json +15 -0
- package/lib/i18n/locales/en.json +15 -0
- package/lib/i18n/locales/es.json +15 -0
- package/lib/i18n/locales/fr.json +15 -0
- package/lib/i18n/locales/it.json +15 -0
- package/lib/i18n/locales/ja.json +15 -0
- package/lib/i18n/locales/ko.json +15 -0
- package/lib/i18n/locales/pt.json +15 -0
- package/lib/i18n/locales/ru.json +15 -0
- package/lib/i18n/locales/tr.json +15 -0
- package/lib/i18n/locales/zh-TW.json +15 -0
- package/lib/i18n/locales/zh.json +15 -0
- package/lib/session/auth/composable.d.ts +1 -5
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +1 -10
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/session/auth/firebase.d.ts.map +1 -1
- package/lib/session/auth/firebase.js +8 -5
- package/lib/session/auth/firebase.js.map +1 -1
- package/lib/session/auth/oauth.d.ts.map +1 -1
- package/lib/session/auth/oauth.js +43 -17
- package/lib/session/auth/oauth.js.map +1 -1
- package/lib/session/auth/vertesiaHosts.d.ts +0 -40
- package/lib/session/auth/vertesiaHosts.d.ts.map +1 -1
- package/lib/session/auth/vertesiaHosts.js +2 -45
- package/lib/session/auth/vertesiaHosts.js.map +1 -1
- package/lib/session/index.d.ts +1 -1
- package/lib/session/index.d.ts.map +1 -1
- package/lib/session/index.js +1 -1
- package/lib/session/index.js.map +1 -1
- package/lib/session/scopeSelection.d.ts +4 -0
- package/lib/session/scopeSelection.d.ts.map +1 -1
- package/lib/session/scopeSelection.js +11 -0
- package/lib/session/scopeSelection.js.map +1 -1
- package/lib/shell/AuthScreenPreview.d.ts.map +1 -1
- package/lib/shell/AuthScreenPreview.js +1 -0
- package/lib/shell/AuthScreenPreview.js.map +1 -1
- package/lib/shell/login/SignInFlow.d.ts +3 -1
- package/lib/shell/login/SignInFlow.d.ts.map +1 -1
- package/lib/shell/login/SignInFlow.js +13 -4
- package/lib/shell/login/SignInFlow.js.map +1 -1
- package/lib/shell/login/SignInIcons.d.ts.map +1 -1
- package/lib/shell/login/SignInIcons.js +2 -1
- package/lib/shell/login/SignInIcons.js.map +1 -1
- package/lib/shell/login/SignInPasswordStep.d.ts +9 -0
- package/lib/shell/login/SignInPasswordStep.d.ts.map +1 -0
- package/lib/shell/login/SignInPasswordStep.js +58 -0
- package/lib/shell/login/SignInPasswordStep.js.map +1 -0
- package/lib/shell/login/SignInPrimitives.d.ts +13 -0
- package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
- package/lib/shell/login/SignInPrimitives.js +11 -1
- package/lib/shell/login/SignInPrimitives.js.map +1 -1
- package/lib/shell/login/SignInProvidersStep.d.ts +3 -1
- package/lib/shell/login/SignInProvidersStep.d.ts.map +1 -1
- package/lib/shell/login/SignInProvidersStep.js +4 -2
- package/lib/shell/login/SignInProvidersStep.js.map +1 -1
- package/lib/shell/login/SignInReturningStep.d.ts +3 -1
- package/lib/shell/login/SignInReturningStep.d.ts.map +1 -1
- package/lib/shell/login/SignInReturningStep.js +18 -8
- package/lib/shell/login/SignInReturningStep.js.map +1 -1
- package/lib/shell/login/SignInTenantStep.d.ts +3 -1
- package/lib/shell/login/SignInTenantStep.d.ts.map +1 -1
- package/lib/shell/login/SignInTenantStep.js +2 -2
- package/lib/shell/login/SignInTenantStep.js.map +1 -1
- package/lib/shell/login/SignInWithProviderButton.d.ts +5 -3
- package/lib/shell/login/SignInWithProviderButton.d.ts.map +1 -1
- package/lib/shell/login/SignInWithProviderButton.js +8 -7
- package/lib/shell/login/SignInWithProviderButton.js.map +1 -1
- package/lib/shell/login/SigninScreen.d.ts.map +1 -1
- package/lib/shell/login/SigninScreen.js +9 -3
- package/lib/shell/login/SigninScreen.js.map +1 -1
- package/lib/shell/login/signInUtils.d.ts +24 -4
- package/lib/shell/login/signInUtils.d.ts.map +1 -1
- package/lib/shell/login/signInUtils.js +53 -1
- package/lib/shell/login/signInUtils.js.map +1 -1
- package/lib/vertesia-ui-boot.js.map +1 -1
- package/lib/vertesia-ui-core.js +42 -42
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +574 -589
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.1NWiB6fw.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.1NWiB6fw.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.6Ozlf6Ks.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.6Ozlf6Ks.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.AttJpg8U.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.AttJpg8U.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.BI_xdp49.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.BI_xdp49.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.C-2EEX6w.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.C-2EEX6w.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.CAmo54FO.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.CAmo54FO.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.CbBzmHNP.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.CbBzmHNP.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DZgTzkIg.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DZgTzkIg.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DZsITxq5.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DZsITxq5.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.Dbf2GHth.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.Dbf2GHth.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.js +2 -2
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-i18n.lleWnH5n.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.lleWnH5n.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.wG_XSkbr.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.wG_XSkbr.chunk.js.map +1 -0
- package/lib/vertesia-ui-layout.js +15 -15
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +40 -40
- package/lib/vertesia-ui-rich-text.js.map +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +54 -47
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +47 -47
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +20 -20
- package/src/boot/vite.ts +15 -0
- package/src/core/components/shadcn/button.tsx +3 -2
- package/src/core/components/shadcn/selectBox.tsx +12 -4
- package/src/core/components/shadcn/tabs.tsx +9 -3
- package/src/css/index.css +1 -1
- package/src/css/typography.css +111 -88
- package/src/env/index.ts +10 -3
- package/src/features/agent/chat/AgentRequestInputOverlay.tsx +73 -34
- package/src/features/agent/chat/AskUserWidget.tsx +225 -206
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +2 -253
- package/src/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.tsx +2 -8
- package/src/features/agent/chat/ModernAgentOutput/agentMarkdownStyles.ts +248 -0
- package/src/features/media-viewer/ImagePanel.tsx +51 -10
- package/src/features/store/types/IntakePolicyEditor.tsx +2 -1
- package/src/i18n/locales/ar.json +15 -0
- package/src/i18n/locales/de.json +15 -0
- package/src/i18n/locales/en.json +15 -0
- package/src/i18n/locales/es.json +15 -0
- package/src/i18n/locales/fr.json +15 -0
- package/src/i18n/locales/it.json +15 -0
- package/src/i18n/locales/ja.json +15 -0
- package/src/i18n/locales/ko.json +15 -0
- package/src/i18n/locales/pt.json +15 -0
- package/src/i18n/locales/ru.json +15 -0
- package/src/i18n/locales/tr.json +15 -0
- package/src/i18n/locales/zh-TW.json +15 -0
- package/src/i18n/locales/zh.json +15 -0
- package/src/session/auth/composable.ts +1 -11
- package/src/session/auth/firebase.ts +9 -6
- package/src/session/auth/oauth.ts +47 -16
- package/src/session/auth/vertesiaHosts.ts +2 -47
- package/src/session/index.ts +1 -1
- package/src/session/scopeSelection.ts +13 -0
- package/src/shell/AuthScreenPreview.tsx +1 -0
- package/src/shell/login/SignInFlow.tsx +23 -2
- package/src/shell/login/SignInIcons.tsx +2 -1
- package/src/shell/login/SignInPasswordStep.tsx +103 -0
- package/src/shell/login/SignInPrimitives.tsx +53 -1
- package/src/shell/login/SignInProvidersStep.tsx +8 -4
- package/src/shell/login/SignInReturningStep.tsx +20 -8
- package/src/shell/login/SignInTenantStep.tsx +6 -2
- package/src/shell/login/SignInWithProviderButton.tsx +11 -7
- package/src/shell/login/SigninScreen.tsx +8 -3
- package/src/shell/login/signInUtils.ts +68 -8
- package/lib/vertesia-ui-i18n.BCPusS2_.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.BCPusS2_.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.BHWlHchf.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.BHWlHchf.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.BkNx8SZu.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.BkNx8SZu.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.C1LasLrO.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.C1LasLrO.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.D8PQ5yKU.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.D8PQ5yKU.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.DUtVV1Bq.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.DUtVV1Bq.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.DgA36_k5.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.DgA36_k5.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.DmG-fjjZ.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.DmG-fjjZ.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.DreWvQIk.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.DreWvQIk.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.Pp8Tj48d.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.Pp8Tj48d.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.gais--x5.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.gais--x5.chunk.js.map +0 -1
- package/lib/vertesia-ui-i18n.xkqaKpY_.chunk.js +0 -5
- package/lib/vertesia-ui-i18n.xkqaKpY_.chunk.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertesia-ui-router.js","names":["_jsx","_jsx","_jsx","_jsx","_jsxs","_jsx","_jsx","_jsx","_jsx"],"sources":["router/PathWithParams.js","router/path.js","router/HistoryNavigator.js","router/FixLinks.js","router/PathMatcher.js","router/Router.js","router/Nav.js","router/RouteComponent.js","router/NestedNavigationContext.js","router/Route404.js","router/NestedRouterProvider.js","router/Redirect.js","router/RouterProvider.js"],"sourcesContent":["export class PathWithParams {\n path;\n params;\n hash;\n constructor(path) {\n let i = path.lastIndexOf('#');\n if (i > -1) {\n this.hash = path.substring(i);\n path = path.substring(0, i);\n }\n else {\n this.hash = '';\n }\n i = path.indexOf('?');\n if (i > -1) {\n this.path = path.substring(0, i);\n this.params = new URLSearchParams(path.substring(i + 1));\n }\n else {\n this.path = path;\n this.params = new URLSearchParams();\n }\n }\n add(params) {\n for (const [key, value] of Object.entries(params)) {\n this.params.set(key, value);\n }\n return this;\n }\n toString() {\n return `${this.path}?${this.params.toString()}${this.hash}`;\n }\n}\n//# sourceMappingURL=PathWithParams.js.map","export function isRootPath(path) {\n return path === '/' || path === '';\n}\nexport function joinPath(path1, path2) {\n if (path1.endsWith('/') && path2.startsWith('/')) {\n path2 = path1 + path2.substring(1);\n }\n else if (path1.endsWith('/')) {\n path2 = path1 + path2;\n }\n else if (path2.startsWith('/')) {\n path2 = path1 + path2;\n }\n else {\n path2 = `${path1}/${path2}`;\n }\n return path2;\n}\n/**\n * The mount base path from an explicit `<base href>` element, or `''` when there is none.\n *\n * Apps served under a deep gateway mount carry `<base href=\"/tenants/.../app/\">`, injected at serve\n * time. The router otherwise resolves absolute routes against the origin, which collapses the URL\n * off the mount (and breaks in-app links). This returns the base pathname without a trailing slash\n * so {@link withMountBasename} can keep navigation under the mount and {@link stripMountBasename}\n * can match routes app-relative. The Studio UI has no `<base>` element, so this returns `''` and\n * every caller becomes a no-op there.\n */\nexport function getMountBasename() {\n if (typeof document === 'undefined')\n return '';\n const base = document.querySelector('base[href]');\n if (!base)\n return '';\n try {\n return new URL(base.href, document.URL).pathname.replace(/\\/+$/, '');\n }\n catch {\n return '';\n }\n}\n/** Prepend the mount basename to an absolute app path (no-op when no mount, path is relative, or already prefixed). */\nexport function withMountBasename(path) {\n const base = getMountBasename();\n if (!base || !path.startsWith('/'))\n return path;\n if (path === base || path.startsWith(`${base}/`))\n return path;\n return joinPath(base, path);\n}\n/** Strip the mount basename from a browser path so route patterns match app-relative (no-op when no mount). */\nexport function stripMountBasename(path) {\n const base = getMountBasename();\n if (!base)\n return path;\n if (path === base)\n return '/';\n if (path.startsWith(`${base}/`))\n return path.slice(base.length) || '/';\n return path;\n}\nexport function getPathSegments(path) {\n if (path === '') {\n return [];\n }\n if (path === '/') {\n return [''];\n }\n let s = 0, e = path.length;\n if (path.startsWith('./')) {\n s = 2;\n }\n else if (path.startsWith('/')) {\n s = 1;\n }\n if (path.endsWith('/')) {\n e = path.length - 1;\n }\n return (s > 0 || e < path.length ? path.substring(s, e) : path).split('/');\n}\nexport function toSegments(path) {\n if (typeof path === 'string') {\n return getPathSegments(path);\n }\n else if (Array.isArray(path)) {\n return path;\n }\n else {\n throw new Error(`Unsupported path object: ${path}`);\n }\n}\n// export class Path {\n// static parse(path: string, abs = false) {\n// if (abs !== undefined) {\n// abs = path.startsWith('/');\n// }\n// return new Path(getPathSegments(path), abs);\n// }\n// constructor(public segments: string[], public isAbsolute = false) {\n// }\n// getParameters() {\n// const out = [];\n// for (const segment of this.segments) {\n// if (segment[0] === ':') {\n// out.push(segment.substring(1));\n// }\n// }\n// if (this.segments[this.segments.length - 1] === '*') {\n// out.push('_');\n// }\n// return out;\n// }\n// resolveParameters(path: string) {\n// const params: PathMatchParams = {};\n// const resolvedSegments = getPathSegments(path);\n// if (resolvedSegments.length < this.segments.length) {\n// return null;\n// }\n// const segments = this.segments;\n// for (let i = 0, l = segments.length; i < l; i++) {\n// const seg = segments[i];\n// if (seg[0] === ':') {\n// params[seg.substring(1)] = resolvedSegments[i];\n// }\n// }\n// if (resolvedSegments.length - this.segments.length) {\n// params._ = resolvedSegments.slice(this.segments.length);\n// }\n// return params;\n// }\n// match(path: string | string[] | Path) {\n// const segments = toSegments(path);\n// if (segments.length < this.segments.length) {\n// return false;\n// }\n// let params: PathMatchParams | undefined;\n// const mySegments = this.segments;\n// for (let i = 0, l = mySegments.length; i < l; i++) {\n// const segment = mySegments[i];\n// if (segment === ':') {\n// if (!params) params = {};\n// params[segment.substring(1)] = segment;\n// } else if (segment !== segments[i]) {\n// if (i === l - 1 && segment === '*') {\n// if (!params) params = {};\n// params._ = segments.slice(i);\n// return params;\n// }\n// return false;\n// }\n// }\n// return params ? params : false;\n// }\n// join(path: Path | string | string[]) {\n// const segments = toSegments(path);\n// return new Path(this.segments.concat(segments), this.isAbsolute);\n// }\n// getRelativePath(path: Path | string | string[], asAbsolute: boolean = false) {\n// const segments = toSegments(path);\n// const extraSegmentsCount = segments.length - this.segments.length;\n// if (extraSegmentsCount <= 0) {\n// return null;\n// }\n// return new Path(segments.slice(this.segments.length), asAbsolute);\n// }\n// prependSegments(segments: string[]) {\n// this.segments = segments.concat(this.segments);\n// }\n// appendSegments(segments: string[]) {\n// this.segments = this.segments.concat(segments);\n// }\n// toAbsolutePath() {\n// return '/' + this.segments.join('/');\n// }\n// toRelativePath() {\n// return this.segments.join('/');\n// }\n// toString() {\n// const path = this.segments.join('/');\n// return this.isAbsolute ? '/' + path : path;\n// }\n// }\n//# sourceMappingURL=path.js.map","import { PathWithParams } from './PathWithParams';\nimport { joinPath, withMountBasename } from './path';\nconst BASE_PATH = Symbol('BASE_PATH');\nexport { BASE_PATH };\nexport class LocationChangeEvent {\n name;\n type;\n location;\n state;\n _canceled = false;\n constructor(name, type, location, state) {\n this.name = name;\n this.type = type;\n this.location = location;\n this.state = state;\n }\n get isPageLoad() {\n return this.type === 'initial';\n }\n get isBackForward() {\n return this.type === 'popState';\n }\n get isLinkClick() {\n return this.type === 'linkClick';\n }\n get isNavigation() {\n return this.type === 'navigate';\n }\n get isCancelable() {\n return this.name === 'beforeChange';\n }\n cancel() {\n if (this.name === 'afterChange') {\n throw new Error('Cannot cancel afterChange event');\n }\n this._canceled = true;\n }\n}\nexport class BeforeLocationChangeEvent extends LocationChangeEvent {\n constructor(type, location, state) {\n super('beforeChange', type, location, state);\n }\n}\nexport class AfterLocationChangeEvent extends LocationChangeEvent {\n constructor(type, location, state) {\n super('afterChange', type, location, state);\n }\n}\nfunction getClosestAnchor(target) {\n if (!(target instanceof Element)) {\n return null;\n }\n return target.closest('a[href]');\n}\nfunction getElementHrefAsUrl(elem) {\n const href = elem.href.trim();\n return href.length > 0 ? new URL(href) : null;\n}\nexport class HistoryNavigator {\n // params to preserve in the query string when navigating\n stickyParams;\n _popStateListener;\n _linkNavListener;\n _listeners = [];\n addListener(listener) {\n this._listeners.push(listener);\n }\n fireLocationChange(event) {\n for (const listener of this._listeners) {\n listener(event);\n }\n }\n /**\n * Should be called when the page is first loaded.\n * It will fire a location change event with type `initial` and the current window.location as the location\n */\n firePageLoad() {\n this.fireLocationChange(new AfterLocationChangeEvent('initial', new URL(window.location.href)));\n }\n addStickyParams(path) {\n if (this.stickyParams) {\n return new PathWithParams(path).add(this.stickyParams).toString();\n }\n return path;\n }\n /**\n * Rewrite the current browser URL in place so that the sticky params are present, without\n * navigating. Used on load / when the params first become known so the address bar reflects\n * the active account/project before the first navigation.\n *\n * Idempotent and side-effect-light: only calls replaceState when the URL would actually\n * change, preserves the existing history state, and never fires a location-change event\n * (so there is no route re-match or component remount).\n */\n normalizeCurrentUrl() {\n if (typeof window === 'undefined' || !this.stickyParams) {\n return;\n }\n const current = window.location.pathname + window.location.search + window.location.hash;\n const normalized = this.addStickyParams(current);\n if (normalized !== current) {\n const to = new URL(normalized, window.location.href);\n window.history.replaceState(window.history.state, '', to.href);\n }\n }\n navigate(to, options = {}) {\n if (options.stepsBack && options.stepsBack > 0) {\n this.stepBack(options.stepsBack, options);\n return;\n }\n if (options.basePath) {\n let basePath = options.basePath;\n if (!basePath.startsWith('/')) {\n basePath = `/${basePath}`;\n }\n to = joinPath(basePath, to);\n }\n to = this.addStickyParams(to);\n // Keep absolute app routes under the served `<base href>` mount instead of resolving them\n // against the bare origin (which collapses the URL off the mount). No-op when origin-served.\n to = withMountBasename(to);\n this._navigate(new URL(to, window.location.href), 'navigate', options);\n }\n stepBack(steps, options = {}) {\n const historyChain = window.history.state.historyChain || [];\n const to = historyChain.length >= steps\n ? new URL(historyChain[historyChain.length - steps].href, window.location.href)\n : new URL(window.location.origin, window.location.href);\n this._navigate(to, 'popState', options);\n const stateToStore = {\n from: window.location.href,\n historyChain: historyChain.slice(0, -steps),\n data: options.state || undefined,\n title: options.title || document.title,\n };\n window.history.replaceState(stateToStore, '', to.href);\n this.fireLocationChange(new AfterLocationChangeEvent('popState', to, options.state));\n }\n _navigate(to, type, options) {\n const beforeEvent = new BeforeLocationChangeEvent(type, to, options.state);\n this.fireLocationChange(beforeEvent);\n if (beforeEvent._canceled) {\n return;\n }\n // Build navigation chain by preserving previous history\n const currentState = window.history.state;\n const currentTitle = options.title || document.title;\n // Create new history chain entry\n const newChainEntry = {\n title: currentTitle,\n href: window.location.pathname + window.location.search + window.location.hash,\n };\n // Build the history chain - clear if using replace\n let historyChain = [];\n if (!options.replace && currentState?.historyChain) {\n historyChain = [...currentState.historyChain];\n }\n // Only add to chain if not replacing\n if (!options.replace) {\n historyChain.push(newChainEntry);\n // Limit chain length to prevent memory issues (keep last 10 entries)\n if (historyChain.length > 10) {\n historyChain = historyChain.slice(-10);\n }\n }\n const stateToStore = {\n from: window.location.href,\n historyChain: historyChain,\n data: options.state || undefined,\n title: options.title || document.title,\n };\n window.history[options.replace ? 'replaceState' : 'pushState'](stateToStore, '', to.href);\n this.fireLocationChange(new AfterLocationChangeEvent(type, to, options.state));\n }\n start() {\n if (typeof window === 'undefined') {\n return;\n }\n const _popStateListener = (ev) => {\n let type;\n const to = new URL(window.location.href);\n let state;\n if (ev.state) {\n type = 'popState';\n state = ev.state.data;\n }\n else {\n type = 'linkClick';\n }\n this.fireLocationChange(new AfterLocationChangeEvent(type, to, state));\n };\n const _linkNavListener = (ev) => {\n // Let the browser handle modifier / non-primary clicks natively (open in new tab/window,\n // download). Intercepting them here would preventDefault those affordances.\n if (ev.defaultPrevented || ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey || ev.button !== 0) {\n return;\n }\n const anchor = getClosestAnchor(ev.target);\n if (!anchor) {\n return;\n }\n const anchorTarget = anchor.getAttribute('target');\n // Downloads, blob URLs, and explicitly targeted links require native browser navigation.\n if (anchor.hasAttribute('download') ||\n anchor.href.startsWith('blob:') ||\n (!!anchorTarget && anchorTarget.toLowerCase() !== '_self')) {\n return;\n }\n const url = getElementHrefAsUrl(anchor);\n if (url && url.origin === window.location.origin) {\n ev.preventDefault();\n const to = new URL(this.addStickyParams(url.href));\n const basePath = ev[BASE_PATH] ||\n ev.target[BASE_PATH];\n if (basePath) {\n to.pathname = joinPath(basePath, to.pathname);\n }\n this._navigate(to, 'linkClick', {});\n }\n };\n this._popStateListener = _popStateListener;\n this._linkNavListener = _linkNavListener;\n window.addEventListener('popstate', _popStateListener);\n document.body.addEventListener('click', this._linkNavListener);\n }\n stop() {\n if (this._popStateListener)\n window.removeEventListener('popstate', this._popStateListener);\n if (this._linkNavListener)\n document.body.removeEventListener('click', this._linkNavListener);\n }\n}\n//# sourceMappingURL=HistoryNavigator.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect, useRef } from 'react';\nimport { BASE_PATH } from './HistoryNavigator';\nexport function FixLinks({ basePath, children }) {\n const ref = useRef(null);\n useEffect(() => {\n if (ref.current) {\n const divElem = ref.current;\n const listener = (ev) => {\n const elem = ev.target;\n if (elem.tagName.toLowerCase() === 'a') {\n ev[BASE_PATH] = basePath;\n }\n };\n divElem.addEventListener('click', listener);\n return () => {\n divElem.removeEventListener('click', listener);\n };\n }\n }, [basePath]);\n return (_jsx(\"div\", { ref: ref, className: \"h-full w-full\", children: children }));\n}\n//# sourceMappingURL=FixLinks.js.map","import { getPathSegments, toSegments } from './path';\n/**\n * Path matcher which support :param and *wildcard segments.\n * The wildcard segment is only supported as the last segment\n */\nexport class PathMatcher {\n tree = new RootSegmentNode();\n loadMapping(mapping) {\n for (const [key, value] of Object.entries(mapping)) {\n this.addSegments(getPathSegments(key), value);\n }\n }\n addPath(path, value) {\n this.addSegments(getPathSegments(path), value);\n }\n addSegments(segments, value) {\n let node = this.tree;\n for (let i = 0, l = segments.length; i < l; i++) {\n const segment = segments[i];\n if (segment[0] === ':') {\n let childNode = node.wildcard;\n if (!childNode) {\n childNode = new VariableSegmentNode(segment);\n node.wildcard = childNode;\n }\n else if (!(childNode instanceof VariableSegmentNode)) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard \":\" segment will overwrite an existing wildcard segment at path: ${`/${segments.slice(0, i).join('/')}`}`);\n }\n node = childNode;\n }\n else if (segment === '*') {\n if (node.wildcard) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard \"*\" segment already exists at path: ${`/${segments.slice(0, i).join('/')}`}`);\n }\n node.wildcard = new WildcardSegmentNode(segment, value);\n if (i < l - 1) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard segment must be the last segment`);\n }\n return;\n }\n else {\n let childNode = node.children[segment];\n if (!childNode) {\n childNode = new LiteralSegmentNode(segment);\n node.children[segment] = childNode;\n } // else // a literal segment already exists\n node = childNode;\n }\n }\n if (node.value !== undefined) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A value already exists at path: ${`/${segments.join('/')}`}`);\n }\n node.value = value;\n }\n match(path) {\n const segments = toSegments(path);\n if (segments.length === 0) {\n return null;\n }\n const params = {};\n let node = this.tree;\n for (const segment of segments) {\n const match = node.match(segment, params);\n if (match) {\n node = match;\n }\n else {\n return null;\n }\n }\n if (!node.value) {\n // not a leaf node (partial match)\n if (node instanceof ParentSegmentNode) {\n if (node.wildcard instanceof WildcardSegmentNode) {\n node = node.wildcard.match('', params);\n if (!node.value) {\n throw new Error('Wildcard segment node `*` must have a value');\n }\n }\n }\n if (!node.value)\n return null; // not a leaf node, neither a trailing wildcard (partial match)\n }\n let matchedSegments, remainingSegments;\n if (params._ && params._.length > 0) {\n matchedSegments = segments.slice(0, -params._.length);\n remainingSegments = params._;\n }\n else {\n matchedSegments = segments;\n }\n return { params, matchedSegments, remainingSegments, value: node.value };\n }\n}\nclass ParentSegmentNode {\n name;\n value;\n children = {};\n wildcard;\n constructor(name, value) {\n this.name = name;\n this.value = value;\n }\n match(segment, params) {\n const node = this.children[segment];\n if (node) {\n return node;\n }\n else if (this.wildcard) {\n if (this.wildcard instanceof WildcardSegmentNode) {\n return this.wildcard.match(segment, params);\n }\n else if (this.wildcard instanceof VariableSegmentNode) {\n params[this.wildcard.paramName] = segment;\n return this.wildcard;\n }\n else {\n throw new Error(`Unknown wildcard segment node type: ${this.wildcard.constructor.name}`);\n }\n }\n else {\n return null;\n }\n }\n}\nclass RootSegmentNode extends ParentSegmentNode {\n constructor() {\n super('#root');\n }\n}\nclass LiteralSegmentNode extends ParentSegmentNode {\n}\nclass VariableSegmentNode extends ParentSegmentNode {\n paramName;\n constructor(name, value) {\n super(name, value);\n this.paramName = name.substring(1);\n }\n}\nclass WildcardSegmentNode {\n name;\n value;\n constructor(name, value) {\n this.name = name;\n this.value = value;\n }\n match(segment, params) {\n if (!params._) {\n params._ = segment ? [segment] : [];\n }\n else {\n if (segment)\n params._.push(segment);\n }\n return this;\n }\n}\n//# sourceMappingURL=PathMatcher.js.map","import { createContext, useContext, useEffect } from 'react';\nimport { HistoryNavigator } from './HistoryNavigator';\nimport { PathMatcher } from './PathMatcher';\nimport { getMountBasename, isRootPath, joinPath, stripMountBasename } from './path';\nexport class BaseRouter {\n // the path to use when navigating to the root of the router\n index;\n matcher = new PathMatcher();\n constructor(routes, index) {\n this.index = index;\n for (const route of routes) {\n this.matcher.addPath(route.path, route);\n }\n }\n match(path) {\n const useIndex = isRootPath(path) && this.index;\n return this.matcher.match(useIndex || path);\n }\n}\nexport class Router extends BaseRouter {\n prompt;\n observer;\n navigator = new HistoryNavigator();\n constructor(routes, updateState) {\n super(routes);\n this.navigator.addListener((event) => {\n if (event.isCancelable && this.prompt?.when) {\n if (!window.confirm(this.prompt.message))\n return;\n }\n if (this.observer) {\n this.observer(event);\n }\n // only process afterChange events\n if (event.name === 'afterChange') {\n // Match app-relative: strip the served `<base href>` mount prefix (no-op when origin-served).\n const match = this.match(stripMountBasename(event.location.pathname));\n if (match?.value) {\n updateState({\n ...match,\n state: event.state,\n });\n }\n else {\n updateState(null);\n }\n }\n });\n }\n getTopRouter() {\n return this;\n }\n /**\n * Subsequent navigations will preserve the given params in the query string.\n * Use null to clear the sticky params.\n * @param params\n */\n setStickyParams(params) {\n this.navigator.stickyParams = params != null ? params : undefined;\n // Reflect the params in the current URL immediately, so the address bar is correct on\n // load (not only after the first navigation).\n this.navigator.normalizeCurrentUrl();\n }\n withObserver(observer) {\n this.observer = observer;\n return this;\n }\n start() {\n this.navigator.start();\n // initialize with the current location\n this.navigator.firePageLoad();\n }\n stop() {\n this.navigator.stop();\n }\n navigate(path, options) {\n this.navigator.navigate(path, options);\n }\n}\nexport class NestedRouter extends BaseRouter {\n parent;\n basePath;\n constructor(parent, basePath, routes) {\n super(routes);\n this.parent = parent;\n this.basePath = basePath;\n }\n getTopRouter() {\n if (this.parent instanceof Router) {\n return this.parent;\n }\n else {\n return this.parent.getTopRouter();\n }\n }\n navigate(path, options) {\n // base path is nested by default in a NestedRouter unless explicitly set to false by caller\n const isBasePathNested = options?.isBasePathNested ?? true;\n let basePath;\n if (isBasePathNested) {\n const childBasePath = options?.basePath;\n // e.g. \"/store\" + \"/objects/123\" => \"/store/objects/123\"\n basePath = childBasePath ? joinPath(this.basePath, childBasePath) : this.basePath;\n this.parent.navigate(path, {\n ...options,\n basePath,\n });\n }\n else {\n // isBasePathNested === false: navigate to an absolute path without adding this router's basePath\n // Pass through to parent without adding our basePath prefix\n this.parent.navigate(path, {\n ...options,\n basePath: options?.basePath,\n });\n }\n }\n}\nconst ReactRouterContext = createContext(undefined);\nexport { ReactRouterContext };\nexport function useRouterContext() {\n const ctx = useContext(ReactRouterContext);\n if (!ctx) {\n throw new Error('useRouter must be used within a RouterProvider');\n }\n return ctx;\n}\nexport function useNavigate() {\n const { navigate } = useRouterContext();\n return navigate;\n}\nexport function useRouterBasePath() {\n const { router } = useRouterContext();\n // The base path apps prepend to build absolute in-app links (e.g. `${base}/items/${id}`). It MUST\n // include the served `<base href>` mount so links stay on the mount and match the full\n // `useLocation().pathname` (which carries the mount). `getMountBasename()` is '' for the\n // origin-served Studio UI and the mount (no trailing slash) for gateway-served apps.\n const mount = getMountBasename();\n if (router instanceof NestedRouter) {\n // NestedRouter.basePath is relative to the parent router, which sits at the mount, so it must\n // be mount-prefixed too. A bare nested base of '/' (an app whose NestedRouterProvider has no\n // basePath) would otherwise make `${base}/items` resolve to `//items` — a protocol-relative\n // URL that escapes the app. Origin-served Studio (mount '') keeps the raw nested basePath.\n if (!mount)\n return router.basePath;\n return router.basePath === '/' ? mount : joinPath(mount, router.basePath);\n }\n return mount;\n}\nexport function useParams(arg) {\n const { params } = useRouterContext();\n if (arg) {\n return params[arg];\n }\n else {\n return params;\n }\n}\nexport function useLocation() {\n const { location } = useRouterContext();\n return location;\n}\nexport function usePageTitle(title) {\n useEffect(() => {\n const prev = document.title;\n document.title = title;\n return () => {\n document.title = prev;\n };\n }, [title]);\n}\nexport function useNavigationPrompt(prompt) {\n const { router } = useRouterContext();\n const topRouter = router.getTopRouter();\n useEffect(() => {\n topRouter.prompt = prompt;\n return () => {\n topRouter.prompt = undefined;\n };\n }, [prompt, topRouter]);\n useEffect(() => {\n if (prompt.when) {\n const doBlock = prompt.when;\n const listener = (ev) => {\n if (doBlock) {\n ev.preventDefault();\n ev.returnValue = '';\n }\n };\n window.addEventListener('beforeunload', listener);\n return () => {\n window.removeEventListener('beforeunload', listener);\n };\n }\n }, [prompt.when]);\n}\n//# sourceMappingURL=Router.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { withMountBasename } from './path';\nimport { useNavigate, useRouterContext } from './Router';\n/**\n * True when the click carries a modifier the browser uses for alternate link behavior\n * (open in new tab/window, download) or is not a primary-button click. Such clicks must fall\n * through to the native anchor so the browser can handle them instead of the SPA router.\n */\nfunction isModifiedClick(ev) {\n return ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey || ev.button !== 0;\n}\nexport function Nav({ children, to, onClick, replace = true }) {\n const navigate = useNavigate();\n const _onClick = (ev) => {\n const link = ev.target.closest('a');\n const rawHref = link?.getAttribute('href');\n const target = to ?? rawHref;\n if (link && target) {\n ev.stopPropagation();\n ev.preventDefault();\n navigate(target, { replace });\n onClick?.(ev);\n }\n };\n return (_jsx(\"span\", { onClick: _onClick, children: children }));\n}\nexport function NavLink({ children, href, className, target, topLevelNav, clearBreadcrumbs = false, replace, skipStickyParams, }) {\n const { router } = useRouterContext();\n // Resolve internal URLs even when a target makes navigation native. New-tab links still need\n // the mount path and tenant sticky params, but must not be intercepted by the SPA router.\n const isAnchorOrEmpty = !href || href.startsWith('#');\n const isExternalUrl = /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith('//');\n const isInternalUrl = !isAnchorOrEmpty && !isExternalUrl;\n const isNativeNavigation = !!target && target !== '_self';\n // Keep the rendered href under the served `<base href>` mount (correct middle-click / hover /\n // open-in-new-tab); the onClick navigates via the router which applies the same rule. No-op when\n // origin-served (Studio UI). Click handler below passes the raw `href` — navigate() re-bases it.\n const resolvedHref = isInternalUrl\n ? withMountBasename(!skipStickyParams ? router.getTopRouter().navigator.addStickyParams(href) : href)\n : href;\n const _onClick = (ev) => {\n if (ev.defaultPrevented || !isInternalUrl || isNativeNavigation || isModifiedClick(ev)) {\n return;\n }\n ev.stopPropagation();\n ev.preventDefault();\n const actualRouter = topLevelNav ? router.getTopRouter() : router;\n actualRouter.navigate(href, { replace: replace ?? clearBreadcrumbs });\n };\n return (_jsx(\"a\", { href: resolvedHref, className: className, target: target, onClick: _onClick, children: children }));\n}\n//# sourceMappingURL=Nav.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect, useState } from 'react';\nimport { useRouterContext, } from './Router';\n// Resolved lazy modules, keyed by the route's LazyComponent function (a stable identity: route\n// tables are declared once). A revisited lazy route renders synchronously from this cache instead\n// of unmounting to the spinner for the async import() round-trip — without it, every navigation\n// between two lazy routes blanks the page for at least a frame, even when the module is loaded.\nconst resolvedComponents = new Map();\nasync function resolveLazyRoute(route) {\n const module = await route.LazyComponent();\n if (!module?.default) {\n throw new Error(`Lazy module for ${route.path} does not have a default export`);\n }\n resolvedComponents.set(route.LazyComponent, module.default);\n return module.default;\n}\n/**\n * Start loading the given routes' lazy modules ahead of navigation (non-lazy routes are ignored).\n * Call it during idle time after first paint: the first navigation to a prefetched route then\n * renders synchronously instead of flashing the spinner while its chunk downloads. Failures are\n * swallowed — navigation retries the import and reports the error the normal way.\n */\nexport function prefetchLazyRoutes(routes) {\n return Promise.allSettled(routes\n .filter((route) => !!route.LazyComponent)\n .map((route) => resolveLazyRoute(route)));\n}\nexport function RouteComponent({ spinner }) {\n const ctx = useRouterContext();\n const route = ctx.route;\n if (route.Component) {\n const Component = route.Component;\n return _jsx(Component, { ...ctx.params });\n }\n else if (route.LazyComponent) {\n // Keyed per path so navigating between two lazy routes remounts: a reused instance would\n // keep rendering the previous route's component while the next import resolves.\n return _jsx(LazyRouteComponent, { route: route, spinner: spinner }, route.path);\n }\n else {\n throw new Error(`Invalid route for ${route.path}. Either Component or LazyCOmponent must be specified.`);\n }\n}\nfunction LazyRouteComponent({ route, spinner }) {\n const [Component, setComponent] = useState(() => resolvedComponents.get(route.LazyComponent) ?? null);\n const [error, setError] = useState();\n useEffect(() => {\n // A slow import must not land after this instance moved on (unmount, or a route object\n // swap without a path change): the stale module would overwrite the current one.\n let stale = false;\n void resolveLazyRoute(route).then((component) => {\n if (!stale)\n setComponent(() => component);\n }, (error) => {\n // Render failures through the surrounding error boundary, including import failures.\n if (!stale)\n setError(() => error);\n });\n return () => {\n stale = true;\n };\n }, [route]);\n if (error !== undefined)\n throw error;\n return Component ? _jsx(Component, {}) : spinner || null;\n}\n//# sourceMappingURL=RouteComponent.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { FixLinks } from './FixLinks';\nimport { joinPath } from './path';\nimport { RouteComponent } from './RouteComponent';\nimport { ReactRouterContext, useRouterContext } from './Router';\nexport function NestedNavigationContext({ basePath, isBasePathNested = true, fixLinks = false, children, }) {\n const ctx = useRouterContext();\n const wrapWithFixLinks = fixLinks\n ? (elem) => _jsx(FixLinks, { basePath: ctx.matchedRoutePath, children: elem })\n : (elem) => elem;\n return (_jsx(ReactRouterContext.Provider, { value: {\n ...ctx,\n navigate: (to, options) => {\n if (options?.isBasePathNested === false) {\n // Navigate to an absolute path without adding this context's basePath\n return ctx.navigate(to, options);\n }\n const actualBasePath = options?.basePath ? joinPath(basePath, options.basePath) : basePath;\n return ctx.navigate(to, { ...options, basePath: actualBasePath, isBasePathNested });\n },\n }, children: wrapWithFixLinks(children ? children : _jsx(RouteComponent, {})) }));\n}\n//# sourceMappingURL=NestedNavigationContext.js.map","import { jsx as _jsx, jsxs as _jsxs } from \"react/jsx-runtime\";\nimport { useRouterContext } from './Router';\nexport function Route404Component() {\n const ctx = useRouterContext();\n return _jsxs(\"div\", { children: [\"Route not found for path \", ctx.matchedRoutePath] });\n}\nexport function createRoute404() {\n return {\n params: {},\n matchedSegments: [],\n state: null,\n value: {\n path: 'virtual:404',\n Component: () => _jsx(Route404Component, {}),\n },\n };\n}\n//# sourceMappingURL=Route404.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useMemo, useRef } from 'react';\nimport { FixLinks } from './FixLinks';\nimport { createRoute404 } from './Route404';\nimport { RouteComponent } from './RouteComponent';\nimport { NestedRouter, ReactRouterContext, useRouterContext } from './Router';\nexport function NestedRouterProvider({ routes, index, children, fixLinks = false }) {\n const ctx = useRouterContext();\n // Capture basePath once at mount. When the parent router switches to a different\n // top-level route (e.g. /store -> /studio), the lazy loader briefly keeps rendering\n // this (now-stale) module with a new ctx. Keeping basePath stable lets the\n // ctx.matchedRoutePath !== nestedRouter.basePath check below detect the mismatch and\n // skip rendering instead of running match() against the wrong route table.\n const basePathRef = useRef(ctx.matchedRoutePath);\n const nestedRouter = useMemo(() => {\n if (typeof window === 'undefined')\n return null;\n const nestedRouter = new NestedRouter(ctx.router, basePathRef.current, routes);\n nestedRouter.index = index;\n return nestedRouter;\n }, [ctx.router, index, routes]);\n const nestedRouteMatch = useMemo(() => {\n if (!nestedRouter) {\n return undefined;\n }\n if (ctx.matchedRoutePath !== nestedRouter.basePath) {\n // The change belongs to another router level and will be handled there.\n return undefined;\n }\n return nestedRouter.match(ctx.remainingPath || '/') || createRoute404();\n }, [ctx.matchedRoutePath, ctx.remainingPath, nestedRouter]);\n const wrapWithFixLinks = fixLinks\n ? (elem) => _jsx(FixLinks, { basePath: ctx.matchedRoutePath, children: elem })\n : (elem) => elem;\n return (nestedRouter &&\n nestedRouteMatch && (_jsx(ReactRouterContext.Provider, { value: {\n ...ctx,\n router: nestedRouter,\n route: nestedRouteMatch.value,\n params: nestedRouteMatch.params,\n matchedRoutePath: `/${nestedRouteMatch.matchedSegments.join('/')}`,\n remainingPath: nestedRouteMatch.remainingSegments\n ? `/${nestedRouteMatch.remainingSegments.join('/')}`\n : undefined,\n navigate: (to, options) => {\n if (nestedRouter) {\n return nestedRouter.navigate(to, options);\n }\n },\n }, children: wrapWithFixLinks(children ? children : _jsx(RouteComponent, {})) })));\n}\n//# sourceMappingURL=NestedRouterProvider.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect } from 'react';\nimport { useNavigate } from './Router';\nexport function Redirect({ to, replace = true, state }) {\n const navigate = useNavigate();\n useEffect(() => {\n navigate(to, { replace, state });\n }, [navigate, replace, state, to]);\n return null;\n}\n/**\n * Creates a route component that redirects to another route when rendered.\n * Useful in route tables, for example: `{ path: '/', Component: redirectTo('/content') }`.\n */\nexport function redirectTo(to, options = {}) {\n return function RedirectRoute() {\n return _jsx(Redirect, { to: to, replace: options.replace, state: options.state });\n };\n}\n//# sourceMappingURL=Redirect.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useSafeLayoutEffect } from '@vertesia/ui/core';\nimport { useMemo, useState } from 'react';\nimport { createRoute404 } from './Route404';\nimport { RouteComponent } from './RouteComponent';\nimport { ReactRouterContext, Router } from './Router';\nexport function RouterProvider({ routes, index, onChange, children }) {\n const [state, setState] = useState(undefined);\n const router = useMemo(() => {\n if (typeof window === 'undefined')\n return null;\n const router = new Router(routes, (match) => {\n if (match === null) {\n match = createRoute404();\n }\n setState({\n location: window.location,\n route: match.value,\n params: match.params,\n state: match.state,\n router: router,\n matchedRoutePath: `/${match.matchedSegments.join('/')}`,\n remainingPath: match.remainingSegments ? `/${match.remainingSegments.join('/')}` : undefined,\n navigate: (to, options) => {\n return router.navigate(to, options);\n },\n });\n }).withObserver(onChange);\n router.index = index;\n return router;\n }, [index, onChange, routes]);\n useSafeLayoutEffect(() => {\n router?.start();\n return () => {\n router?.stop();\n };\n }, [router]);\n return (state && (_jsx(ReactRouterContext.Provider, { value: state, children: children ? children : _jsx(RouteComponent, {}) })));\n}\n//# sourceMappingURL=RouterProvider.js.map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vertesia-ui-router.js","names":["_jsx","_jsx","_jsx","_jsx","_jsxs","_jsx","_jsx","_jsx","_jsx","__defProp","__exportAll","target","name","all","no_symbols","PathWithParams","i","path","key","value","params","path_exports","getMountBasename","getPathSegments","isRootPath","joinPath","stripMountBasename","toSegments","withMountBasename","path2","path1","base","s","e","BASE_PATH","LocationChangeEvent","type","location","state","BeforeLocationChangeEvent","AfterLocationChangeEvent","getClosestAnchor","getElementHrefAsUrl","href","elem","HistoryNavigator","listener","event","current","normalized","to","options","basePath","historyChain","steps","stateToStore","beforeEvent","currentState","newChainEntry","_popStateListener","ev","_linkNavListener","anchor","anchorTarget","url","FixLinks","ref","useRef","useEffect","divElem","jsx","PathMatcher","RootSegmentNode","mapping","node","l","segments","segment","childNode","VariableSegmentNode","WildcardSegmentNode","LiteralSegmentNode","match","ParentSegmentNode","matchedSegments","remainingSegments","BaseRouter","index","route","routes","useIndex","Router","updateState","observer","NestedRouter","parent","isBasePathNested","childBasePath","ReactRouterContext","createContext","useRouterContext","ctx","useContext","useNavigate","navigate","useRouterBasePath","mount","router","useParams","arg","useLocation","usePageTitle","prev","title","useNavigationPrompt","topRouter","prompt","doBlock","isModifiedClick","Nav","link","rawHref","onClick","NavLink","isAnchorOrEmpty","isExternalUrl","isInternalUrl","isNativeNavigation","resolvedHref","skipStickyParams","topLevelNav","replace","clearBreadcrumbs","resolvedComponents","resolveLazyRoute","module","prefetchLazyRoutes","RouteComponent","Component","LazyRouteComponent","setComponent","useState","error","setError","stale","component","spinner","NestedNavigationContext","wrapWithFixLinks","fixLinks","actualBasePath","children","Route404Component","jsxs","createRoute404","NestedRouterProvider","basePathRef","nestedRouter","useMemo","nestedRouteMatch","Redirect","redirectTo","RouterProvider","setState","onChange","useSafeLayoutEffect"],"sources":["router/PathWithParams.js","router/path.js","router/HistoryNavigator.js","router/FixLinks.js","router/PathMatcher.js","router/Router.js","router/Nav.js","router/RouteComponent.js","router/NestedNavigationContext.js","router/Route404.js","router/NestedRouterProvider.js","router/Redirect.js","router/RouterProvider.js"],"sourcesContent":["export class PathWithParams {\n path;\n params;\n hash;\n constructor(path) {\n let i = path.lastIndexOf('#');\n if (i > -1) {\n this.hash = path.substring(i);\n path = path.substring(0, i);\n }\n else {\n this.hash = '';\n }\n i = path.indexOf('?');\n if (i > -1) {\n this.path = path.substring(0, i);\n this.params = new URLSearchParams(path.substring(i + 1));\n }\n else {\n this.path = path;\n this.params = new URLSearchParams();\n }\n }\n add(params) {\n for (const [key, value] of Object.entries(params)) {\n this.params.set(key, value);\n }\n return this;\n }\n toString() {\n return `${this.path}?${this.params.toString()}${this.hash}`;\n }\n}\n//# sourceMappingURL=PathWithParams.js.map","export function isRootPath(path) {\n return path === '/' || path === '';\n}\nexport function joinPath(path1, path2) {\n if (path1.endsWith('/') && path2.startsWith('/')) {\n path2 = path1 + path2.substring(1);\n }\n else if (path1.endsWith('/')) {\n path2 = path1 + path2;\n }\n else if (path2.startsWith('/')) {\n path2 = path1 + path2;\n }\n else {\n path2 = `${path1}/${path2}`;\n }\n return path2;\n}\n/**\n * The mount base path from an explicit `<base href>` element, or `''` when there is none.\n *\n * Apps served under a deep gateway mount carry `<base href=\"/tenants/.../app/\">`, injected at serve\n * time. The router otherwise resolves absolute routes against the origin, which collapses the URL\n * off the mount (and breaks in-app links). This returns the base pathname without a trailing slash\n * so {@link withMountBasename} can keep navigation under the mount and {@link stripMountBasename}\n * can match routes app-relative. The Studio UI has no `<base>` element, so this returns `''` and\n * every caller becomes a no-op there.\n */\nexport function getMountBasename() {\n if (typeof document === 'undefined')\n return '';\n const base = document.querySelector('base[href]');\n if (!base)\n return '';\n try {\n return new URL(base.href, document.URL).pathname.replace(/\\/+$/, '');\n }\n catch {\n return '';\n }\n}\n/** Prepend the mount basename to an absolute app path (no-op when no mount, path is relative, or already prefixed). */\nexport function withMountBasename(path) {\n const base = getMountBasename();\n if (!base || !path.startsWith('/'))\n return path;\n if (path === base || path.startsWith(`${base}/`))\n return path;\n return joinPath(base, path);\n}\n/** Strip the mount basename from a browser path so route patterns match app-relative (no-op when no mount). */\nexport function stripMountBasename(path) {\n const base = getMountBasename();\n if (!base)\n return path;\n if (path === base)\n return '/';\n if (path.startsWith(`${base}/`))\n return path.slice(base.length) || '/';\n return path;\n}\nexport function getPathSegments(path) {\n if (path === '') {\n return [];\n }\n if (path === '/') {\n return [''];\n }\n let s = 0, e = path.length;\n if (path.startsWith('./')) {\n s = 2;\n }\n else if (path.startsWith('/')) {\n s = 1;\n }\n if (path.endsWith('/')) {\n e = path.length - 1;\n }\n return (s > 0 || e < path.length ? path.substring(s, e) : path).split('/');\n}\nexport function toSegments(path) {\n if (typeof path === 'string') {\n return getPathSegments(path);\n }\n else if (Array.isArray(path)) {\n return path;\n }\n else {\n throw new Error(`Unsupported path object: ${path}`);\n }\n}\n// export class Path {\n// static parse(path: string, abs = false) {\n// if (abs !== undefined) {\n// abs = path.startsWith('/');\n// }\n// return new Path(getPathSegments(path), abs);\n// }\n// constructor(public segments: string[], public isAbsolute = false) {\n// }\n// getParameters() {\n// const out = [];\n// for (const segment of this.segments) {\n// if (segment[0] === ':') {\n// out.push(segment.substring(1));\n// }\n// }\n// if (this.segments[this.segments.length - 1] === '*') {\n// out.push('_');\n// }\n// return out;\n// }\n// resolveParameters(path: string) {\n// const params: PathMatchParams = {};\n// const resolvedSegments = getPathSegments(path);\n// if (resolvedSegments.length < this.segments.length) {\n// return null;\n// }\n// const segments = this.segments;\n// for (let i = 0, l = segments.length; i < l; i++) {\n// const seg = segments[i];\n// if (seg[0] === ':') {\n// params[seg.substring(1)] = resolvedSegments[i];\n// }\n// }\n// if (resolvedSegments.length - this.segments.length) {\n// params._ = resolvedSegments.slice(this.segments.length);\n// }\n// return params;\n// }\n// match(path: string | string[] | Path) {\n// const segments = toSegments(path);\n// if (segments.length < this.segments.length) {\n// return false;\n// }\n// let params: PathMatchParams | undefined;\n// const mySegments = this.segments;\n// for (let i = 0, l = mySegments.length; i < l; i++) {\n// const segment = mySegments[i];\n// if (segment === ':') {\n// if (!params) params = {};\n// params[segment.substring(1)] = segment;\n// } else if (segment !== segments[i]) {\n// if (i === l - 1 && segment === '*') {\n// if (!params) params = {};\n// params._ = segments.slice(i);\n// return params;\n// }\n// return false;\n// }\n// }\n// return params ? params : false;\n// }\n// join(path: Path | string | string[]) {\n// const segments = toSegments(path);\n// return new Path(this.segments.concat(segments), this.isAbsolute);\n// }\n// getRelativePath(path: Path | string | string[], asAbsolute: boolean = false) {\n// const segments = toSegments(path);\n// const extraSegmentsCount = segments.length - this.segments.length;\n// if (extraSegmentsCount <= 0) {\n// return null;\n// }\n// return new Path(segments.slice(this.segments.length), asAbsolute);\n// }\n// prependSegments(segments: string[]) {\n// this.segments = segments.concat(this.segments);\n// }\n// appendSegments(segments: string[]) {\n// this.segments = this.segments.concat(segments);\n// }\n// toAbsolutePath() {\n// return '/' + this.segments.join('/');\n// }\n// toRelativePath() {\n// return this.segments.join('/');\n// }\n// toString() {\n// const path = this.segments.join('/');\n// return this.isAbsolute ? '/' + path : path;\n// }\n// }\n//# sourceMappingURL=path.js.map","import { PathWithParams } from './PathWithParams';\nimport { joinPath, withMountBasename } from './path';\nconst BASE_PATH = Symbol('BASE_PATH');\nexport { BASE_PATH };\nexport class LocationChangeEvent {\n name;\n type;\n location;\n state;\n _canceled = false;\n constructor(name, type, location, state) {\n this.name = name;\n this.type = type;\n this.location = location;\n this.state = state;\n }\n get isPageLoad() {\n return this.type === 'initial';\n }\n get isBackForward() {\n return this.type === 'popState';\n }\n get isLinkClick() {\n return this.type === 'linkClick';\n }\n get isNavigation() {\n return this.type === 'navigate';\n }\n get isCancelable() {\n return this.name === 'beforeChange';\n }\n cancel() {\n if (this.name === 'afterChange') {\n throw new Error('Cannot cancel afterChange event');\n }\n this._canceled = true;\n }\n}\nexport class BeforeLocationChangeEvent extends LocationChangeEvent {\n constructor(type, location, state) {\n super('beforeChange', type, location, state);\n }\n}\nexport class AfterLocationChangeEvent extends LocationChangeEvent {\n constructor(type, location, state) {\n super('afterChange', type, location, state);\n }\n}\nfunction getClosestAnchor(target) {\n if (!(target instanceof Element)) {\n return null;\n }\n return target.closest('a[href]');\n}\nfunction getElementHrefAsUrl(elem) {\n const href = elem.href.trim();\n return href.length > 0 ? new URL(href) : null;\n}\nexport class HistoryNavigator {\n // params to preserve in the query string when navigating\n stickyParams;\n _popStateListener;\n _linkNavListener;\n _listeners = [];\n addListener(listener) {\n this._listeners.push(listener);\n }\n fireLocationChange(event) {\n for (const listener of this._listeners) {\n listener(event);\n }\n }\n /**\n * Should be called when the page is first loaded.\n * It will fire a location change event with type `initial` and the current window.location as the location\n */\n firePageLoad() {\n this.fireLocationChange(new AfterLocationChangeEvent('initial', new URL(window.location.href)));\n }\n addStickyParams(path) {\n if (this.stickyParams) {\n return new PathWithParams(path).add(this.stickyParams).toString();\n }\n return path;\n }\n /**\n * Rewrite the current browser URL in place so that the sticky params are present, without\n * navigating. Used on load / when the params first become known so the address bar reflects\n * the active account/project before the first navigation.\n *\n * Idempotent and side-effect-light: only calls replaceState when the URL would actually\n * change, preserves the existing history state, and never fires a location-change event\n * (so there is no route re-match or component remount).\n */\n normalizeCurrentUrl() {\n if (typeof window === 'undefined' || !this.stickyParams) {\n return;\n }\n const current = window.location.pathname + window.location.search + window.location.hash;\n const normalized = this.addStickyParams(current);\n if (normalized !== current) {\n const to = new URL(normalized, window.location.href);\n window.history.replaceState(window.history.state, '', to.href);\n }\n }\n navigate(to, options = {}) {\n if (options.stepsBack && options.stepsBack > 0) {\n this.stepBack(options.stepsBack, options);\n return;\n }\n if (options.basePath) {\n let basePath = options.basePath;\n if (!basePath.startsWith('/')) {\n basePath = `/${basePath}`;\n }\n to = joinPath(basePath, to);\n }\n to = this.addStickyParams(to);\n // Keep absolute app routes under the served `<base href>` mount instead of resolving them\n // against the bare origin (which collapses the URL off the mount). No-op when origin-served.\n to = withMountBasename(to);\n this._navigate(new URL(to, window.location.href), 'navigate', options);\n }\n stepBack(steps, options = {}) {\n const historyChain = window.history.state.historyChain || [];\n const to = historyChain.length >= steps\n ? new URL(historyChain[historyChain.length - steps].href, window.location.href)\n : new URL(window.location.origin, window.location.href);\n this._navigate(to, 'popState', options);\n const stateToStore = {\n from: window.location.href,\n historyChain: historyChain.slice(0, -steps),\n data: options.state || undefined,\n title: options.title || document.title,\n };\n window.history.replaceState(stateToStore, '', to.href);\n this.fireLocationChange(new AfterLocationChangeEvent('popState', to, options.state));\n }\n _navigate(to, type, options) {\n const beforeEvent = new BeforeLocationChangeEvent(type, to, options.state);\n this.fireLocationChange(beforeEvent);\n if (beforeEvent._canceled) {\n return;\n }\n // Build navigation chain by preserving previous history\n const currentState = window.history.state;\n const currentTitle = options.title || document.title;\n // Create new history chain entry\n const newChainEntry = {\n title: currentTitle,\n href: window.location.pathname + window.location.search + window.location.hash,\n };\n // Build the history chain - clear if using replace\n let historyChain = [];\n if (!options.replace && currentState?.historyChain) {\n historyChain = [...currentState.historyChain];\n }\n // Only add to chain if not replacing\n if (!options.replace) {\n historyChain.push(newChainEntry);\n // Limit chain length to prevent memory issues (keep last 10 entries)\n if (historyChain.length > 10) {\n historyChain = historyChain.slice(-10);\n }\n }\n const stateToStore = {\n from: window.location.href,\n historyChain: historyChain,\n data: options.state || undefined,\n title: options.title || document.title,\n };\n window.history[options.replace ? 'replaceState' : 'pushState'](stateToStore, '', to.href);\n this.fireLocationChange(new AfterLocationChangeEvent(type, to, options.state));\n }\n start() {\n if (typeof window === 'undefined') {\n return;\n }\n const _popStateListener = (ev) => {\n let type;\n const to = new URL(window.location.href);\n let state;\n if (ev.state) {\n type = 'popState';\n state = ev.state.data;\n }\n else {\n type = 'linkClick';\n }\n this.fireLocationChange(new AfterLocationChangeEvent(type, to, state));\n };\n const _linkNavListener = (ev) => {\n // Let the browser handle modifier / non-primary clicks natively (open in new tab/window,\n // download). Intercepting them here would preventDefault those affordances.\n if (ev.defaultPrevented || ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey || ev.button !== 0) {\n return;\n }\n const anchor = getClosestAnchor(ev.target);\n if (!anchor) {\n return;\n }\n const anchorTarget = anchor.getAttribute('target');\n // Downloads, blob URLs, and explicitly targeted links require native browser navigation.\n if (anchor.hasAttribute('download') ||\n anchor.href.startsWith('blob:') ||\n (!!anchorTarget && anchorTarget.toLowerCase() !== '_self')) {\n return;\n }\n const url = getElementHrefAsUrl(anchor);\n if (url && url.origin === window.location.origin) {\n ev.preventDefault();\n const to = new URL(this.addStickyParams(url.href));\n const basePath = ev[BASE_PATH] ||\n ev.target[BASE_PATH];\n if (basePath) {\n to.pathname = joinPath(basePath, to.pathname);\n }\n this._navigate(to, 'linkClick', {});\n }\n };\n this._popStateListener = _popStateListener;\n this._linkNavListener = _linkNavListener;\n window.addEventListener('popstate', _popStateListener);\n document.body.addEventListener('click', this._linkNavListener);\n }\n stop() {\n if (this._popStateListener)\n window.removeEventListener('popstate', this._popStateListener);\n if (this._linkNavListener)\n document.body.removeEventListener('click', this._linkNavListener);\n }\n}\n//# sourceMappingURL=HistoryNavigator.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect, useRef } from 'react';\nimport { BASE_PATH } from './HistoryNavigator';\nexport function FixLinks({ basePath, children }) {\n const ref = useRef(null);\n useEffect(() => {\n if (ref.current) {\n const divElem = ref.current;\n const listener = (ev) => {\n const elem = ev.target;\n if (elem.tagName.toLowerCase() === 'a') {\n ev[BASE_PATH] = basePath;\n }\n };\n divElem.addEventListener('click', listener);\n return () => {\n divElem.removeEventListener('click', listener);\n };\n }\n }, [basePath]);\n return (_jsx(\"div\", { ref: ref, className: \"h-full w-full\", children: children }));\n}\n//# sourceMappingURL=FixLinks.js.map","import { getPathSegments, toSegments } from './path';\n/**\n * Path matcher which support :param and *wildcard segments.\n * The wildcard segment is only supported as the last segment\n */\nexport class PathMatcher {\n tree = new RootSegmentNode();\n loadMapping(mapping) {\n for (const [key, value] of Object.entries(mapping)) {\n this.addSegments(getPathSegments(key), value);\n }\n }\n addPath(path, value) {\n this.addSegments(getPathSegments(path), value);\n }\n addSegments(segments, value) {\n let node = this.tree;\n for (let i = 0, l = segments.length; i < l; i++) {\n const segment = segments[i];\n if (segment[0] === ':') {\n let childNode = node.wildcard;\n if (!childNode) {\n childNode = new VariableSegmentNode(segment);\n node.wildcard = childNode;\n }\n else if (!(childNode instanceof VariableSegmentNode)) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard \":\" segment will overwrite an existing wildcard segment at path: ${`/${segments.slice(0, i).join('/')}`}`);\n }\n node = childNode;\n }\n else if (segment === '*') {\n if (node.wildcard) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard \"*\" segment already exists at path: ${`/${segments.slice(0, i).join('/')}`}`);\n }\n node.wildcard = new WildcardSegmentNode(segment, value);\n if (i < l - 1) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A wildcard segment must be the last segment`);\n }\n return;\n }\n else {\n let childNode = node.children[segment];\n if (!childNode) {\n childNode = new LiteralSegmentNode(segment);\n node.children[segment] = childNode;\n } // else // a literal segment already exists\n node = childNode;\n }\n }\n if (node.value !== undefined) {\n throw new Error(`Failed to index path segments: ${segments.join('/')}. A value already exists at path: ${`/${segments.join('/')}`}`);\n }\n node.value = value;\n }\n match(path) {\n const segments = toSegments(path);\n if (segments.length === 0) {\n return null;\n }\n const params = {};\n let node = this.tree;\n for (const segment of segments) {\n const match = node.match(segment, params);\n if (match) {\n node = match;\n }\n else {\n return null;\n }\n }\n if (!node.value) {\n // not a leaf node (partial match)\n if (node instanceof ParentSegmentNode) {\n if (node.wildcard instanceof WildcardSegmentNode) {\n node = node.wildcard.match('', params);\n if (!node.value) {\n throw new Error('Wildcard segment node `*` must have a value');\n }\n }\n }\n if (!node.value)\n return null; // not a leaf node, neither a trailing wildcard (partial match)\n }\n let matchedSegments, remainingSegments;\n if (params._ && params._.length > 0) {\n matchedSegments = segments.slice(0, -params._.length);\n remainingSegments = params._;\n }\n else {\n matchedSegments = segments;\n }\n return { params, matchedSegments, remainingSegments, value: node.value };\n }\n}\nclass ParentSegmentNode {\n name;\n value;\n children = {};\n wildcard;\n constructor(name, value) {\n this.name = name;\n this.value = value;\n }\n match(segment, params) {\n const node = this.children[segment];\n if (node) {\n return node;\n }\n else if (this.wildcard) {\n if (this.wildcard instanceof WildcardSegmentNode) {\n return this.wildcard.match(segment, params);\n }\n else if (this.wildcard instanceof VariableSegmentNode) {\n params[this.wildcard.paramName] = segment;\n return this.wildcard;\n }\n else {\n throw new Error(`Unknown wildcard segment node type: ${this.wildcard.constructor.name}`);\n }\n }\n else {\n return null;\n }\n }\n}\nclass RootSegmentNode extends ParentSegmentNode {\n constructor() {\n super('#root');\n }\n}\nclass LiteralSegmentNode extends ParentSegmentNode {\n}\nclass VariableSegmentNode extends ParentSegmentNode {\n paramName;\n constructor(name, value) {\n super(name, value);\n this.paramName = name.substring(1);\n }\n}\nclass WildcardSegmentNode {\n name;\n value;\n constructor(name, value) {\n this.name = name;\n this.value = value;\n }\n match(segment, params) {\n if (!params._) {\n params._ = segment ? [segment] : [];\n }\n else {\n if (segment)\n params._.push(segment);\n }\n return this;\n }\n}\n//# sourceMappingURL=PathMatcher.js.map","import { createContext, useContext, useEffect } from 'react';\nimport { HistoryNavigator } from './HistoryNavigator';\nimport { PathMatcher } from './PathMatcher';\nimport { getMountBasename, isRootPath, joinPath, stripMountBasename } from './path';\nexport class BaseRouter {\n // the path to use when navigating to the root of the router\n index;\n matcher = new PathMatcher();\n constructor(routes, index) {\n this.index = index;\n for (const route of routes) {\n this.matcher.addPath(route.path, route);\n }\n }\n match(path) {\n const useIndex = isRootPath(path) && this.index;\n return this.matcher.match(useIndex || path);\n }\n}\nexport class Router extends BaseRouter {\n prompt;\n observer;\n navigator = new HistoryNavigator();\n constructor(routes, updateState) {\n super(routes);\n this.navigator.addListener((event) => {\n if (event.isCancelable && this.prompt?.when) {\n if (!window.confirm(this.prompt.message))\n return;\n }\n if (this.observer) {\n this.observer(event);\n }\n // only process afterChange events\n if (event.name === 'afterChange') {\n // Match app-relative: strip the served `<base href>` mount prefix (no-op when origin-served).\n const match = this.match(stripMountBasename(event.location.pathname));\n if (match?.value) {\n updateState({\n ...match,\n state: event.state,\n });\n }\n else {\n updateState(null);\n }\n }\n });\n }\n getTopRouter() {\n return this;\n }\n /**\n * Subsequent navigations will preserve the given params in the query string.\n * Use null to clear the sticky params.\n * @param params\n */\n setStickyParams(params) {\n this.navigator.stickyParams = params != null ? params : undefined;\n // Reflect the params in the current URL immediately, so the address bar is correct on\n // load (not only after the first navigation).\n this.navigator.normalizeCurrentUrl();\n }\n withObserver(observer) {\n this.observer = observer;\n return this;\n }\n start() {\n this.navigator.start();\n // initialize with the current location\n this.navigator.firePageLoad();\n }\n stop() {\n this.navigator.stop();\n }\n navigate(path, options) {\n this.navigator.navigate(path, options);\n }\n}\nexport class NestedRouter extends BaseRouter {\n parent;\n basePath;\n constructor(parent, basePath, routes) {\n super(routes);\n this.parent = parent;\n this.basePath = basePath;\n }\n getTopRouter() {\n if (this.parent instanceof Router) {\n return this.parent;\n }\n else {\n return this.parent.getTopRouter();\n }\n }\n navigate(path, options) {\n // base path is nested by default in a NestedRouter unless explicitly set to false by caller\n const isBasePathNested = options?.isBasePathNested ?? true;\n let basePath;\n if (isBasePathNested) {\n const childBasePath = options?.basePath;\n // e.g. \"/store\" + \"/objects/123\" => \"/store/objects/123\"\n basePath = childBasePath ? joinPath(this.basePath, childBasePath) : this.basePath;\n this.parent.navigate(path, {\n ...options,\n basePath,\n });\n }\n else {\n // isBasePathNested === false: navigate to an absolute path without adding this router's basePath\n // Pass through to parent without adding our basePath prefix\n this.parent.navigate(path, {\n ...options,\n basePath: options?.basePath,\n });\n }\n }\n}\nconst ReactRouterContext = createContext(undefined);\nexport { ReactRouterContext };\nexport function useRouterContext() {\n const ctx = useContext(ReactRouterContext);\n if (!ctx) {\n throw new Error('useRouter must be used within a RouterProvider');\n }\n return ctx;\n}\nexport function useNavigate() {\n const { navigate } = useRouterContext();\n return navigate;\n}\nexport function useRouterBasePath() {\n const { router } = useRouterContext();\n // The base path apps prepend to build absolute in-app links (e.g. `${base}/items/${id}`). It MUST\n // include the served `<base href>` mount so links stay on the mount and match the full\n // `useLocation().pathname` (which carries the mount). `getMountBasename()` is '' for the\n // origin-served Studio UI and the mount (no trailing slash) for gateway-served apps.\n const mount = getMountBasename();\n if (router instanceof NestedRouter) {\n // NestedRouter.basePath is relative to the parent router, which sits at the mount, so it must\n // be mount-prefixed too. A bare nested base of '/' (an app whose NestedRouterProvider has no\n // basePath) would otherwise make `${base}/items` resolve to `//items` — a protocol-relative\n // URL that escapes the app. Origin-served Studio (mount '') keeps the raw nested basePath.\n if (!mount)\n return router.basePath;\n return router.basePath === '/' ? mount : joinPath(mount, router.basePath);\n }\n return mount;\n}\nexport function useParams(arg) {\n const { params } = useRouterContext();\n if (arg) {\n return params[arg];\n }\n else {\n return params;\n }\n}\nexport function useLocation() {\n const { location } = useRouterContext();\n return location;\n}\nexport function usePageTitle(title) {\n useEffect(() => {\n const prev = document.title;\n document.title = title;\n return () => {\n document.title = prev;\n };\n }, [title]);\n}\nexport function useNavigationPrompt(prompt) {\n const { router } = useRouterContext();\n const topRouter = router.getTopRouter();\n useEffect(() => {\n topRouter.prompt = prompt;\n return () => {\n topRouter.prompt = undefined;\n };\n }, [prompt, topRouter]);\n useEffect(() => {\n if (prompt.when) {\n const doBlock = prompt.when;\n const listener = (ev) => {\n if (doBlock) {\n ev.preventDefault();\n ev.returnValue = '';\n }\n };\n window.addEventListener('beforeunload', listener);\n return () => {\n window.removeEventListener('beforeunload', listener);\n };\n }\n }, [prompt.when]);\n}\n//# sourceMappingURL=Router.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { withMountBasename } from './path';\nimport { useNavigate, useRouterContext } from './Router';\n/**\n * True when the click carries a modifier the browser uses for alternate link behavior\n * (open in new tab/window, download) or is not a primary-button click. Such clicks must fall\n * through to the native anchor so the browser can handle them instead of the SPA router.\n */\nfunction isModifiedClick(ev) {\n return ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey || ev.button !== 0;\n}\nexport function Nav({ children, to, onClick, replace = true }) {\n const navigate = useNavigate();\n const _onClick = (ev) => {\n const link = ev.target.closest('a');\n const rawHref = link?.getAttribute('href');\n const target = to ?? rawHref;\n if (link && target) {\n ev.stopPropagation();\n ev.preventDefault();\n navigate(target, { replace });\n onClick?.(ev);\n }\n };\n return (_jsx(\"span\", { onClick: _onClick, children: children }));\n}\nexport function NavLink({ children, href, className, target, topLevelNav, clearBreadcrumbs = false, replace, skipStickyParams, }) {\n const { router } = useRouterContext();\n // Resolve internal URLs even when a target makes navigation native. New-tab links still need\n // the mount path and tenant sticky params, but must not be intercepted by the SPA router.\n const isAnchorOrEmpty = !href || href.startsWith('#');\n const isExternalUrl = /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith('//');\n const isInternalUrl = !isAnchorOrEmpty && !isExternalUrl;\n const isNativeNavigation = !!target && target !== '_self';\n // Keep the rendered href under the served `<base href>` mount (correct middle-click / hover /\n // open-in-new-tab); the onClick navigates via the router which applies the same rule. No-op when\n // origin-served (Studio UI). Click handler below passes the raw `href` — navigate() re-bases it.\n const resolvedHref = isInternalUrl\n ? withMountBasename(!skipStickyParams ? router.getTopRouter().navigator.addStickyParams(href) : href)\n : href;\n const _onClick = (ev) => {\n if (ev.defaultPrevented || !isInternalUrl || isNativeNavigation || isModifiedClick(ev)) {\n return;\n }\n ev.stopPropagation();\n ev.preventDefault();\n const actualRouter = topLevelNav ? router.getTopRouter() : router;\n actualRouter.navigate(href, { replace: replace ?? clearBreadcrumbs });\n };\n return (_jsx(\"a\", { href: resolvedHref, className: className, target: target, onClick: _onClick, children: children }));\n}\n//# sourceMappingURL=Nav.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect, useState } from 'react';\nimport { useRouterContext, } from './Router';\n// Resolved lazy modules, keyed by the route's LazyComponent function (a stable identity: route\n// tables are declared once). A revisited lazy route renders synchronously from this cache instead\n// of unmounting to the spinner for the async import() round-trip — without it, every navigation\n// between two lazy routes blanks the page for at least a frame, even when the module is loaded.\nconst resolvedComponents = new Map();\nasync function resolveLazyRoute(route) {\n const module = await route.LazyComponent();\n if (!module?.default) {\n throw new Error(`Lazy module for ${route.path} does not have a default export`);\n }\n resolvedComponents.set(route.LazyComponent, module.default);\n return module.default;\n}\n/**\n * Start loading the given routes' lazy modules ahead of navigation (non-lazy routes are ignored).\n * Call it during idle time after first paint: the first navigation to a prefetched route then\n * renders synchronously instead of flashing the spinner while its chunk downloads. Failures are\n * swallowed — navigation retries the import and reports the error the normal way.\n */\nexport function prefetchLazyRoutes(routes) {\n return Promise.allSettled(routes\n .filter((route) => !!route.LazyComponent)\n .map((route) => resolveLazyRoute(route)));\n}\nexport function RouteComponent({ spinner }) {\n const ctx = useRouterContext();\n const route = ctx.route;\n if (route.Component) {\n const Component = route.Component;\n return _jsx(Component, { ...ctx.params });\n }\n else if (route.LazyComponent) {\n // Keyed per path so navigating between two lazy routes remounts: a reused instance would\n // keep rendering the previous route's component while the next import resolves.\n return _jsx(LazyRouteComponent, { route: route, spinner: spinner }, route.path);\n }\n else {\n throw new Error(`Invalid route for ${route.path}. Either Component or LazyCOmponent must be specified.`);\n }\n}\nfunction LazyRouteComponent({ route, spinner }) {\n const [Component, setComponent] = useState(() => resolvedComponents.get(route.LazyComponent) ?? null);\n const [error, setError] = useState();\n useEffect(() => {\n // A slow import must not land after this instance moved on (unmount, or a route object\n // swap without a path change): the stale module would overwrite the current one.\n let stale = false;\n void resolveLazyRoute(route).then((component) => {\n if (!stale)\n setComponent(() => component);\n }, (error) => {\n // Render failures through the surrounding error boundary, including import failures.\n if (!stale)\n setError(() => error);\n });\n return () => {\n stale = true;\n };\n }, [route]);\n if (error !== undefined)\n throw error;\n return Component ? _jsx(Component, {}) : spinner || null;\n}\n//# sourceMappingURL=RouteComponent.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { FixLinks } from './FixLinks';\nimport { joinPath } from './path';\nimport { RouteComponent } from './RouteComponent';\nimport { ReactRouterContext, useRouterContext } from './Router';\nexport function NestedNavigationContext({ basePath, isBasePathNested = true, fixLinks = false, children, }) {\n const ctx = useRouterContext();\n const wrapWithFixLinks = fixLinks\n ? (elem) => _jsx(FixLinks, { basePath: ctx.matchedRoutePath, children: elem })\n : (elem) => elem;\n return (_jsx(ReactRouterContext.Provider, { value: {\n ...ctx,\n navigate: (to, options) => {\n if (options?.isBasePathNested === false) {\n // Navigate to an absolute path without adding this context's basePath\n return ctx.navigate(to, options);\n }\n const actualBasePath = options?.basePath ? joinPath(basePath, options.basePath) : basePath;\n return ctx.navigate(to, { ...options, basePath: actualBasePath, isBasePathNested });\n },\n }, children: wrapWithFixLinks(children ? children : _jsx(RouteComponent, {})) }));\n}\n//# sourceMappingURL=NestedNavigationContext.js.map","import { jsx as _jsx, jsxs as _jsxs } from \"react/jsx-runtime\";\nimport { useRouterContext } from './Router';\nexport function Route404Component() {\n const ctx = useRouterContext();\n return _jsxs(\"div\", { children: [\"Route not found for path \", ctx.matchedRoutePath] });\n}\nexport function createRoute404() {\n return {\n params: {},\n matchedSegments: [],\n state: null,\n value: {\n path: 'virtual:404',\n Component: () => _jsx(Route404Component, {}),\n },\n };\n}\n//# sourceMappingURL=Route404.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useMemo, useRef } from 'react';\nimport { FixLinks } from './FixLinks';\nimport { createRoute404 } from './Route404';\nimport { RouteComponent } from './RouteComponent';\nimport { NestedRouter, ReactRouterContext, useRouterContext } from './Router';\nexport function NestedRouterProvider({ routes, index, children, fixLinks = false }) {\n const ctx = useRouterContext();\n // Capture basePath once at mount. When the parent router switches to a different\n // top-level route (e.g. /store -> /studio), the lazy loader briefly keeps rendering\n // this (now-stale) module with a new ctx. Keeping basePath stable lets the\n // ctx.matchedRoutePath !== nestedRouter.basePath check below detect the mismatch and\n // skip rendering instead of running match() against the wrong route table.\n const basePathRef = useRef(ctx.matchedRoutePath);\n const nestedRouter = useMemo(() => {\n if (typeof window === 'undefined')\n return null;\n const nestedRouter = new NestedRouter(ctx.router, basePathRef.current, routes);\n nestedRouter.index = index;\n return nestedRouter;\n }, [ctx.router, index, routes]);\n const nestedRouteMatch = useMemo(() => {\n if (!nestedRouter) {\n return undefined;\n }\n if (ctx.matchedRoutePath !== nestedRouter.basePath) {\n // The change belongs to another router level and will be handled there.\n return undefined;\n }\n return nestedRouter.match(ctx.remainingPath || '/') || createRoute404();\n }, [ctx.matchedRoutePath, ctx.remainingPath, nestedRouter]);\n const wrapWithFixLinks = fixLinks\n ? (elem) => _jsx(FixLinks, { basePath: ctx.matchedRoutePath, children: elem })\n : (elem) => elem;\n return (nestedRouter &&\n nestedRouteMatch && (_jsx(ReactRouterContext.Provider, { value: {\n ...ctx,\n router: nestedRouter,\n route: nestedRouteMatch.value,\n params: nestedRouteMatch.params,\n matchedRoutePath: `/${nestedRouteMatch.matchedSegments.join('/')}`,\n remainingPath: nestedRouteMatch.remainingSegments\n ? `/${nestedRouteMatch.remainingSegments.join('/')}`\n : undefined,\n navigate: (to, options) => {\n if (nestedRouter) {\n return nestedRouter.navigate(to, options);\n }\n },\n }, children: wrapWithFixLinks(children ? children : _jsx(RouteComponent, {})) })));\n}\n//# sourceMappingURL=NestedRouterProvider.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useEffect } from 'react';\nimport { useNavigate } from './Router';\nexport function Redirect({ to, replace = true, state }) {\n const navigate = useNavigate();\n useEffect(() => {\n navigate(to, { replace, state });\n }, [navigate, replace, state, to]);\n return null;\n}\n/**\n * Creates a route component that redirects to another route when rendered.\n * Useful in route tables, for example: `{ path: '/', Component: redirectTo('/content') }`.\n */\nexport function redirectTo(to, options = {}) {\n return function RedirectRoute() {\n return _jsx(Redirect, { to: to, replace: options.replace, state: options.state });\n };\n}\n//# sourceMappingURL=Redirect.js.map","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useSafeLayoutEffect } from '@vertesia/ui/core';\nimport { useMemo, useState } from 'react';\nimport { createRoute404 } from './Route404';\nimport { RouteComponent } from './RouteComponent';\nimport { ReactRouterContext, Router } from './Router';\nexport function RouterProvider({ routes, index, onChange, children }) {\n const [state, setState] = useState(undefined);\n const router = useMemo(() => {\n if (typeof window === 'undefined')\n return null;\n const router = new Router(routes, (match) => {\n if (match === null) {\n match = createRoute404();\n }\n setState({\n location: window.location,\n route: match.value,\n params: match.params,\n state: match.state,\n router: router,\n matchedRoutePath: `/${match.matchedSegments.join('/')}`,\n remainingPath: match.remainingSegments ? `/${match.remainingSegments.join('/')}` : undefined,\n navigate: (to, options) => {\n return router.navigate(to, options);\n },\n });\n }).withObserver(onChange);\n router.index = index;\n return router;\n }, [index, onChange, routes]);\n useSafeLayoutEffect(() => {\n router?.start();\n return () => {\n router?.stop();\n };\n }, [router]);\n return (state && (_jsx(ReactRouterContext.Provider, { value: state, children: children ? children : _jsx(RouteComponent, {}) })));\n}\n//# sourceMappingURL=RouterProvider.js.map"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{NO_ACCESSIBLE_ACCOUNT_ERROR_CODE as e,REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE as t,RESTRICTED_ENVIRONMENT_ERROR_CODE as n}from"@vertesia/common";import{Env as r}from"@vertesia/ui/env";import{jwtDecode as i}from"jwt-decode";import{getAnalytics as a,logEvent as o}from"firebase/analytics";import{initializeApp as s}from"firebase/app";import{getAuth as c,onAuthStateChanged as l}from"firebase/auth";import{createContext as u,useCallback as d,useContext as f,useEffect as p,useMemo as m,useRef as h,useState as g}from"react";import{NAMESPACE as _,i18nInstance as v}from"@vertesia/ui/i18n";import{VertesiaClient as y}from"@vertesia/client";import{jsx as b}from"react/jsx-runtime";const x=`composableai.lastSelectedAccountId`,S=`composableai.lastSelectedProjectId`,C=`composableai.tabAccountId`,w=`composableai.tabProjectId`;function T(e){try{return sessionStorage.getItem(e)??void 0}catch{return}}function E(e,t){try{t?sessionStorage.setItem(e,t):sessionStorage.removeItem(e)}catch{}}function D(e){let t=T(C),n=e??t??localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0;return{accountId:n,projectId:(t&&t===n?T(w):localStorage.getItem(`composableai.lastSelectedProjectId-${n}`)??void 0)||void 0}}function O(e,t){E(C,e),E(w,t),localStorage.setItem(x,e),localStorage.setItem(`${S}-${e}`,t??``)}function ee(){E(C,void 0),E(w,void 0)}function te(e,t){T(C)===e&&(!t||T(w)===t)&&ee();let n=`${S}-${e}`;if(t){let r=localStorage.getItem(n)===t;r&&localStorage.removeItem(n),r&&localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&localStorage.removeItem(x);return}localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&(localStorage.removeItem(x),localStorage.removeItem(n))}const ne=`auth_state`,re=`auth_state_expiry`;function ie(){let e=crypto.randomUUID();return sessionStorage.setItem(ne,e),sessionStorage.setItem(re,String(Date.now()+3e5)),e}function ae(e){if(!e)return`Missing state`;let t=sessionStorage.getItem(ne),n=parseInt(sessionStorage.getItem(re)||`0`,10);if(t!==e)return`State mismatched (${t} !== ${e})`;if(Date.now()>n)return`State expired`}function oe(){sessionStorage.removeItem(ne),sessionStorage.removeItem(re)}function se(e,t){return`vtsauth=${e}; Path=/; Max-Age=${t}; SameSite=Lax${window.location.protocol===`https:`?`; Secure`:``}`}function ce(){document.cookie=se(`1`,300)}function le(){document.cookie=se(``,0)}function k(){if(typeof window>`u`||window.parent!==window)return!1;let e=window.__VERTESIA_RUNTIME_CONFIG__;return e?.authMode===`central`&&e.gatewaySession===!0}function ue(){let e=new URL(window.location.href),t=new URL(`/__appgen/auth/login`,e.origin);return t.searchParams.set(`target`,`${e.pathname}${e.search}${e.hash}`),t.toString()}async function de(e,t){let n=new Request(e,t);if(new URL(n.url).origin!==window.location.origin)throw Error(`Gateway session requests must stay on the application origin`);let r=new Headers(n.headers);r.delete(`authorization`),r.set(`x-vertesia-app-session`,`1`);let i=await fetch(new Request(n,{headers:r,credentials:`same-origin`,cache:`no-store`}));return i.status===401&&i.headers.get(`x-vertesia-session-required`)===`1`?(window.location.replace(ue()),new Promise(()=>{})):i}async function fe(){let e=await de(new URL(`/__appgen/session`,window.location.origin).toString());if(!e.ok)throw Error(`Application session could not be loaded (${e.status})`);let t=await e.json();if(!t.sub||!t.account?.id||!t.project?.id)throw Error(`Application session returned invalid user information`);return t}async function pe(){let e=await de(new URL(`/__appgen/session/logout`,window.location.origin).toString(),{method:`POST`});if(!e.ok)throw Error(`Application sign-out failed (${e.status})`)}function me(e,t){if(!e)return!1;let n=e.replace(/\/+$/,``);if(n===t.replace(/\/+$/,``))return!0;try{let e=new URL(t),r=/^token-server-dev-[a-z0-9-]+\.api\.(dev1|dev2)\.vertesia\.io$/.exec(e.hostname);return!(!r||e.protocol!==`https:`||e.port||e.username||e.password||e.pathname!==`/`||e.search||e.hash||n!==`https://sts.${r[1]}.vertesia.io`)}catch{return!1}}const A=`vertesia.oauth.transaction`,j=`vertesia.oauth.access`;let he,M;var ge=class extends Error{};function _e(){try{let e=new URLSearchParams(window.location.hash.slice(1)),t=e.get(`token`);return!t||ae(e.get(`state`))?!1:me(i(t).iss,r.endpoints.sts)}catch{return!1}}function N(){return!(!r.oauth||window.parent!==window||window.AUTH_MODE===`firebase`||k()||_e())}function ve(e){return btoa(String.fromCharCode(...e)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function ye(){return ve(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32)))}function P(e){let t=new URL(e);if(t.protocol!==`https:`||t.username||t.password)throw Error(`OAuth endpoint must use HTTPS`);return t}function be(){M=void 0,sessionStorage.removeItem(j),sessionStorage.removeItem(A)}async function xe(e=!1){let t=r.oauth;if(!t)throw Error(`Application OAuth is not configured`);let n=t.clientId.trim();if(!n)throw Error(`OAuth client ID is required`);let a=new URL(t.redirectUri),o=a.hostname===`localhost`||a.hostname.endsWith(`.localhost`)||a.hostname===`[::1]`||/^127\.\d+\.\d+\.\d+$/.test(a.hostname);if(a.protocol!==`https:`&&!(o&&a.protocol===`http:`))throw Error(`OAuth callback must use HTTPS or loopback HTTP`);let s=a.toString();if(new URL(s).origin!==window.location.origin)throw Error(`OAuth callback must be same-origin`);let c=r.endpoints.sts.replace(/\/+$/,``),l=new URL(window.location.href),u=l.origin+l.pathname===new URL(s).origin+new URL(s).pathname,d=u?l.searchParams.get(`state`):null,f=u?l.searchParams.get(`code`):null,p=u?l.searchParams.get(`error`):null,m,h;if(d||f||p){let e=sessionStorage.getItem(A);if(sessionStorage.removeItem(A),h=e?JSON.parse(e):void 0,!h||h.state!==d||h.clientId!==n||h.redirectUri!==s||h.issuer!==c||Date.now()-h.created>6e5||h.created>Date.now())throw Error(`Invalid or expired OAuth login state`);if(p||!f)throw Error(`Application sign-in was not completed (${p||`missing code`})`)}else{let r=sessionStorage.getItem(j);if(r){let a=JSON.parse(r),o=i(a.token);if(t.offlineAccess&&a.clientId===n&&a.issuer===c&&(!l.searchParams.get(`p`)||o.project?.id===l.searchParams.get(`p`))&&(!l.searchParams.get(`a`)||o.account?.id===l.searchParams.get(`a`))&&(m=M?.clientId===n&&M.issuer===c?M.token:void 0),a.refreshToken&&sessionStorage.removeItem(j),a.clientId===n&&a.issuer===c&&!e&&o.exp>Date.now()/1e3+(t.offlineAccess?300:30)&&(!l.searchParams.get(`p`)||o.project?.id===l.searchParams.get(`p`))&&(!l.searchParams.get(`a`)||o.account?.id===l.searchParams.get(`a`)))return a.token}}let g=await fetch(`${c}/.well-known/oauth-authorization-server`);if(!g.ok)throw Error(`OAuth discovery failed (${g.status})`);let _=await g.json();if(_.issuer.replace(/\/+$/,``)!==c)throw Error(`OAuth issuer mismatch`);let v=P(_.authorization_endpoint),y=P(_.token_endpoint),b=_.revocation_endpoint===void 0?void 0:P(_.revocation_endpoint).toString(),x=new URL(_.issuer).toString();if(m){try{let e=await fetch(y,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`refresh_token`,client_id:n,refresh_token:m,resource:x})});if(e.ok){let t=await e.json();if(!t.access_token||t.token_type?.toLowerCase()!==`bearer`)throw new ge(`Invalid OAuth refresh grant`);let r=i(t.access_token);if(r.iss.replace(/\/+$/,``)!==c||r.client_id!==n||r.exp<=Date.now()/1e3||l.searchParams.get(`a`)&&r.account?.id!==l.searchParams.get(`a`)||l.searchParams.get(`p`)&&r.project?.id!==l.searchParams.get(`p`))throw new ge(`Invalid OAuth refresh identity`);return sessionStorage.setItem(j,JSON.stringify({token:t.access_token,clientId:n,issuer:c})),M={token:t.refresh_token??m,clientId:n,issuer:c,tokenEndpoint:y.toString(),revocationEndpoint:b},t.access_token}}catch{}M=void 0,sessionStorage.removeItem(j)}if(h&&f){let e=await fetch(y,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`authorization_code`,resource:x,code:f,client_id:n,redirect_uri:s,code_verifier:h.verifier})});if(!e.ok)throw Error(`OAuth code exchange failed (${e.status})`);let r=await e.json();if(!r.access_token||r.token_type?.toLowerCase()!==`bearer`)throw Error(`Invalid OAuth grant`);let a=i(r.access_token);if(a.iss.replace(/\/+$/,``)!==c||a.client_id!==n||a.exp<=Date.now()/1e3)throw Error(`OAuth grant does not match this application`);sessionStorage.setItem(j,JSON.stringify({token:r.access_token,clientId:n,issuer:c})),M=t.offlineAccess&&r.refresh_token?{token:r.refresh_token,clientId:n,issuer:c,tokenEndpoint:y.toString(),revocationEndpoint:b}:void 0;let o=new URL(h.target);if(o.origin!==window.location.origin)throw Error(`Invalid OAuth return target`);return a.account?.id?o.searchParams.set(`a`,a.account.id):o.searchParams.delete(`a`),a.project?.id?o.searchParams.set(`p`,a.project.id):o.searchParams.delete(`p`),o.pathname===`/auth/callback`&&(o.pathname=`/`),window.history.replaceState(window.history.state,``,o),r.access_token}let S=t.scopes??[`openid`,`profile`];if(n.startsWith(`https://`)){let e=await fetch(P(n),{cache:`no-store`});if(!e.ok)throw Error(`Application CIMD unavailable (${e.status})`);let r=await e.json();if(!r.redirect_uris?.includes(s))throw Error(`Application CIMD does not allow this callback`);!t.scopes&&r.scope&&(S=r.scope.split(/\s+/))}let C=ye(),w={state:ye(),verifier:C,clientId:n,redirectUri:s,issuer:c,target:l.toString(),created:Date.now()},T=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(C));v.searchParams.set(`client_id`,n),v.searchParams.set(`redirect_uri`,s),v.searchParams.set(`response_type`,`code`),v.searchParams.set(`resource`,x),v.searchParams.set(`state`,w.state),v.searchParams.set(`code_challenge_method`,`S256`),v.searchParams.set(`code_challenge`,ve(new Uint8Array(T))),v.searchParams.set(`scope`,(t.offlineAccess?[.../* @__PURE__ */ new Set([...S,`offline_access`])]:S.filter(e=>e!==`offline_access`)).join(` `));let E=l.searchParams.get(`a`);E&&v.searchParams.set(`account_id`,E);let D=l.searchParams.get(`p`);return D&&v.searchParams.set(`project_id`,D),sessionStorage.setItem(A,JSON.stringify(w)),ce(),window.location.replace(v.toString()),new Promise(()=>{})}function F(e=!1){return he??=xe(e).finally(()=>{he=void 0}),he}function Se(){return N()}const Ce=F;async function we(){let e=M;if(be(),!e)return;let t=P(e.revocationEndpoint??e.tokenEndpoint);e.revocationEndpoint===void 0&&(t.pathname=t.pathname.replace(/\/token$/,`/revoke`)),await fetch(t,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:e.clientId,token:e.token,token_type_hint:`refresh_token`})})}function I(){return r.endpoints.auth||`https://auth.vertesia.io/`}function Te(e){return window.AUTH_MODE===`firebase`}function L(e){return!Te()}function R(){let e=new URL(document.baseURI),t=new URL(window.location.href),n=t.pathname.startsWith(e.pathname)?t:e;return n.hash=``,n}function Ee(){let e=new URL(document.baseURI);return e.hash=``,e.search=``,e}function De(e,t,n,r,i={}){let a=new URL(n);i.projectId&&a.searchParams.set(`p`,i.projectId),i.accountId&&a.searchParams.set(`a`,i.accountId);let o=new URL(e);return o.searchParams.set(`sts`,t),o.searchParams.set(`redirect_uri`,a.toString()),o.searchParams.set(`state`,r),o}function z(e={}){if(N()){F().catch(e=>r.logger.error(`Application OAuth sign-in failed`,e));return}if(k()){window.location.replace(ue());return}let t=De(I(),r.endpoints.sts??`https://sts.vertesia.io`,R(),ie(),e);ce(),location.replace(t.toString())}function Oe(){if(k()||N()||!L()||r.authTokenProvider||r.isLocalDev&&r.devAuthToken)return!1;let e=new URLSearchParams(window.location.hash.substring(1));return!(e.get(`token`)&&e.get(`state`))}let ke=null,Ae=null,B=null;function je(){if(!ke)try{if(!r.firebase)throw Error(`Firebase configuration is not available in the environment`);ke=s(r.firebase)}catch(e){throw console.error(`Failed to initialize Firebase app:`,e),Error(`Firebase initialization failed - environment may not be properly initialized`,{cause:e})}return ke}function Me(){return Ae||=a(je()),Ae}function V(){return B||(B=c(je()),B.tenantId=r.firebase?.tenantId??null),B}async function Ne(e){if(r.firebase?.tenantId)return V().tenantId=r.firebase.tenantId,{firebaseTenantId:r.firebase.tenantId,provider:r.firebase.providerType??`oidc`,name:``,label:``};if(!e){r.logger.debug(`Skipping Firebase tenant setup because no tenant identity was provided`);return}if(!r.firebase){r.logger.debug(`Skipping Firebase tenant setup because Firebase is not configured`);return}try{r.logger.debug(`Resolving Firebase tenant`);let t=3,n=250;for(;t>0;)try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e}),signal:AbortSignal.timeout(5e3)});if(!t)throw Error(`No response received from tenant API`);if(!t.ok){if(t.status===404){r.logger.warn(`Firebase tenant was not found; continuing with the default tenant`,{vertesia:{status:t.status}});return}let e=await t.json().catch(()=>void 0);throw Error(e?.error??`HTTP error ${t.status}`)}let n=await t.json();if(n?.firebaseTenantId){let e=V();return e.tenantId=n.firebaseTenantId,r.firebase.providerType=n.provider??`oidc`,r.logger.debug(`Firebase tenant resolved`),n}r.logger.warn(`Firebase tenant response did not include a tenant ID`);return}catch(e){if(t>1)r.logger.debug(`Firebase tenant resolution failed; retrying`,{vertesia:{retry_delay_ms:n,attempts_remaining:t-1,error:e}}),await new Promise(e=>setTimeout(e,n)),n*=2,t--;else throw e}}catch(e){r.logger.warn(`Firebase tenant resolution failed; continuing with the default tenant`,{vertesia:{error:e}})}}async function Pe(e){let t=V().currentUser;return t?t.getIdToken(e).then(n=>(r.logger.debug(`Got Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e}}),n)).catch(n=>(r.logger.warn(`Failed to get Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e,error:n}}),null)):(r.logger.warn(`No user found`),Promise.resolve(null))}let H,U,W=!1;const Fe=`vt.centralAuthRenewalAt`;function Ie(){if(!W||!L())return!1;let e=0;try{e=Number(sessionStorage.getItem(Fe)??`0`)}catch{}if(Number.isFinite(e)&&e>0&&Date.now()-e<6e4)return r.logger.warn(`Central Auth session renewal already attempted; surfacing the failure instead`,{vertesia:{last_attempt_ms_ago:Date.now()-e}}),!1;try{sessionStorage.setItem(Fe,String(Date.now()))}catch{}r.logger.info(`Renewing an expired Central Auth session through the broker`);let t=De(I(),r.endpoints.sts??`https://sts.vertesia.io`,R(),ie());return location.replace(t.toString()),!0}function Le(e){try{let t=i(e);return typeof t.email!=`string`||!t.email?void 0:{email:t.email,name:typeof t.name==`string`&&t.name?t.name:void 0}}catch{return}}function Re(e){let t=e.searchParams.has(`a`)||e.searchParams.has(`p`)?void 0:r.defaultAuthSelection,n=e.searchParams.get(`a`)??t?.accountId,i=e.searchParams.get(`p`)??t?.projectId,a=i===void 0?D(n):void 0;return{accountId:n??a?.accountId,projectId:i??a?.projectId}}function G(e){return i(e)}function ze(e){if(!e)return!1;try{return me(G(e).iss,r.endpoints.sts)}catch{return!1}}function Be(e,t,n){let r=G(e),i=`client_id`in r&&typeof r.client_id==`string`&&r.client_id.startsWith(`vertesia-app:`);return!(!r.exp||r.exp<=Date.now()/1e3+(i?60:300)||!(r.permissions?.length||r.account_roles?.length||r.project_roles?.length||r.apps?.length)||t&&r.account?.id!==t||n&&r.project?.id!==n)}async function K(a,o,s,c,l=0){r.logger.debug(`Getting/refreshing composable token`,{vertesia:{account_id:o,project_id:s,retry_count:l}});let u=await a();if(!u)throw Error(`No id token found`);let d=r.endpoints.sts;r.logger.debug(`Using STS for token generation`,{vertesia:{account_id:o,project_id:s,sts_url:d}});try{let f=new URL(`${d}/token/issue`),p={type:`user`,account_id:o,project_id:s,expires_at:c?Math.floor(Date.now()/1e3)+c:void 0},m=await fetch(f,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${u}`},body:JSON.stringify(p)}).catch(e=>{throw console.error(`Failed to call STS endpoint`,e),r.logger.error(`Failed to call STS endpoint`,{vertesia:{account_id:o,project_id:s,error:e}}),new $(`The authentication service could not be reached`,d,{cause:e})});if(u&&m?.status===404){r.logger.debug(`404: User not found - calling ensure-user endpoint`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=await fetch(`${r.endpoints.studio}/auth/ensure-user`,{method:`POST`,headers:{Authorization:`Bearer ${u}`,"Content-Type":`application/json`}});if(e.status===412){r.logger.debug(`412: No invite found - signup required`,{vertesia:{account_id:o,project_id:s}});let e=i(u);throw e?.email?new J(`User not found - signup required`,e.email):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(e.status===403)throw r.logger.warn(`403: Customer-domain user requires an invite to join`,{vertesia:{account_id:o,project_id:s}}),Error(`Customer-domain user requires an invite to join`);if(!e.ok)throw console.error(`Failed to ensure user exists`,e.status),r.logger.error(`Failed to ensure user exists`,{vertesia:{account_id:o,project_id:s,status:e.status}}),Error(`Failed to ensure user exists`);return r.logger.debug(`User ensured - retrying token generation`,{vertesia:{account_id:o,project_id:s}}),K(a,o,s,c,l)}if(u&&m?.status===412){r.logger.info(`412: auth succeeded but user doesn't exist - signup required`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=i(u);throw e?.email?(r.logger.info(`User not found`,{vertesia:{account_id:o,project_id:s,email:e.email}}),new J(`User not found`,e.email)):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(m.status===401)throw r.logger.warn(`STS rejected the identity credential`,{vertesia:{account_id:o,project_id:s,status:m.status}}),new Q(`Your sign-in credentials could not be verified`,d,{status:m.status});if(m.status===403){let i=await m.json().catch(()=>void 0),a=Le(u);throw i?.errorCode===n?(r.logger.warn(`403: User lacks early-access for this restricted environment`,{vertesia:{account_id:o,project_id:s}}),new Xe(i.message??`You don't have sufficient permission to visit unstable environments`)):i?.errorCode===e?(r.logger.warn(`STS identity has no accessible account`,{vertesia:{error_code:i.errorCode,status:m.status}}),new Z(d,i.message,a)):!i?.errorCode||i.errorCode===t?(r.logger.warn(`STS rejected the requested account or project`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i?.errorCode??t}}),new X(d,o,s,i?.errorCode?i.message:void 0,a)):(r.logger.error(`STS returned an unrecognized forbidden response`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i.errorCode}}),new $(`The authentication service rejected the request`,d,{status:m.status,errorCode:i.errorCode,cause:i}))}if(!m.ok){let e=await m.text();throw console.error(`STS token generation failed:`,m.status,e),r.logger.error(`STS token generation failed`,{vertesia:{status:m.status,error:e,account_id:o,project_id:s}}),new $(`The authentication service could not complete sign-in`,d,{status:m.status,cause:e})}let{token:h}=await m.json();return r.logger.debug(`Successfully got token from STS`),h}catch(e){throw e instanceof J||e instanceof Y||e instanceof Xe||e instanceof Error&&e.message===`Customer-domain user requires an invite to join`?e:(console.error(`Failed to get composable token from STS`,e),r.logger.error(`Failed to get composable token from STS`,{vertesia:{account_id:o,project_id:s,error:e}}),new $(`The authentication service could not complete sign-in`,d,{cause:e}))}}async function Ve(e,t,n){return K(Pe,e,t,n)}async function He(e,t,n,r){return K(()=>Promise.resolve(e),t,n,r)}function Ue(){return H}function We(e){return U?.account?.id&&(!e||U.account.id===e)?{accountId:U.account.id,projectId:U.project?.id}:D(e)}async function q(e,t,n,i=!1,a=!1){let o=t===void 0?We(e):void 0,s=e??o?.accountId,c=t??o?.projectId,l=r.isLocalDev?r.devAuthToken:void 0,u=l??n??H,d=(!s||U?.account?.id===s)&&(!c||U?.project?.id===c);if(!i&&H&&U&&d&&U.exp>Date.now()/1e3+300)return W=!0,{rawToken:H,token:U,error:!1};if(!i&&ze(u)&&Be(u,s,c)){if(H=u,U=G(H),!U.exp)throw Error(`Invalid composable token`);return W=!0,{rawToken:H,token:U,error:!1}}try{if(!l&&!a&&V().currentUser)H=await Ve(s,c);else if(l)l&&(H=l);else{let e=await r.authTokenProvider?.(),t=e??n??H;H=(!i||e)&&t&&ze(t)&&Be(t,s,c)?t:t?await K(()=>Promise.resolve(t),s,c):void 0}}catch(e){throw(e instanceof X||e instanceof Z||e instanceof Q)&&(H=void 0,U=void 0,e instanceof X&&s&&te(s,c)),e instanceof Q&&Ie(),e}if(!H)throw r.logger.error(`Cannot acquire a composable token`,{vertesia:{account_id:s,project_id:c}}),Ie(),Error(`Cannot acquire a composable token`);if(U=G(H),!U?.exp||!H)throw console.error(`Invalid composable token`,U),r.logger.error(`Invalid composable token`,{vertesia:{account_id:s,project_id:c}}),Error(`Invalid composable token`);return W=!0,{rawToken:H,token:U,error:!1}}var J=class extends Error{email;constructor(e,t){super(e),this.name=`UserNotFoundError`,this.email=t}},Y=class extends Error{stsURL;status;errorCode;constructor(e,t,n){super(e,n),this.name=`STSError`,this.stsURL=t,this.status=n?.status,this.errorCode=n?.errorCode}},X=class extends Y{accountId;projectId;identity;requestedScope;selectorSource;recoveryUrl;constructor(e,n,r,i,a){super(i??`The requested account or project is not available.`,e,{status:403,errorCode:t}),this.accountId=n,this.projectId=r,this.identity=a,this.name=`RequestedScopeUnavailableError`,this.requestedScope=r?`project`:`account`}};const Ge=X;var Z=class extends Y{identity;constructor(t,n,r){super(n??`No accessible account is available for this user.`,t,{status:403,errorCode:e}),this.identity=r,this.name=`NoAccessibleAccountError`}},Q=class extends Y{constructor(e,t,n){super(e,t,n),this.name=`CredentialError`}},$=class extends Y{constructor(e,t,n){super(e,t,n),this.name=`AuthenticationServiceError`}};function Ke(e){return e instanceof X}function qe(e){return e instanceof Z}function Je(e){return e instanceof Q}function Ye(e){return e instanceof $}var Xe=class extends Error{constructor(e){super(e),this.name=`RestrictedEnvironmentError`}};function Ze(){return{generateState:d(()=>ie(),[]),verifyState:d(e=>ae(e),[]),clearState:d(()=>oe(),[])}}var Qe=class e{authMethod=`token`;isLoading=!0;client;authError;authToken;setSession;lastSelectedAccount;lastSelectedProject;onboardingComplete;constructor(e,t){this.client=e||new y({serverUrl:k()?`${window.location.origin}/__appgen/session/studio`:r.endpoints.studio,storeUrl:k()?`${window.location.origin}/__appgen/session/store`:r.endpoints.zeno,tokenServerUrl:r.endpoints.sts,fetch:k()?de:void 0}),t&&(this.setSession=t),this.logout=this.logout.bind(this),this.signOut=this.signOut.bind(this)}get store(){return this.client.store}get user(){return this.authToken}get account(){return this.authToken?.account}get project(){return this.authToken?.project}get accounts(){return this.authToken?.accounts}get authCallback(){return this.rawAuthToken.then(e=>`Bearer ${e}`)}get rawAuthToken(){return this.authMethod===`oauth`?F():k()?Promise.reject(/* @__PURE__ */ Error(`Gateway session credentials are not available to application JavaScript`)):q().then(e=>{let t=e?.rawToken;if(!t)throw Error(`No token available`);return this.adoptToken(t),t})}adoptToken(e){let t=i(e),n=this.authToken,a=!!n?.project&&n.project.id!==t.project?.id;if(n&&(n.account?.id!==t.account?.id||a))throw r.logger.warn(`Auth token scope changed under the session; reloading`,{vertesia:{account_id:n.account?.id,project_id:n.project?.id,next_account_id:t.account?.id,next_project_id:t.project?.id}}),location.reload(),Error(`The session account or project changed; reloading`);return this.authToken=t,t}async refreshAuthToken(){if(k()){let e=await this.loginGatewaySession();return this.setSession?.(this.clone()),e}if(this.authMethod===`oauth`)return this.authToken=i(await F(!0)),this.setSession?.(this.clone()),this.authToken;let e=(await q(void 0,void 0,void 0,!0))?.rawToken;if(!e)throw Error(`No token available`);let t=this.adoptToken(e);return this.setSession?.(this.clone()),t}signOut(){this.logout()}getAccount(){return this.authToken?.account}async login(e,t={}){return this.authMethod=t.authMethod??`token`,this.authError=void 0,this.isLoading=!1,this.client.withAuthCallback(()=>this.authCallback),this.authToken=i(e),console.log(`Logging in as ${this.authToken?.name} with account ${this.authToken?.account.name} (${this.authToken?.account.id}, and project ${this.authToken?.project?.name} (${this.authToken?.project?.id})`),O(this.authToken.account.id,this.authToken.project?.id),r.onLogin?.(this.authToken),t.loadOnboardingStatus&&await this.fetchOnboardingStatus(),Promise.resolve()}async loginGatewaySession(){return this.authToken=await fe(),this.client.withAuthCallback(void 0),this.authError=void 0,this.isLoading=!1,r.onLogin?.(this.authToken),this.authToken}isLoggedIn(){return!!this.authToken}logout(){if(console.log(`Logging out`),k()){pe().then(()=>{this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone())}).catch(e=>{this.authError=e instanceof Error?e:Error(String(e)),this.setSession?.(this.clone())});return}if(this.authMethod===`oauth`){we().catch(()=>void 0).finally(()=>{let e=new URL(I());e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,R().toString()),location.replace(e.toString())}),this.client.withAuthCallback(void 0),this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone());return}if(L()){console.log(`Using central auth logout`),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0);let e=new URL(I()),t=R();e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,t.toString()),location.replace(e.toString())}else{console.log(`Using Firebase logout`);let e=!!this.authToken;this.authToken&&V().signOut(),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0),e&&location.replace(Ee().toString())}}async switchAccount(e){localStorage.setItem(x,e),this&&(this.account&&this.project?localStorage.setItem(`${S}-${this.account.id}`,this.project.id):this.account&&localStorage.removeItem(`${S}-${this.account.id}`)),ee();let t=Ee();t.searchParams.set(`a`,e),window.location.replace(t.toString())}async switchProject(e){this.account&&O(this.account.id,e);let t=Ee();this.account?.id&&t.searchParams.set(`a`,this.account.id),t.searchParams.set(`p`,e),window.location.replace(t.toString())}async fetchAccounts(){return this.client.accounts.list().then(e=>{if(!this.authToken)throw Error(`No token available`);this.authToken.accounts=e,this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch accounts`,e),e})}async fetchProjects(e){return this.client.projects.list([e]).then(t=>{if(!this.authToken)throw Error(`No token available`);this.authToken={...this.authToken,accounts:this.authToken.accounts?.map(n=>n.id===e?{...n,projects:t.filter(t=>t.account===e)}:n)},this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch projects`,e),e})}async fetchOnboardingStatus(){if(!this.project?.id)return!1;if(this.onboardingComplete)return console.log(`Onboarding already completed`),!1;let e=this.onboardingComplete;try{let t=await this.client.account.onboardingProgress();return this.onboardingComplete=Object.values(t).every(e=>e===!0),e!==this.onboardingComplete&&this.setSession?.(this.clone()),e===!1&&this.onboardingComplete}catch(t){console.error(`Error fetching onboarding status:`,t),this.onboardingComplete=!1,e!==this.onboardingComplete&&this.setSession?.(this.clone())}return!1}clone(){let t=new e(this.client);return t.isLoading=this.isLoading,t.authError=this.authError,t.authToken=this.authToken,t.authMethod=this.authMethod,t.setSession=this.setSession,t.lastSelectedAccount=this.lastSelectedAccount,t.switchAccount=this.switchAccount,t.onboardingComplete=this.onboardingComplete,t}};const $e=u(void 0);function et(){let e=f($e);if(!e)throw Error(`useUserSession must be used within a UserSessionProvider`);return e}function tt(){let{user:e}=et(),[t,n]=g(null),[r,i]=g(!0),[a,o]=g(null);return p(()=>{(async()=>{if(!e?.email){n(null),i(!1);return}try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e.email})});if(t.ok){let e=await t.json();n(e?{tenantKey:e.name||`unknown`,name:e.label||e.name||`Unknown`,domain:e.domain||[],firebaseTenantId:e.firebaseTenantId,provider:e.provider,logo:e.logo}:null)}else n(null)}catch(e){console.error(`Error loading current tenant:`,e),o(v.getFixedT(null,_)(`errors.failedToLoadTenantConfig`)),n(null)}finally{i(!1)}})()},[e?.email]),{currentTenant:t,isLoading:r,error:a}}function nt(e){let[,t]=e.split(`.`);if(!t)throw Error(`Invalid Vertesia auth token`);let n=t.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(Math.ceil(t.length/4)*4,`=`);return JSON.parse(atob(n))}function rt({children:e,token:t}){let n=m(()=>{let e=new Qe;e.isLoading=!1;try{e.authToken=nt(t),e.client.withAuthCallback(()=>Promise.resolve(`Bearer ${t}`)),O(e.authToken.account.id,e.authToken.project?.id)}catch(t){e.authError=t instanceof Error?t:Error(String(t))}return e.clone()},[t]);return b($e.Provider,{value:n,children:e})}function it(){let e=new URL(window.location.href);e.hash=``,window.history.replaceState(window.history.state,``,`${e.pathname}${e.search}`)}function at(e,t,n=!1){let r=new URL(e),i=r.searchParams.get(`a`)??void 0,a=r.searchParams.get(`p`)??void 0;return i&&a&&i===t.accountId&&a===t.projectId?(r.searchParams.delete(`a`),r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):a&&a===t.projectId?(r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):i&&i===t.accountId?(r.searchParams.delete(`a`),t.requestedScope=`account`,t.selectorSource=`url`):(t.requestedScope=t.projectId?`project`:`account`,t.selectorSource=`persisted`),n&&(r.hash=``),t.recoveryUrl=r.toString(),r}function ot({children:e,loadOnboardingStatus:n=!1}){let i=new URLSearchParams(location.hash.substring(1)),a=i.get(`token`),o=i.get(`state`),[s,c]=g(new Qe),{verifyState:u,clearState:d}=Ze(),f=h(!1),m=h(void 0),_=(e,n=!1)=>{let i=at(new URL(window.location.href),e,n);window.history.replaceState(window.history.state,``,i),r.logger.warn(`Sanitized an unavailable authentication scope`,{vertesia:{account_id:e.accountId,project_id:e.projectId,error_code:t,selector_source:e.selectorSource,requested_scope:e.requestedScope,recovery_action:`url_sanitized`}})},v=(e,t=!1)=>e instanceof X||e instanceof Z||e instanceof Q||e instanceof $||e instanceof J||e instanceof Xe?(e instanceof X?_(e,t):t&&it(),s.isLoading=!1,s.authError=e,c(s.clone()),!0):!1;return m.current=()=>{if(f.current){r.logger.debug(`Skipping duplicate auth flow initiation`);return}f.current=!0,r.logger.debug(`Starting auth flow`);let{accountId:e,projectId:t}=Re(new URL(window.location.href));if(r.logger.debug(`Selected account and project`,{vertesia:{account_id:e,project_id:t}}),r.isLocalDev&&r.devAuthToken){s.setSession=c,q(e,t,r.devAuthToken).then(e=>s.login(e.rawToken).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Failed to initialize dev auth token`,n),r.logger.error(`Failed to initialize dev auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))});return}if(k()||N()){let e=!1;return s.setSession=c,(k()?s.loginGatewaySession():F().then(e=>s.login(e,{loadOnboardingStatus:n,authMethod:`oauth`}))).then(()=>{e||c(s.clone())}).catch(t=>{e||v(t)||(s.isLoading=!1,s.authError=t instanceof Error?t:Error(String(t)),c(s.clone()))}),()=>{e=!0,f.current=!1}}if(a&&o){s.setSession=c;let i=u(o);if(i){console.error(`Auth: invalid state: ${i}`),r.logger.error(`Invalid state: ${i}`,{vertesia:{state:o}}),d(),it(),z({accountId:e,projectId:t});return}d(),q(e,t,a,!1,L()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>{c(s.clone()),it()})).catch(n=>{v(n,!0)||(console.error(`Failed to fetch user token from studio, redirecting to central auth`,n),r.logger.error(`Failed to fetch user token from studio, redirecting to central auth`,{vertesia:{error:n}}),z({accountId:e,projectId:t}))});return}let i=!1,p,m=()=>{if(!i){if(window.parent!==window&&!r.allowLegacyIframeAuth){s.isLoading=!1,s.authError=/* @__PURE__ */ Error(`Embedded authentication requires a valid token from the host.`),c(s.clone());return}if(!s.isLoggedIn()){if(r.logger.debug(`Not logged in & no token/state`,{vertesia:{account_id:e,project_id:t}}),L()){r.logger.debug(`Redirecting to central auth with selection`,{vertesia:{account_id:e,project_id:t}}),z({accountId:e,projectId:t});return}r.logger.debug(`Host is in Firebase auth allowlist`,{vertesia:{account_id:e,project_id:t}})}p=l(V(),async i=>{i?(r.logger.debug(`Successful login with firebase`,{vertesia:{account_id:e,project_id:t}}),s.setSession=c,await q(e,t,void 0,!1,L()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Unexpected failure while fetching a user token`,n),r.logger.error(`Unexpected failure while fetching a user token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.logout(),s.isLoading=!1,s.authError=n,c(s.clone()))})):(r.logger.debug(`Using anonymous user`,{vertesia:{account_id:e,project_id:t}}),s.client.withAuthCallback(void 0),s.logout(),c(s.clone()))})}};return r.authTokenProvider?(s.setSession=c,r.authTokenProvider().then(async r=>{if(i)return;if(!r){m();return}let a=await q(e,t,r,!1,L());await s.login(a.rawToken,{loadOnboardingStatus:n}),i||c(s.clone())}).catch(n=>{i||v(n)||(console.warn(`Auth: failed to initialize injected auth token`,n),r.logger.warn(`Failed to initialize injected auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))}),()=>{i=!0,f.current=!1,p?.()}):(m(),()=>{i=!0,f.current=!1,p?.()})},p(()=>m.current?.(),[]),b($e.Provider,{value:s,children:e})}function st(){return{tagUserSession:async e=>{let t=window.localStorage.getItem(`composableSignupData`);if(!e){console.error(`No user found -- skipping tagging`);return}t&&window.localStorage.removeItem(`composableSignupData`)},trackEvent:(e,t)=>{r.isProd||console.debug(`track event`,e,t),r.firebase?.apiKey&&o(Me(),e,{...t,debug_mode:!r.isProd})}}}export{$ as AuthenticationServiceError,Q as CredentialError,rt as DevSessionProvider,x as LastSelectedAccountId_KEY,S as LastSelectedProjectId_KEY,Z as NoAccessibleAccountError,X as RequestedScopeUnavailableError,Xe as RestrictedEnvironmentError,Y as STSError,Ge as TokenAuthorizationError,J as UserNotFoundError,Qe as UserSession,$e as UserSessionContext,ot as UserSessionProvider,De as buildCentralAuthRedirectUrl,le as clearCentralAuthRoundTripMarker,K as fetchComposableToken,Ve as fetchComposableTokenFromFirebaseToken,He as fetchComposableTokenFromVertesiaToken,q as getComposableToken,Ue as getCurrentVertesiaToken,Me as getFirebaseAnalytics,je as getFirebaseApp,V as getFirebaseAuth,Pe as getFirebaseAuthToken,Se as isAppOAuthLoginPending,Ye as isAuthenticationServiceError,Oe as isCentralAuthRedirectPending,Je as isCredentialError,qe as isNoAccessibleAccountError,Ke as isRequestedScopeUnavailableError,z as redirectToCentralAuth,O as rememberScopeSelection,Re as resolveAuthSelection,at as sanitizeRejectedScopeUrl,Ne as setFirebaseTenant,Ce as startAppOAuthLogin,Ze as useAuthState,tt as useCurrentTenant,st as useUXTracking,et as useUserSession};
|
|
1
|
+
import{NO_ACCESSIBLE_ACCOUNT_ERROR_CODE as e,REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE as t,RESTRICTED_ENVIRONMENT_ERROR_CODE as n}from"@vertesia/common";import{Env as r}from"@vertesia/ui/env";import{jwtDecode as i}from"jwt-decode";import{getAnalytics as a,logEvent as o}from"firebase/analytics";import{initializeApp as s}from"firebase/app";import{getAuth as c,onAuthStateChanged as l}from"firebase/auth";import{createContext as u,useCallback as d,useContext as f,useEffect as p,useMemo as m,useRef as h,useState as g}from"react";import{NAMESPACE as _,i18nInstance as v}from"@vertesia/ui/i18n";import{VertesiaClient as ee}from"@vertesia/client";import{jsx as te}from"react/jsx-runtime";const y=`composableai.lastSelectedAccountId`,b=`composableai.lastSelectedProjectId`,x=`composableai.tabAccountId`,S=`composableai.tabProjectId`;function C(e){try{return sessionStorage.getItem(e)??void 0}catch{return}}function w(e,t){try{t?sessionStorage.setItem(e,t):sessionStorage.removeItem(e)}catch{}}function T(e){let t=C(x),n=e??t??localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0;return{accountId:n,projectId:(t&&t===n?C(S):localStorage.getItem(`composableai.lastSelectedProjectId-${n}`)??void 0)||void 0}}function ne(e){let t=e.searchParams.has(`a`)||e.searchParams.has(`p`)?void 0:r.defaultAuthSelection,n=e.searchParams.get(`a`)??t?.accountId,i=e.searchParams.get(`p`)??t?.projectId,a=i===void 0?T(n):void 0;return{accountId:n??a?.accountId,projectId:i??a?.projectId}}function E(e,t){w(x,e),w(S,t),localStorage.setItem(y,e),localStorage.setItem(`${b}-${e}`,t??``)}function D(){w(x,void 0),w(S,void 0)}function re(e,t){C(x)===e&&(!t||C(S)===t)&&D();let n=`${b}-${e}`;if(t){let r=localStorage.getItem(n)===t;r&&localStorage.removeItem(n),r&&localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&localStorage.removeItem(y);return}localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&(localStorage.removeItem(y),localStorage.removeItem(n))}const O=`auth_state`,k=`auth_state_expiry`;function ie(){let e=crypto.randomUUID();return sessionStorage.setItem(O,e),sessionStorage.setItem(k,String(Date.now()+3e5)),e}function ae(e){if(!e)return`Missing state`;let t=sessionStorage.getItem(O),n=parseInt(sessionStorage.getItem(k)||`0`,10);if(t!==e)return`State mismatched (${t} !== ${e})`;if(Date.now()>n)return`State expired`}function oe(){sessionStorage.removeItem(O),sessionStorage.removeItem(k)}function se(e,t){return`vtsauth=${e}; Path=/; Max-Age=${t}; SameSite=Lax${window.location.protocol===`https:`?`; Secure`:``}`}function ce(){document.cookie=se(`1`,300)}function le(){document.cookie=se(``,0)}function A(){if(typeof window>`u`||window.parent!==window)return!1;let e=window.__VERTESIA_RUNTIME_CONFIG__;return e?.authMode===`central`&&e.gatewaySession===!0}function ue(){let e=new URL(window.location.href),t=new URL(`/__appgen/auth/login`,e.origin);return t.searchParams.set(`target`,`${e.pathname}${e.search}${e.hash}`),t.toString()}async function de(e,t){let n=new Request(e,t);if(new URL(n.url).origin!==window.location.origin)throw Error(`Gateway session requests must stay on the application origin`);let r=new Headers(n.headers);r.delete(`authorization`),r.set(`x-vertesia-app-session`,`1`);let i=await fetch(new Request(n,{headers:r,credentials:`same-origin`,cache:`no-store`}));return i.status===401&&i.headers.get(`x-vertesia-session-required`)===`1`?(window.location.replace(ue()),new Promise(()=>{})):i}async function fe(){let e=await de(new URL(`/__appgen/session`,window.location.origin).toString());if(!e.ok)throw Error(`Application session could not be loaded (${e.status})`);let t=await e.json();if(!t.sub||!t.account?.id||!t.project?.id)throw Error(`Application session returned invalid user information`);return t}async function pe(){let e=await de(new URL(`/__appgen/session/logout`,window.location.origin).toString(),{method:`POST`});if(!e.ok)throw Error(`Application sign-out failed (${e.status})`)}function me(e,t){if(!e)return!1;let n=e.replace(/\/+$/,``);if(n===t.replace(/\/+$/,``))return!0;try{let e=new URL(t),r=/^token-server-dev-[a-z0-9-]+\.api\.(dev1|dev2)\.vertesia\.io$/.exec(e.hostname);return!(!r||e.protocol!==`https:`||e.port||e.username||e.password||e.pathname!==`/`||e.search||e.hash||n!==`https://sts.${r[1]}.vertesia.io`)}catch{return!1}}const j=`vertesia.oauth.transaction`,M=`vertesia.oauth.access`;let he,N;var ge=class extends Error{};function _e(){try{let e=new URLSearchParams(window.location.hash.slice(1)),t=e.get(`token`);return!t||ae(e.get(`state`))?!1:me(i(t).iss,r.endpoints.sts)}catch{return!1}}function ve(){return!(!r.oauth||window.parent!==window||window.AUTH_MODE===`firebase`||A()||_e())}function ye(e){return btoa(String.fromCharCode(...e)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function be(){return ye(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(32)))}function P(e){let t=new URL(e);if(t.protocol!==`https:`||t.username||t.password)throw Error(`OAuth endpoint must use HTTPS`);return t}function xe(){N=void 0,sessionStorage.removeItem(M),sessionStorage.removeItem(j)}async function Se(e=!1){let n=r.oauth;if(!n)throw Error(`Application OAuth is not configured`);let a=n.clientId.trim();if(!a)throw Error(`OAuth client ID is required`);let o=new URL(n.redirectUri),s=o.hostname===`localhost`||o.hostname.endsWith(`.localhost`)||o.hostname===`[::1]`||/^127\.\d+\.\d+\.\d+$/.test(o.hostname);if(o.protocol!==`https:`&&!(s&&o.protocol===`http:`))throw Error(`OAuth callback must use HTTPS or loopback HTTP`);let c=o.toString();if(new URL(c).origin!==window.location.origin)throw Error(`OAuth callback must be same-origin`);let l=(n.issuer?P(n.issuer).toString():r.endpoints.sts).replace(/\/+$/,``),u=new URL(window.location.href),{accountId:d,projectId:f}=ne(u),p=u.origin+u.pathname===new URL(c).origin+new URL(c).pathname,m=p?u.searchParams.get(`state`):null,h=p?u.searchParams.get(`code`):null,g=p?u.searchParams.get(`error`):null,_,v;if(m||h||g){let e=sessionStorage.getItem(j);if(sessionStorage.removeItem(j),v=e?JSON.parse(e):void 0,!v||v.state!==m||v.clientId!==a||v.redirectUri!==c||v.issuer!==l||Date.now()-v.created>6e5||v.created>Date.now())throw Error(`Invalid or expired OAuth login state`);if(g===t&&v.rememberedScope?.accountId){let e=new URL(v.target);if(e.origin!==window.location.origin)throw Error(`Invalid OAuth return target`);re(v.rememberedScope.accountId,v.rememberedScope.projectId),xe(),u=e,window.history.replaceState(window.history.state,``,u),d=v.retryScope?.accountId,f=void 0,v=void 0}else if(g||!h)throw Error(`Application sign-in was not completed (${g||`missing code`})`)}else{let t=sessionStorage.getItem(M);if(t){let r=JSON.parse(t),o=i(r.token);if(n.offlineAccess&&r.clientId===a&&r.issuer===l&&(!f||o.project?.id===f)&&(!d||o.account?.id===d)&&(_=N?.clientId===a&&N.issuer===l?N.token:void 0),r.refreshToken&&sessionStorage.removeItem(M),r.clientId===a&&r.issuer===l&&!e&&o.exp>Date.now()/1e3+(n.offlineAccess?300:30)&&(!f||o.project?.id===f)&&(!d||o.account?.id===d))return r.token}}let ee=new URL(l),te=new URL(`/.well-known/oauth-authorization-server${ee.pathname.replace(/\/$/,``)}`,ee.origin),y=await fetch(te);if(!y.ok)throw Error(`OAuth discovery failed (${y.status})`);let b=await y.json();if(b.issuer.replace(/\/+$/,``)!==l)throw Error(`OAuth issuer mismatch`);let x=P(b.authorization_endpoint),S=P(b.token_endpoint),C=b.revocation_endpoint===void 0?void 0:P(b.revocation_endpoint).toString(),w=n.resource?P(n.resource).toString():new URL(b.issuer).toString();if(_){try{let e=await fetch(S,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`refresh_token`,client_id:a,refresh_token:_,resource:w})});if(e.ok){let t=await e.json();if(!t.access_token||t.token_type?.toLowerCase()!==`bearer`)throw new ge(`Invalid OAuth refresh grant`);let n=i(t.access_token);if(n.iss.replace(/\/+$/,``)!==l||n.client_id!==a||n.exp<=Date.now()/1e3||d&&n.account?.id!==d||f&&n.project?.id!==f)throw new ge(`Invalid OAuth refresh identity`);return sessionStorage.setItem(M,JSON.stringify({token:t.access_token,clientId:a,issuer:l})),N={token:t.refresh_token??_,clientId:a,issuer:l,tokenEndpoint:S.toString(),revocationEndpoint:C},t.access_token}}catch{}N=void 0,sessionStorage.removeItem(M)}if(v&&h){let e=await fetch(S,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`authorization_code`,resource:w,code:h,client_id:a,redirect_uri:c,code_verifier:v.verifier})});if(!e.ok)throw Error(`OAuth code exchange failed (${e.status})`);let t=await e.json();if(!t.access_token||t.token_type?.toLowerCase()!==`bearer`)throw Error(`Invalid OAuth grant`);let r=i(t.access_token);if(r.iss.replace(/\/+$/,``)!==l||r.client_id!==a||r.exp<=Date.now()/1e3)throw Error(`OAuth grant does not match this application`);sessionStorage.setItem(M,JSON.stringify({token:t.access_token,clientId:a,issuer:l})),N=n.offlineAccess&&t.refresh_token?{token:t.refresh_token,clientId:a,issuer:l,tokenEndpoint:S.toString(),revocationEndpoint:C}:void 0;let o=new URL(v.target);if(o.origin!==window.location.origin)throw Error(`Invalid OAuth return target`);return r.account?.id?o.searchParams.set(`a`,r.account.id):o.searchParams.delete(`a`),r.project?.id?o.searchParams.set(`p`,r.project.id):o.searchParams.delete(`p`),o.pathname===`/auth/callback`&&(o.pathname=`/`),window.history.replaceState(window.history.state,``,o),t.access_token}let T=n.scopes??[`openid`,`profile`];if(a.startsWith(`https://`)){let e=await fetch(P(a),{cache:`no-store`});if(!e.ok)throw Error(`Application CIMD unavailable (${e.status})`);let t=await e.json();if(!t.redirect_uris?.includes(c))throw Error(`Application CIMD does not allow this callback`);!n.scopes&&t.scope&&(T=t.scope.split(/\s+/))}let E=u.searchParams.has(`a`)||u.searchParams.has(`p`)?{accountId:u.searchParams.get(`a`)??void 0,projectId:u.searchParams.get(`p`)??void 0}:r.defaultAuthSelection,D=be(),O={state:be(),verifier:D,clientId:a,redirectUri:c,issuer:l,target:u.toString(),rememberedScope:d&&E?.projectId===void 0&&(!E?.accountId||f)?{accountId:d,projectId:f}:void 0,retryScope:E?.accountId?{accountId:E.accountId}:void 0,created:Date.now()},k=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(D));return x.searchParams.set(`client_id`,a),x.searchParams.set(`redirect_uri`,c),x.searchParams.set(`response_type`,`code`),x.searchParams.set(`resource`,w),x.searchParams.set(`state`,O.state),x.searchParams.set(`code_challenge_method`,`S256`),x.searchParams.set(`code_challenge`,ye(new Uint8Array(k))),x.searchParams.set(`scope`,(n.offlineAccess?[.../* @__PURE__ */ new Set([...T,`offline_access`])]:T.filter(e=>e!==`offline_access`)).join(` `)),d&&x.searchParams.set(`account_id`,d),f&&x.searchParams.set(`project_id`,f),sessionStorage.setItem(j,JSON.stringify(O)),ce(),window.location.replace(x.toString()),new Promise(()=>{})}function F(e=!1){return he??=Se(e).finally(()=>{he=void 0}),he}function Ce(){return ve()}const we=F;async function Te(){let e=N;if(xe(),!e)return;let t=P(e.revocationEndpoint??e.tokenEndpoint);e.revocationEndpoint===void 0&&(t.pathname=t.pathname.replace(/\/token$/,`/revoke`)),await fetch(t,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({client_id:e.clientId,token:e.token,token_type_hint:`refresh_token`})})}function I(){return r.endpoints.auth||`https://auth.vertesia.io/`}function Ee(e){return window.AUTH_MODE===`firebase`}function L(e){return!Ee()}function R(){let e=new URL(document.baseURI),t=new URL(window.location.href),n=t.pathname.startsWith(e.pathname)?t:e;return n.hash=``,n}function De(){let e=new URL(document.baseURI);return e.hash=``,e.search=``,e}function Oe(e,t,n,r,i={}){let a=new URL(n);i.projectId&&a.searchParams.set(`p`,i.projectId),i.accountId&&a.searchParams.set(`a`,i.accountId);let o=new URL(e);return o.searchParams.set(`sts`,t),o.searchParams.set(`redirect_uri`,a.toString()),o.searchParams.set(`state`,r),o}function z(e={}){if(ve()){F().catch(e=>r.logger.error(`Application OAuth sign-in failed`,e));return}if(A()){window.location.replace(ue());return}let t=Oe(I(),r.endpoints.sts??`https://sts.vertesia.io`,R(),ie(),e);ce(),location.replace(t.toString())}function ke(){if(A()||ve()||!L()||r.authTokenProvider||r.isLocalDev&&r.devAuthToken)return!1;let e=new URLSearchParams(window.location.hash.substring(1));return!(e.get(`token`)&&e.get(`state`))}let Ae=null,je=null,B=null;function Me(){if(!Ae)try{if(!r.firebase)throw Error(`Firebase configuration is not available in the environment`);Ae=s(r.firebase)}catch(e){throw console.error(`Failed to initialize Firebase app:`,e),Error(`Firebase initialization failed - environment may not be properly initialized`,{cause:e})}return Ae}function Ne(){return je||=a(Me()),je}function V(){return B||(B=c(Me()),B.tenantId=r.firebase?.tenantId??null),B}async function Pe(e){if(r.firebase?.tenantId)return V().tenantId=r.firebase.tenantId,{firebaseTenantId:r.firebase.tenantId,provider:r.firebase.providerType??`oidc`,name:``,label:``};if(!e){r.logger.debug(`Skipping Firebase tenant setup because no tenant identity was provided`);return}if(!r.firebase){r.logger.debug(`Skipping Firebase tenant setup because Firebase is not configured`);return}try{r.logger.debug(`Resolving Firebase tenant`);let t=3,n=250;for(;t>0;)try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e}),signal:AbortSignal.timeout(5e3)});if(!t)throw Error(`No response received from tenant API`);if(!t.ok){if(t.status===404){r.logger.debug(`No Firebase tenant for this address; using the default tenant`);return}let e=await t.json().catch(()=>void 0);throw Error(e?.error??`HTTP error ${t.status}`)}let n=await t.json();if(n===null){r.logger.debug(`No Firebase tenant for this address; using the default tenant`);return}if(n.firebaseTenantId){let e=V();return e.tenantId=n.firebaseTenantId,r.firebase.providerType=n.provider??`oidc`,r.logger.debug(`Firebase tenant resolved`),n}r.logger.warn(`Firebase tenant response did not include a tenant ID`);return}catch(e){if(t>1)r.logger.debug(`Firebase tenant resolution failed; retrying`,{vertesia:{retry_delay_ms:n,attempts_remaining:t-1,error:e}}),await new Promise(e=>setTimeout(e,n)),n*=2,t--;else throw e}}catch(e){r.logger.warn(`Firebase tenant resolution failed; continuing with the default tenant`,{vertesia:{error:e}})}}async function Fe(e){let t=V().currentUser;return t?t.getIdToken(e).then(n=>(r.logger.debug(`Got Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e}}),n)).catch(n=>(r.logger.warn(`Failed to get Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e,error:n}}),null)):(r.logger.warn(`No user found`),Promise.resolve(null))}let H,U,W=!1;const Ie=`vt.centralAuthRenewalAt`;function Le(){if(!W||!L())return!1;let e=0;try{e=Number(sessionStorage.getItem(Ie)??`0`)}catch{}if(Number.isFinite(e)&&e>0&&Date.now()-e<6e4)return r.logger.warn(`Central Auth session renewal already attempted; surfacing the failure instead`,{vertesia:{last_attempt_ms_ago:Date.now()-e}}),!1;try{sessionStorage.setItem(Ie,String(Date.now()))}catch{}r.logger.info(`Renewing an expired Central Auth session through the broker`);let t=Oe(I(),r.endpoints.sts??`https://sts.vertesia.io`,R(),ie());return location.replace(t.toString()),!0}function Re(e){try{let t=i(e);return typeof t.email!=`string`||!t.email?void 0:{email:t.email,name:typeof t.name==`string`&&t.name?t.name:void 0}}catch{return}}function G(e){return i(e)}function ze(e){if(!e)return!1;try{return me(G(e).iss,r.endpoints.sts)}catch{return!1}}function Be(e,t,n){let r=G(e),i=`client_id`in r&&typeof r.client_id==`string`&&r.client_id.startsWith(`vertesia-app:`);return!(!r.exp||r.exp<=Date.now()/1e3+(i?60:300)||!(r.permissions?.length||r.account_roles?.length||r.project_roles?.length||r.apps?.length)||t&&r.account?.id!==t||n&&r.project?.id!==n)}async function K(a,o,s,c,l=0){r.logger.debug(`Getting/refreshing composable token`,{vertesia:{account_id:o,project_id:s,retry_count:l}});let u=await a();if(!u)throw Error(`No id token found`);let d=r.endpoints.sts;r.logger.debug(`Using STS for token generation`,{vertesia:{account_id:o,project_id:s,sts_url:d}});try{let f=new URL(`${d}/token/issue`),p={type:`user`,account_id:o,project_id:s,expires_at:c?Math.floor(Date.now()/1e3)+c:void 0},m=await fetch(f,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${u}`},body:JSON.stringify(p)}).catch(e=>{throw console.error(`Failed to call STS endpoint`,e),r.logger.error(`Failed to call STS endpoint`,{vertesia:{account_id:o,project_id:s,error:e}}),new $(`The authentication service could not be reached`,d,{cause:e})});if(u&&m?.status===404){r.logger.debug(`404: User not found - calling ensure-user endpoint`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=await fetch(`${r.endpoints.studio}/auth/ensure-user`,{method:`POST`,headers:{Authorization:`Bearer ${u}`,"Content-Type":`application/json`}});if(e.status===412){r.logger.debug(`412: No invite found - signup required`,{vertesia:{account_id:o,project_id:s}});let e=i(u);throw e?.email?new J(`User not found - signup required`,e.email):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(e.status===403)throw r.logger.warn(`403: Customer-domain user requires an invite to join`,{vertesia:{account_id:o,project_id:s}}),Error(`Customer-domain user requires an invite to join`);if(!e.ok)throw console.error(`Failed to ensure user exists`,e.status),r.logger.error(`Failed to ensure user exists`,{vertesia:{account_id:o,project_id:s,status:e.status}}),Error(`Failed to ensure user exists`);return r.logger.debug(`User ensured - retrying token generation`,{vertesia:{account_id:o,project_id:s}}),K(a,o,s,c,l)}if(u&&m?.status===412){r.logger.info(`412: auth succeeded but user doesn't exist - signup required`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=i(u);throw e?.email?(r.logger.info(`User not found`,{vertesia:{account_id:o,project_id:s,email:e.email}}),new J(`User not found`,e.email)):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(m.status===401)throw r.logger.warn(`STS rejected the identity credential`,{vertesia:{account_id:o,project_id:s,status:m.status}}),new Q(`Your sign-in credentials could not be verified`,d,{status:m.status});if(m.status===403){let i=await m.json().catch(()=>void 0),a=Re(u);throw i?.errorCode===n?(r.logger.warn(`403: User lacks early-access for this restricted environment`,{vertesia:{account_id:o,project_id:s}}),new Xe(i.message??`You don't have sufficient permission to visit unstable environments`)):i?.errorCode===e?(r.logger.warn(`STS identity has no accessible account`,{vertesia:{error_code:i.errorCode,status:m.status}}),new Z(d,i.message,a)):!i?.errorCode||i.errorCode===t?(r.logger.warn(`STS rejected the requested account or project`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i?.errorCode??t}}),new X(d,o,s,i?.errorCode?i.message:void 0,a)):(r.logger.error(`STS returned an unrecognized forbidden response`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i.errorCode}}),new $(`The authentication service rejected the request`,d,{status:m.status,errorCode:i.errorCode,cause:i}))}if(!m.ok){let e=await m.text();throw console.error(`STS token generation failed:`,m.status,e),r.logger.error(`STS token generation failed`,{vertesia:{status:m.status,error:e,account_id:o,project_id:s}}),new $(`The authentication service could not complete sign-in`,d,{status:m.status,cause:e})}let{token:h}=await m.json();return r.logger.debug(`Successfully got token from STS`),h}catch(e){throw e instanceof J||e instanceof Y||e instanceof Xe||e instanceof Error&&e.message===`Customer-domain user requires an invite to join`?e:(console.error(`Failed to get composable token from STS`,e),r.logger.error(`Failed to get composable token from STS`,{vertesia:{account_id:o,project_id:s,error:e}}),new $(`The authentication service could not complete sign-in`,d,{cause:e}))}}async function Ve(e,t,n){return K(Fe,e,t,n)}async function He(e,t,n,r){return K(()=>Promise.resolve(e),t,n,r)}function Ue(){return H}function We(e){return U?.account?.id&&(!e||U.account.id===e)?{accountId:U.account.id,projectId:U.project?.id}:T(e)}async function q(e,t,n,i=!1,a=!1){let o=t===void 0?We(e):void 0,s=e??o?.accountId,c=t??o?.projectId,l=r.isLocalDev?r.devAuthToken:void 0,u=l??n??H,d=(!s||U?.account?.id===s)&&(!c||U?.project?.id===c);if(!i&&H&&U&&d&&U.exp>Date.now()/1e3+300)return W=!0,{rawToken:H,token:U,error:!1};if(!i&&ze(u)&&Be(u,s,c)){if(H=u,U=G(H),!U.exp)throw Error(`Invalid composable token`);return W=!0,{rawToken:H,token:U,error:!1}}try{if(!l&&!a&&V().currentUser)H=await Ve(s,c);else if(l)l&&(H=l);else{let e=await r.authTokenProvider?.(),t=e??n??H;H=(!i||e)&&t&&ze(t)&&Be(t,s,c)?t:t?await K(()=>Promise.resolve(t),s,c):void 0}}catch(e){throw(e instanceof X||e instanceof Z||e instanceof Q)&&(H=void 0,U=void 0,e instanceof X&&s&&re(s,c)),e instanceof Q&&Le(),e}if(!H)throw r.logger.error(`Cannot acquire a composable token`,{vertesia:{account_id:s,project_id:c}}),Le(),Error(`Cannot acquire a composable token`);if(U=G(H),!U?.exp||!H)throw console.error(`Invalid composable token`,U),r.logger.error(`Invalid composable token`,{vertesia:{account_id:s,project_id:c}}),Error(`Invalid composable token`);return W=!0,{rawToken:H,token:U,error:!1}}var J=class extends Error{email;constructor(e,t){super(e),this.name=`UserNotFoundError`,this.email=t}},Y=class extends Error{stsURL;status;errorCode;constructor(e,t,n){super(e,n),this.name=`STSError`,this.stsURL=t,this.status=n?.status,this.errorCode=n?.errorCode}},X=class extends Y{accountId;projectId;identity;requestedScope;selectorSource;recoveryUrl;constructor(e,n,r,i,a){super(i??`The requested account or project is not available.`,e,{status:403,errorCode:t}),this.accountId=n,this.projectId=r,this.identity=a,this.name=`RequestedScopeUnavailableError`,this.requestedScope=r?`project`:`account`}};const Ge=X;var Z=class extends Y{identity;constructor(t,n,r){super(n??`No accessible account is available for this user.`,t,{status:403,errorCode:e}),this.identity=r,this.name=`NoAccessibleAccountError`}},Q=class extends Y{constructor(e,t,n){super(e,t,n),this.name=`CredentialError`}},$=class extends Y{constructor(e,t,n){super(e,t,n),this.name=`AuthenticationServiceError`}};function Ke(e){return e instanceof X}function qe(e){return e instanceof Z}function Je(e){return e instanceof Q}function Ye(e){return e instanceof $}var Xe=class extends Error{constructor(e){super(e),this.name=`RestrictedEnvironmentError`}};function Ze(){return{generateState:d(()=>ie(),[]),verifyState:d(e=>ae(e),[]),clearState:d(()=>oe(),[])}}var Qe=class e{authMethod=`token`;isLoading=!0;client;authError;authToken;setSession;lastSelectedAccount;lastSelectedProject;onboardingComplete;constructor(e,t){this.client=e||new ee({serverUrl:A()?`${window.location.origin}/__appgen/session/studio`:r.endpoints.studio,storeUrl:A()?`${window.location.origin}/__appgen/session/store`:r.endpoints.zeno,tokenServerUrl:r.endpoints.sts,fetch:A()?de:void 0}),t&&(this.setSession=t),this.logout=this.logout.bind(this),this.signOut=this.signOut.bind(this)}get store(){return this.client.store}get user(){return this.authToken}get account(){return this.authToken?.account}get project(){return this.authToken?.project}get accounts(){return this.authToken?.accounts}get authCallback(){return this.rawAuthToken.then(e=>`Bearer ${e}`)}get rawAuthToken(){return this.authMethod===`oauth`?F():A()?Promise.reject(/* @__PURE__ */ Error(`Gateway session credentials are not available to application JavaScript`)):q().then(e=>{let t=e?.rawToken;if(!t)throw Error(`No token available`);return this.adoptToken(t),t})}adoptToken(e){let t=i(e),n=this.authToken,a=!!n?.project&&n.project.id!==t.project?.id;if(n&&(n.account?.id!==t.account?.id||a))throw r.logger.warn(`Auth token scope changed under the session; reloading`,{vertesia:{account_id:n.account?.id,project_id:n.project?.id,next_account_id:t.account?.id,next_project_id:t.project?.id}}),location.reload(),Error(`The session account or project changed; reloading`);return this.authToken=t,t}async refreshAuthToken(){if(A()){let e=await this.loginGatewaySession();return this.setSession?.(this.clone()),e}if(this.authMethod===`oauth`)return this.authToken=i(await F(!0)),this.setSession?.(this.clone()),this.authToken;let e=(await q(void 0,void 0,void 0,!0))?.rawToken;if(!e)throw Error(`No token available`);let t=this.adoptToken(e);return this.setSession?.(this.clone()),t}signOut(){this.logout()}getAccount(){return this.authToken?.account}async login(e,t={}){return this.authMethod=t.authMethod??`token`,this.authError=void 0,this.isLoading=!1,this.client.withAuthCallback(()=>this.authCallback),this.authToken=i(e),console.log(`Logging in as ${this.authToken?.name} with account ${this.authToken?.account.name} (${this.authToken?.account.id}, and project ${this.authToken?.project?.name} (${this.authToken?.project?.id})`),E(this.authToken.account.id,this.authToken.project?.id),r.onLogin?.(this.authToken),t.loadOnboardingStatus&&await this.fetchOnboardingStatus(),Promise.resolve()}async loginGatewaySession(){return this.authToken=await fe(),this.client.withAuthCallback(void 0),this.authError=void 0,this.isLoading=!1,r.onLogin?.(this.authToken),this.authToken}isLoggedIn(){return!!this.authToken}logout(){if(console.log(`Logging out`),A()){pe().then(()=>{this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone())}).catch(e=>{this.authError=e instanceof Error?e:Error(String(e)),this.setSession?.(this.clone())});return}if(this.authMethod===`oauth`){Te().catch(()=>void 0).finally(()=>{let e=new URL(I());e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,R().toString()),location.replace(e.toString())}),this.client.withAuthCallback(void 0),this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone());return}if(L()){console.log(`Using central auth logout`),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0);let e=new URL(I()),t=R();e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,t.toString()),location.replace(e.toString())}else{console.log(`Using Firebase logout`);let e=!!this.authToken;this.authToken&&V().signOut(),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0),e&&location.replace(De().toString())}}async switchAccount(e){localStorage.setItem(y,e),this&&(this.account&&this.project?localStorage.setItem(`${b}-${this.account.id}`,this.project.id):this.account&&localStorage.removeItem(`${b}-${this.account.id}`)),D();let t=De();t.searchParams.set(`a`,e),window.location.replace(t.toString())}async switchProject(e){this.account&&E(this.account.id,e);let t=De();this.account?.id&&t.searchParams.set(`a`,this.account.id),t.searchParams.set(`p`,e),window.location.replace(t.toString())}async fetchAccounts(){return this.client.accounts.list().then(e=>{if(!this.authToken)throw Error(`No token available`);this.authToken.accounts=e,this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch accounts`,e),e})}async fetchProjects(e){return this.client.projects.list([e]).then(t=>{if(!this.authToken)throw Error(`No token available`);this.authToken={...this.authToken,accounts:this.authToken.accounts?.map(n=>n.id===e?{...n,projects:t.filter(t=>t.account===e)}:n)},this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch projects`,e),e})}async fetchOnboardingStatus(){if(!this.project?.id)return!1;if(this.onboardingComplete)return console.log(`Onboarding already completed`),!1;let e=this.onboardingComplete;try{let t=await this.client.account.onboardingProgress();return this.onboardingComplete=Object.values(t).every(e=>e===!0),e!==this.onboardingComplete&&this.setSession?.(this.clone()),e===!1&&this.onboardingComplete}catch(t){console.error(`Error fetching onboarding status:`,t),this.onboardingComplete=!1,e!==this.onboardingComplete&&this.setSession?.(this.clone())}return!1}clone(){let t=new e(this.client);return t.isLoading=this.isLoading,t.authError=this.authError,t.authToken=this.authToken,t.authMethod=this.authMethod,t.setSession=this.setSession,t.lastSelectedAccount=this.lastSelectedAccount,t.switchAccount=this.switchAccount,t.onboardingComplete=this.onboardingComplete,t}};const $e=u(void 0);function et(){let e=f($e);if(!e)throw Error(`useUserSession must be used within a UserSessionProvider`);return e}function tt(){let{user:e}=et(),[t,n]=g(null),[r,i]=g(!0),[a,o]=g(null);return p(()=>{(async()=>{if(!e?.email){n(null),i(!1);return}try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e.email})});if(t.ok){let e=await t.json();n(e?{tenantKey:e.name||`unknown`,name:e.label||e.name||`Unknown`,domain:e.domain||[],firebaseTenantId:e.firebaseTenantId,provider:e.provider,logo:e.logo}:null)}else n(null)}catch(e){console.error(`Error loading current tenant:`,e),o(v.getFixedT(null,_)(`errors.failedToLoadTenantConfig`)),n(null)}finally{i(!1)}})()},[e?.email]),{currentTenant:t,isLoading:r,error:a}}function nt(e){let[,t]=e.split(`.`);if(!t)throw Error(`Invalid Vertesia auth token`);let n=t.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(Math.ceil(t.length/4)*4,`=`);return JSON.parse(atob(n))}function rt({children:e,token:t}){let n=m(()=>{let e=new Qe;e.isLoading=!1;try{e.authToken=nt(t),e.client.withAuthCallback(()=>Promise.resolve(`Bearer ${t}`)),E(e.authToken.account.id,e.authToken.project?.id)}catch(t){e.authError=t instanceof Error?t:Error(String(t))}return e.clone()},[t]);return te($e.Provider,{value:n,children:e})}function it(){let e=new URL(window.location.href);e.hash=``,window.history.replaceState(window.history.state,``,`${e.pathname}${e.search}`)}function at(e,t,n=!1){let r=new URL(e),i=r.searchParams.get(`a`)??void 0,a=r.searchParams.get(`p`)??void 0;return i&&a&&i===t.accountId&&a===t.projectId?(r.searchParams.delete(`a`),r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):a&&a===t.projectId?(r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):i&&i===t.accountId?(r.searchParams.delete(`a`),t.requestedScope=`account`,t.selectorSource=`url`):(t.requestedScope=t.projectId?`project`:`account`,t.selectorSource=`persisted`),n&&(r.hash=``),t.recoveryUrl=r.toString(),r}function ot({children:e,loadOnboardingStatus:n=!1}){let i=new URLSearchParams(location.hash.substring(1)),a=i.get(`token`),o=i.get(`state`),[s,c]=g(new Qe),{verifyState:u,clearState:d}=Ze(),f=h(!1),m=h(void 0),_=(e,n=!1)=>{let i=at(new URL(window.location.href),e,n);window.history.replaceState(window.history.state,``,i),r.logger.warn(`Sanitized an unavailable authentication scope`,{vertesia:{account_id:e.accountId,project_id:e.projectId,error_code:t,selector_source:e.selectorSource,requested_scope:e.requestedScope,recovery_action:`url_sanitized`}})},v=(e,t=!1)=>e instanceof X||e instanceof Z||e instanceof Q||e instanceof $||e instanceof J||e instanceof Xe?(e instanceof X?_(e,t):t&&it(),s.isLoading=!1,s.authError=e,c(s.clone()),!0):!1;return m.current=()=>{if(f.current){r.logger.debug(`Skipping duplicate auth flow initiation`);return}f.current=!0,r.logger.debug(`Starting auth flow`);let{accountId:e,projectId:t}=ne(new URL(window.location.href));if(r.logger.debug(`Selected account and project`,{vertesia:{account_id:e,project_id:t}}),r.isLocalDev&&r.devAuthToken){s.setSession=c,q(e,t,r.devAuthToken).then(e=>s.login(e.rawToken).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Failed to initialize dev auth token`,n),r.logger.error(`Failed to initialize dev auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))});return}if(A()||ve()){let e=!1;return s.setSession=c,(A()?s.loginGatewaySession():F().then(e=>s.login(e,{loadOnboardingStatus:n,authMethod:`oauth`}))).then(()=>{e||c(s.clone())}).catch(t=>{e||v(t)||(s.isLoading=!1,s.authError=t instanceof Error?t:Error(String(t)),c(s.clone()))}),()=>{e=!0,f.current=!1}}if(a&&o){s.setSession=c;let i=u(o);if(i){console.error(`Auth: invalid state: ${i}`),r.logger.error(`Invalid state: ${i}`,{vertesia:{state:o}}),d(),it(),z({accountId:e,projectId:t});return}d(),q(e,t,a,!1,L()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>{c(s.clone()),it()})).catch(n=>{v(n,!0)||(console.error(`Failed to fetch user token from studio, redirecting to central auth`,n),r.logger.error(`Failed to fetch user token from studio, redirecting to central auth`,{vertesia:{error:n}}),z({accountId:e,projectId:t}))});return}let i=!1,p,m=()=>{if(!i){if(window.parent!==window&&!r.allowLegacyIframeAuth){s.isLoading=!1,s.authError=/* @__PURE__ */ Error(`Embedded authentication requires a valid token from the host.`),c(s.clone());return}if(!s.isLoggedIn()){if(r.logger.debug(`Not logged in & no token/state`,{vertesia:{account_id:e,project_id:t}}),L()){r.logger.debug(`Redirecting to central auth with selection`,{vertesia:{account_id:e,project_id:t}}),z({accountId:e,projectId:t});return}r.logger.debug(`Host is in Firebase auth allowlist`,{vertesia:{account_id:e,project_id:t}})}p=l(V(),async i=>{i?(r.logger.debug(`Successful login with firebase`,{vertesia:{account_id:e,project_id:t}}),s.setSession=c,await q(e,t,void 0,!1,L()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Unexpected failure while fetching a user token`,n),r.logger.error(`Unexpected failure while fetching a user token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.logout(),s.isLoading=!1,s.authError=n,c(s.clone()))})):(r.logger.debug(`Using anonymous user`,{vertesia:{account_id:e,project_id:t}}),s.client.withAuthCallback(void 0),s.logout(),c(s.clone()))})}};return r.authTokenProvider?(s.setSession=c,r.authTokenProvider().then(async r=>{if(i)return;if(!r){m();return}let a=await q(e,t,r,!1,L());await s.login(a.rawToken,{loadOnboardingStatus:n}),i||c(s.clone())}).catch(n=>{i||v(n)||(console.warn(`Auth: failed to initialize injected auth token`,n),r.logger.warn(`Failed to initialize injected auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))}),()=>{i=!0,f.current=!1,p?.()}):(m(),()=>{i=!0,f.current=!1,p?.()})},p(()=>m.current?.(),[]),te($e.Provider,{value:s,children:e})}function st(){return{tagUserSession:async e=>{let t=window.localStorage.getItem(`composableSignupData`);if(!e){console.error(`No user found -- skipping tagging`);return}t&&window.localStorage.removeItem(`composableSignupData`)},trackEvent:(e,t)=>{r.isProd||console.debug(`track event`,e,t),r.firebase?.apiKey&&o(Ne(),e,{...t,debug_mode:!r.isProd})}}}export{$ as AuthenticationServiceError,Q as CredentialError,rt as DevSessionProvider,y as LastSelectedAccountId_KEY,b as LastSelectedProjectId_KEY,Z as NoAccessibleAccountError,X as RequestedScopeUnavailableError,Xe as RestrictedEnvironmentError,Y as STSError,Ge as TokenAuthorizationError,J as UserNotFoundError,Qe as UserSession,$e as UserSessionContext,ot as UserSessionProvider,Oe as buildCentralAuthRedirectUrl,le as clearCentralAuthRoundTripMarker,K as fetchComposableToken,Ve as fetchComposableTokenFromFirebaseToken,He as fetchComposableTokenFromVertesiaToken,q as getComposableToken,Ue as getCurrentVertesiaToken,Ne as getFirebaseAnalytics,Me as getFirebaseApp,V as getFirebaseAuth,Fe as getFirebaseAuthToken,Ce as isAppOAuthLoginPending,Ye as isAuthenticationServiceError,ke as isCentralAuthRedirectPending,Je as isCredentialError,qe as isNoAccessibleAccountError,Ke as isRequestedScopeUnavailableError,z as redirectToCentralAuth,E as rememberScopeSelection,ne as resolveAuthSelection,Te as revokeAppOAuthSession,at as sanitizeRejectedScopeUrl,Pe as setFirebaseTenant,we as startAppOAuthLogin,Ze as useAuthState,tt as useCurrentTenant,st as useUXTracking,et as useUserSession};
|
|
2
2
|
//# sourceMappingURL=vertesia-ui-session.js.map
|