@pontive/pontkit-loader 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const $="1.1.1",U=["/__auth/auth/v1/runtime-config","/auth/v1/runtime-config"],j=1500,K=/^\d+\.\d+\.\d+$/;function F(t){return typeof t=="string"&&K.test(t)}function b(t){return typeof t=="string"&&/^https?:\/\//.test(t)}function N(t){return typeof t=="string"&&/^sha(256|384|512)-[A-Za-z0-9+/]+=*$/.test(t)}async function V(t={}){const a=t.fetchImpl??globalThis.fetch;if(typeof a!="function")return null;const l=t.urls??D(),d=t.timeoutMs??j;for(const e of l){const p=await W(a,e,d);if(p)return p}return null}function D(){return typeof window<"u"&&typeof window.__pontRuntimeConfigUrl=="string"?[window.__pontRuntimeConfigUrl]:U}async function W(t,a,l){const d=typeof AbortController=="function"?new AbortController:null,e=d?setTimeout(()=>d.abort(),l):null;try{const p=await t(a,{headers:{accept:"application/json"},signal:d?.signal});if(!p.ok)return null;const n=await p.json();if(!n||!F(n.core_elements_version))return null;const g={core_elements_version:n.core_elements_version,source:typeof n.source=="string"?n.source:void 0,catalog_revision:typeof n.catalog_revision=="number"?n.catalog_revision:void 0};return n.assets&&b(n.assets.js)&&b(n.assets.css)&&(g.assets={js:n.assets.js,css:n.assets.css}),n.integrity&&N(n.integrity.js)&&N(n.integrity.css)&&(g.integrity={js:n.integrity.js,css:n.integrity.css}),g}catch{return null}finally{e&&clearTimeout(e)}}let v=null,T=null;const E="@pontive/pontkit-core",q=[t=>`https://cdn.jsdelivr.net/npm/${E}@${t}/dist/index.mjs`,t=>`https://unpkg.com/${E}@${t}/dist/index.mjs`,t=>`https://esm.sh/${E}@${t}/dist/index.mjs`],z=[t=>`https://cdn.jsdelivr.net/npm/${E}@${t}/dist/styles.css`,t=>`https://unpkg.com/${E}@${t}/dist/styles.css`,t=>`https://esm.sh/${E}@${t}/dist/styles.css`],B=$;function X(t,a){return new Promise((l,d)=>{const e=document.createElement("link");e.rel="stylesheet",e.href=t,a&&(e.integrity=a,e.crossOrigin="anonymous"),e.onload=()=>l(),e.onerror=p=>d(p),document.head.appendChild(e)})}function Z(t,a){return new Promise((l,d)=>{const e=document.createElement("script");e.type="module",e.src=t,e.integrity=a,e.crossOrigin="anonymous",e.onload=()=>l(),e.onerror=()=>d(new Error(`core-elements module at ${t} failed to load or did not match its integrity hash`)),document.head.appendChild(e)}).then(()=>import(t))}async function x(){return typeof window>"u"||typeof document>"u"?null:window.__pontLoaded?window.__pontCoreSdk:window.__pontLoading?window.__pontLoading:(T||(T=J().catch(t=>{throw T=null,window.__pontLoading=void 0,t}),window.__pontLoading=T),T)}async function J(){const t=await V(),a=t?.core_elements_version??B,l=q.map(n=>n(a)),d=z.map(n=>n(a));t?.assets&&(l.unshift(t.assets.js),d.unshift(t.assets.css));const e=t?.integrity;let p=null;for(let n=0;n<l.length;n++){const g=l[n],G=d[n];try{let k=function(i){if(!i)return i;const C=[];let _=!1,m=null;const h=new Promise(o=>{m=o}),y=new Proxy(i,{get(o,c,f){if(c==="configure")return(...u)=>{const r=o.configure?.(...u);_=!0;try{C.forEach(({prop:w,args:I,resolve:A,reject:S})=>{try{const M=o[w].apply(o,I);M&&typeof M.then=="function"?M.then(A).catch(S):A(M)}catch(O){S(O)}})}catch{}C.length=0;try{y.__configured=!0}catch{}return m?.(),r};const s=o[c];return typeof s=="function"?(...u)=>{if(!_)return new Promise((r,w)=>{C.push({prop:c,args:u,resolve:r,reject:w})});try{return s.apply(o,u)}catch(r){throw r}}:s}});try{y.__whenConfigured=h,y.__configured=_}catch{}try{i.__whenConfigured=h,i.__configured=_;const o=i.configure;typeof o=="function"&&(i.configure=(...f)=>{const s=o.apply(i,f);_=!0;try{C.forEach(({prop:u,args:r,resolve:w,reject:I})=>{try{const S=i[u].apply(i,r);S&&typeof S.then=="function"?S.then(w).catch(I):w(S)}catch(A){I(A)}})}catch{}C.length=0;try{i.__configured=!0}catch{}return m?.(),s});const c=i.startLoginflow;typeof c=="function"&&(i.startLoginflow=(...f)=>_?c.apply(i,f):new Promise((s,u)=>{h.then(()=>{try{const r=c.apply(i,f);r&&typeof r.then=="function"?r.then(s).catch(u):s(r)}catch(r){u(r)}}).catch(()=>{try{const r=c.apply(i,f);r&&typeof r.then=="function"?r.then(s).catch(u):s(r)}catch(r){u(r)}})}))}catch{}try{h.then(()=>{setTimeout(()=>{try{document.querySelectorAll("pont-signin, pont-signup").forEach(o=>{try{if(o.__pontInitRetried)return;o.__pontInitRetried=!0;const c=o.__pontRetryInit;if(typeof c=="function"){try{c.call(o)}catch(f){console.error(f)}return}if(o.__pontFailedForConfig)try{o.connectedCallback?.()}catch(f){console.error(f)}}catch{}})}catch{}},0)})}catch{}return y};await X(G,e?.css);const P=e?await Z(g,e.js):await import(g),H=P.useAuthProvider?.(),R=k(H);try{P.Auth=R,P.useAuthProvider=()=>R}catch{}window.__pontCoreSdk={...P,Auth:R},v=window.__pontCoreSdk,window.__pontLoaded=!0,window.__pontLoading=void 0;try{const i=C=>{const _=customElements.get(C);if(!_)return;const m=_.prototype;if(m.__pontConfiguredPatched)return;m.__pontConfiguredPatched=!0;const h=m.connectedCallback;typeof h=="function"&&(m.connectedCallback=function(...y){const o=window.__pontCoreSdk?.Auth,c=o?.__whenConfigured,f=!!o?.__configured;if(c&&!f){c.then(()=>{try{h.apply(this,y)}catch(s){console.error(s)}}).catch(()=>{try{h.apply(this,y)}catch(s){console.error(s)}});return}try{h.apply(this,y)}catch(s){if(s&&typeof s.message=="string"&&s.message.includes("Auth.configure() must be called")&&c){c.then(()=>{try{h.apply(this,y)}catch(u){console.error(u)}});return}throw s}})};["pont-signin","pont-signup"].forEach(i)}catch{}return console.log(`PontKit Web Components loaded (${a}) from:`,g),v}catch(k){console.error(`Failed loading from ${g}`,k),p=k}}throw console.error("❌ Failed to load PontKit web components from all CDNs.",p),p}let L=null;async function Q(){typeof window>"u"||window.__pontCoreSdk?.openAccountSettingsModal||(L||(L=x().then(()=>{window.__pontCoreSdk?.openAccountSettingsModal||console.warn("[pontive-react] Core sdk loaded but modal functions are missing.")}).catch(t=>{throw console.error("[pontive-react] Failed to load core SDK:",t),t})),await L)}exports.CORE_ELEMENTS_VERSION=$;exports.RUNTIME_CONFIG_PATHS=U;exports.RUNTIME_CONFIG_TIMEOUT_MS=j;exports.ensureCoreSdkLoaded=Q;exports.fetchRuntimeConfig=V;exports.isExactVersion=F;exports.isSriHash=N;exports.loadWebComponents=x;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const $="1.1.4",U=["/__auth/auth/v1/runtime-config","/auth/v1/runtime-config"],j=1500,K=/^\d+\.\d+\.\d+$/;function F(t){return typeof t=="string"&&K.test(t)}function b(t){return typeof t=="string"&&/^https?:\/\//.test(t)}function N(t){return typeof t=="string"&&/^sha(256|384|512)-[A-Za-z0-9+/]+=*$/.test(t)}async function V(t={}){const a=t.fetchImpl??globalThis.fetch;if(typeof a!="function")return null;const l=t.urls??D(),d=t.timeoutMs??j;for(const e of l){const p=await W(a,e,d);if(p)return p}return null}function D(){return typeof window<"u"&&typeof window.__pontRuntimeConfigUrl=="string"?[window.__pontRuntimeConfigUrl]:U}async function W(t,a,l){const d=typeof AbortController=="function"?new AbortController:null,e=d?setTimeout(()=>d.abort(),l):null;try{const p=await t(a,{headers:{accept:"application/json"},signal:d?.signal});if(!p.ok)return null;const n=await p.json();if(!n||!F(n.core_elements_version))return null;const g={core_elements_version:n.core_elements_version,source:typeof n.source=="string"?n.source:void 0,catalog_revision:typeof n.catalog_revision=="number"?n.catalog_revision:void 0};return n.assets&&b(n.assets.js)&&b(n.assets.css)&&(g.assets={js:n.assets.js,css:n.assets.css}),n.integrity&&N(n.integrity.js)&&N(n.integrity.css)&&(g.integrity={js:n.integrity.js,css:n.integrity.css}),g}catch{return null}finally{e&&clearTimeout(e)}}let v=null,T=null;const E="@pontive/pontkit-core",q=[t=>`https://cdn.jsdelivr.net/npm/${E}@${t}/dist/index.mjs`,t=>`https://unpkg.com/${E}@${t}/dist/index.mjs`,t=>`https://esm.sh/${E}@${t}/dist/index.mjs`],z=[t=>`https://cdn.jsdelivr.net/npm/${E}@${t}/dist/styles.css`,t=>`https://unpkg.com/${E}@${t}/dist/styles.css`,t=>`https://esm.sh/${E}@${t}/dist/styles.css`],B=$;function X(t,a){return new Promise((l,d)=>{const e=document.createElement("link");e.rel="stylesheet",e.href=t,a&&(e.integrity=a,e.crossOrigin="anonymous"),e.onload=()=>l(),e.onerror=p=>d(p),document.head.appendChild(e)})}function Z(t,a){return new Promise((l,d)=>{const e=document.createElement("script");e.type="module",e.src=t,e.integrity=a,e.crossOrigin="anonymous",e.onload=()=>l(),e.onerror=()=>d(new Error(`core-elements module at ${t} failed to load or did not match its integrity hash`)),document.head.appendChild(e)}).then(()=>import(t))}async function x(){return typeof window>"u"||typeof document>"u"?null:window.__pontLoaded?window.__pontCoreSdk:window.__pontLoading?window.__pontLoading:(T||(T=J().catch(t=>{throw T=null,window.__pontLoading=void 0,t}),window.__pontLoading=T),T)}async function J(){const t=await V(),a=t?.core_elements_version??B,l=q.map(n=>n(a)),d=z.map(n=>n(a));t?.assets&&(l.unshift(t.assets.js),d.unshift(t.assets.css));const e=t?.integrity;let p=null;for(let n=0;n<l.length;n++){const g=l[n],G=d[n];try{let k=function(i){if(!i)return i;const C=[];let _=!1,m=null;const h=new Promise(o=>{m=o}),y=new Proxy(i,{get(o,c,f){if(c==="configure")return(...u)=>{const r=o.configure?.(...u);_=!0;try{C.forEach(({prop:w,args:I,resolve:A,reject:S})=>{try{const M=o[w].apply(o,I);M&&typeof M.then=="function"?M.then(A).catch(S):A(M)}catch(O){S(O)}})}catch{}C.length=0;try{y.__configured=!0}catch{}return m?.(),r};const s=o[c];return typeof s=="function"?(...u)=>{if(!_)return new Promise((r,w)=>{C.push({prop:c,args:u,resolve:r,reject:w})});try{return s.apply(o,u)}catch(r){throw r}}:s}});try{y.__whenConfigured=h,y.__configured=_}catch{}try{i.__whenConfigured=h,i.__configured=_;const o=i.configure;typeof o=="function"&&(i.configure=(...f)=>{const s=o.apply(i,f);_=!0;try{C.forEach(({prop:u,args:r,resolve:w,reject:I})=>{try{const S=i[u].apply(i,r);S&&typeof S.then=="function"?S.then(w).catch(I):w(S)}catch(A){I(A)}})}catch{}C.length=0;try{i.__configured=!0}catch{}return m?.(),s});const c=i.startLoginflow;typeof c=="function"&&(i.startLoginflow=(...f)=>_?c.apply(i,f):new Promise((s,u)=>{h.then(()=>{try{const r=c.apply(i,f);r&&typeof r.then=="function"?r.then(s).catch(u):s(r)}catch(r){u(r)}}).catch(()=>{try{const r=c.apply(i,f);r&&typeof r.then=="function"?r.then(s).catch(u):s(r)}catch(r){u(r)}})}))}catch{}try{h.then(()=>{setTimeout(()=>{try{document.querySelectorAll("pont-signin, pont-signup").forEach(o=>{try{if(o.__pontInitRetried)return;o.__pontInitRetried=!0;const c=o.__pontRetryInit;if(typeof c=="function"){try{c.call(o)}catch(f){console.error(f)}return}if(o.__pontFailedForConfig)try{o.connectedCallback?.()}catch(f){console.error(f)}}catch{}})}catch{}},0)})}catch{}return y};await X(G,e?.css);const P=e?await Z(g,e.js):await import(g),H=P.useAuthProvider?.(),R=k(H);try{P.Auth=R,P.useAuthProvider=()=>R}catch{}window.__pontCoreSdk={...P,Auth:R},v=window.__pontCoreSdk,window.__pontLoaded=!0,window.__pontLoading=void 0;try{const i=C=>{const _=customElements.get(C);if(!_)return;const m=_.prototype;if(m.__pontConfiguredPatched)return;m.__pontConfiguredPatched=!0;const h=m.connectedCallback;typeof h=="function"&&(m.connectedCallback=function(...y){const o=window.__pontCoreSdk?.Auth,c=o?.__whenConfigured,f=!!o?.__configured;if(c&&!f){c.then(()=>{try{h.apply(this,y)}catch(s){console.error(s)}}).catch(()=>{try{h.apply(this,y)}catch(s){console.error(s)}});return}try{h.apply(this,y)}catch(s){if(s&&typeof s.message=="string"&&s.message.includes("Auth.configure() must be called")&&c){c.then(()=>{try{h.apply(this,y)}catch(u){console.error(u)}});return}throw s}})};["pont-signin","pont-signup"].forEach(i)}catch{}return console.log(`PontKit Web Components loaded (${a}) from:`,g),v}catch(k){console.error(`Failed loading from ${g}`,k),p=k}}throw console.error("❌ Failed to load PontKit web components from all CDNs.",p),p}let L=null;async function Q(){typeof window>"u"||window.__pontCoreSdk?.openAccountSettingsModal||(L||(L=x().then(()=>{window.__pontCoreSdk?.openAccountSettingsModal||console.warn("[pontive-react] Core sdk loaded but modal functions are missing.")}).catch(t=>{throw console.error("[pontive-react] Failed to load core SDK:",t),t})),await L)}exports.CORE_ELEMENTS_VERSION=$;exports.RUNTIME_CONFIG_PATHS=U;exports.RUNTIME_CONFIG_TIMEOUT_MS=j;exports.ensureCoreSdkLoaded=Q;exports.fetchRuntimeConfig=V;exports.isExactVersion=F;exports.isSriHash=N;exports.loadWebComponents=x;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const j = "1.1.1", F = [
1
+ const j = "1.1.4", F = [
2
2
  "/__auth/auth/v1/runtime-config",
3
3
  "/auth/v1/runtime-config"
4
4
  ], J = 1500, x = /^\d+\.\d+\.\d+$/;
@@ -18,7 +18,7 @@
18
18
  * `SameSite=Lax`.
19
19
  *
20
20
  * Everything else on the auth server is a top-level navigation — `/authorize`,
21
- * the hosted sign-in page, `/end_session` as a redirect — and a `Lax` cookie is
21
+ * the hosted sign-in page, `/logout` as a redirect — and a `Lax` cookie is
22
22
  * sent on those already, whatever origin they are served from. Proxying them
23
23
  * would not help, and it would break: the authorization server builds those
24
24
  * URLs absolute, on its own hostname, so the browser leaves the proxy at the
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.cjs","sources":["../src/proxy/target.ts","../src/proxy/vite.ts"],"sourcesContent":["/**\n * Where a proxied request is sent, and which requests are sent at all.\n *\n * Deliberately not shared with `resolveAuthBaseUrl` in the SDK, which answers a\n * different question. That one resolves what the BROWSER should call and its\n * most useful answer — a bare path like `/__auth` — is meaningless here: a\n * proxy runs on a server, where there is no page origin for a path to be\n * relative to. Sharing them would mean one function with a mode flag, and the\n * mode that is wrong in either direction is silent.\n */\n\n/**\n * The endpoints an app-level proxy has to carry, and the reason the list is\n * short.\n *\n * These are the requests the browser makes with `fetch` — the auth flow, the\n * token endpoint, userinfo, logout, branding CSS. They are the ones that need\n * to be same-origin, because they are the ones carrying cookies under\n * `SameSite=Lax`.\n *\n * Everything else on the auth server is a top-level navigation — `/authorize`,\n * the hosted sign-in page, `/end_session` as a redirect — and a `Lax` cookie is\n * sent on those already, whatever origin they are served from. Proxying them\n * would not help, and it would break: the authorization server builds those\n * URLs absolute, on its own hostname, so the browser leaves the proxy at the\n * first redirect anyway.\n *\n * The two prefixes are the same pair the dev-server proxy uses (auth-api,\n * `docs/auth-domains-and-token-storage.md` §3). That is not a coincidence to be\n * tidied away: local development against a shared sandbox domain is the same\n * cross-site problem this solves in production, and the two configurations\n * being identical is what makes the local one a rehearsal.\n */\nexport const DEFAULT_FORWARDED_PATHS = [\"/auth/v1\", \"/oauth2\"] as const;\n\n/**\n * Where the endpoints hang off the app's own origin.\n *\n * `__`-prefixed by convention — Clerk uses `/__clerk`, Firebase `/__/auth` —\n * because it has to be a path no real route of the app will ever want.\n */\nexport const DEFAULT_BASE_PATH = \"/__auth\";\n\n/**\n * The auth server, as an origin.\n *\n * Accepts `tenant.idp.us.pontive.app` or `https://tenant.idp.us.pontive.app`,\n * and nothing with a path: the upstream path comes from the incoming request,\n * and a base path here would be silently prepended to endpoints the auth server\n * does not serve.\n *\n * `http://` is inferred for loopback only, and accepted only there. A proxy is\n * the one hop a refresh token cannot be carried over in the clear — it is the\n * hop that exists precisely so the cookie is first-party — and the failure is\n * invisible from the browser, which sees its own `https://` origin either way.\n */\nexport function authOrigin(authHost: string): string {\n const configured = (authHost ?? \"\").trim();\n\n if (!configured) {\n throw new TypeError(\"authHost is required\");\n }\n\n const loopback = /^(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d+)?$/i.test(\n configured.replace(/^https?:\\/\\//i, \"\").split(\"/\")[0],\n );\n\n const scheme = /^https?:\\/\\//i.test(configured) ? \"\" : `${loopback ? \"http\" : \"https\"}://`;\n\n let url: URL;\n try {\n url = new URL(`${scheme}${configured}`);\n } catch {\n throw new TypeError(`authHost \"${configured}\" is not a hostname or an origin`);\n }\n\n if (url.pathname !== \"/\" || url.search || url.hash) {\n throw new TypeError(\n `authHost \"${configured}\" must be a bare origin — the path comes from the request being proxied`,\n );\n }\n\n if (url.protocol !== \"https:\" && !loopback) {\n throw new TypeError(`authHost \"${configured}\" must be https outside loopback`);\n }\n\n return url.origin;\n}\n\n/**\n * A base path with a leading slash and no trailing one, so joining is\n * unambiguous.\n *\n * `\"/\"` normalises to `\"\"`, which mounts the endpoints at the origin root —\n * `/auth/v1/...` and `/oauth2/...` where the app itself is served. That is the\n * shape a Vite dev server has always used, and it stays available because in\n * development the app owns the whole origin and there is nothing to collide\n * with. A deployed app usually does not, which is what the prefix is for.\n */\nexport function normaliseBasePath(basePath: string): string {\n const trimmed = (basePath ?? \"\").trim().replace(/\\/+$/, \"\");\n\n if (trimmed === \"\") {\n return \"\";\n }\n\n if (!trimmed.startsWith(\"/\")) {\n throw new TypeError(`basePath \"${basePath}\" must start with \"/\"`);\n }\n\n return trimmed;\n}\n\n/** Whether `pathname` is `prefix` itself or something under it. */\nexport function isUnder(pathname: string, prefix: string): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`);\n}\n","import {\n DEFAULT_BASE_PATH,\n DEFAULT_FORWARDED_PATHS,\n authOrigin,\n normaliseBasePath,\n} from \"./target\";\n\n/**\n * The shape of one entry in Vite's `server.proxy`.\n *\n * Declared here rather than imported from Vite so that nothing which imports\n * this module needs Vite installed, and so the published types do not depend on\n * a particular version of it. It is structural: Vite accepts this object.\n */\nexport interface ViteProxyEntry {\n target: string;\n changeOrigin: boolean;\n rewrite: (path: string) => string;\n}\n\nexport interface ViteAuthProxyOptions {\n authHost: string;\n basePath?: string;\n paths?: readonly string[];\n}\n\n/**\n * The auth endpoints, proxied through a Vite dev server.\n *\n * ```ts\n * // vite.config.ts\n * server: { proxy: viteAuthProxy({ authHost: env.VITE_SB_AUTH_DOMAIN }) }\n * ```\n *\n * Vite already has a proxy; what it does not have is the knowledge of which\n * paths to carry and what to do with Host, and both of those are easy to get\n * wrong in ways that fail silently. So this is a config generator rather than a\n * request handler — `createAuthProxy` is for runtimes that have no proxy of\n * their own.\n *\n * Worth doing even where the browser would tolerate the cross-site setup,\n * because it is the same topology production runs on: a dev server that proxies\n * is rehearsing the deployment, and a dev server that does not is testing a\n * configuration no user will ever have. It is also the only way an embedded\n * sign-in flow works in Safari, which blocks third-party cookies outright.\n */\nexport function viteAuthProxy(\n options: ViteAuthProxyOptions,\n): Record<string, ViteProxyEntry> {\n const target = authOrigin(options.authHost);\n const basePath = normaliseBasePath(options.basePath ?? DEFAULT_BASE_PATH);\n const paths = options.paths ?? DEFAULT_FORWARDED_PATHS;\n\n const proxy: Record<string, ViteProxyEntry> = {};\n\n for (const prefix of paths) {\n proxy[`${basePath}${prefix}`] = {\n target,\n // The single most important line, and the one a hand-written config\n // leaves out. Without it the auth server is asked to answer as\n // `localhost:5173` — a Host it has no project for — and the reply is a\n // CORS refusal and an empty issuer rather than anything that says so.\n changeOrigin: true,\n // Only the base path comes off. The prefix below it is the path the auth\n // server actually serves.\n rewrite: (path: string) => (basePath ? path.replace(basePath, \"\") : path),\n };\n }\n\n return proxy;\n}\n"],"names":["DEFAULT_FORWARDED_PATHS","DEFAULT_BASE_PATH","authOrigin","authHost","configured","loopback","scheme","url","normaliseBasePath","basePath","trimmed","isUnder","pathname","prefix","viteAuthProxy","options","target","paths","proxy","path"],"mappings":"gFAiCO,MAAMA,EAA0B,CAAC,WAAY,SAAS,EAQhDC,EAAoB,UAe1B,SAASC,EAAWC,EAA0B,CACnD,MAAMC,GAAcD,GAAY,IAAI,KAAA,EAEpC,GAAI,CAACC,EACH,MAAM,IAAI,UAAU,sBAAsB,EAG5C,MAAMC,EAAW,6CAA6C,KAC5DD,EAAW,QAAQ,gBAAiB,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAA,EAGhDE,EAAS,gBAAgB,KAAKF,CAAU,EAAI,GAAK,GAAGC,EAAW,OAAS,OAAO,MAErF,IAAIE,EACJ,GAAI,CACFA,EAAM,IAAI,IAAI,GAAGD,CAAM,GAAGF,CAAU,EAAE,CACxC,MAAQ,CACN,MAAM,IAAI,UAAU,aAAaA,CAAU,kCAAkC,CAC/E,CAEA,GAAIG,EAAI,WAAa,KAAOA,EAAI,QAAUA,EAAI,KAC5C,MAAM,IAAI,UACR,aAAaH,CAAU,yEAAA,EAI3B,GAAIG,EAAI,WAAa,UAAY,CAACF,EAChC,MAAM,IAAI,UAAU,aAAaD,CAAU,kCAAkC,EAG/E,OAAOG,EAAI,MACb,CAYO,SAASC,EAAkBC,EAA0B,CAC1D,MAAMC,GAAWD,GAAY,IAAI,OAAO,QAAQ,OAAQ,EAAE,EAE1D,GAAIC,IAAY,GACd,MAAO,GAGT,GAAI,CAACA,EAAQ,WAAW,GAAG,EACzB,MAAM,IAAI,UAAU,aAAaD,CAAQ,uBAAuB,EAGlE,OAAOC,CACT,CAGO,SAASC,EAAQC,EAAkBC,EAAyB,CACjE,OAAOD,IAAaC,GAAUD,EAAS,WAAW,GAAGC,CAAM,GAAG,CAChE,CCtEO,SAASC,EACdC,EACgC,CAChC,MAAMC,EAASd,EAAWa,EAAQ,QAAQ,EACpCN,EAAWD,EAAkBO,EAAQ,UAAYd,CAAiB,EAClEgB,EAAQF,EAAQ,OAASf,EAEzBkB,EAAwC,CAAA,EAE9C,UAAWL,KAAUI,EACnBC,EAAM,GAAGT,CAAQ,GAAGI,CAAM,EAAE,EAAI,CAC9B,OAAAG,EAKA,aAAc,GAGd,QAAUG,GAAkBV,EAAWU,EAAK,QAAQV,EAAU,EAAE,EAAIU,CAAA,EAIxE,OAAOD,CACT"}
1
+ {"version":3,"file":"proxy.cjs","sources":["../src/proxy/target.ts","../src/proxy/vite.ts"],"sourcesContent":["/**\n * Where a proxied request is sent, and which requests are sent at all.\n *\n * Deliberately not shared with `resolveAuthBaseUrl` in the SDK, which answers a\n * different question. That one resolves what the BROWSER should call and its\n * most useful answer — a bare path like `/__auth` — is meaningless here: a\n * proxy runs on a server, where there is no page origin for a path to be\n * relative to. Sharing them would mean one function with a mode flag, and the\n * mode that is wrong in either direction is silent.\n */\n\n/**\n * The endpoints an app-level proxy has to carry, and the reason the list is\n * short.\n *\n * These are the requests the browser makes with `fetch` — the auth flow, the\n * token endpoint, userinfo, logout, branding CSS. They are the ones that need\n * to be same-origin, because they are the ones carrying cookies under\n * `SameSite=Lax`.\n *\n * Everything else on the auth server is a top-level navigation — `/authorize`,\n * the hosted sign-in page, `/logout` as a redirect — and a `Lax` cookie is\n * sent on those already, whatever origin they are served from. Proxying them\n * would not help, and it would break: the authorization server builds those\n * URLs absolute, on its own hostname, so the browser leaves the proxy at the\n * first redirect anyway.\n *\n * The two prefixes are the same pair the dev-server proxy uses (auth-api,\n * `docs/auth-domains-and-token-storage.md` §3). That is not a coincidence to be\n * tidied away: local development against a shared sandbox domain is the same\n * cross-site problem this solves in production, and the two configurations\n * being identical is what makes the local one a rehearsal.\n */\nexport const DEFAULT_FORWARDED_PATHS = [\"/auth/v1\", \"/oauth2\"] as const;\n\n/**\n * Where the endpoints hang off the app's own origin.\n *\n * `__`-prefixed by convention — Clerk uses `/__clerk`, Firebase `/__/auth` —\n * because it has to be a path no real route of the app will ever want.\n */\nexport const DEFAULT_BASE_PATH = \"/__auth\";\n\n/**\n * The auth server, as an origin.\n *\n * Accepts `tenant.idp.us.pontive.app` or `https://tenant.idp.us.pontive.app`,\n * and nothing with a path: the upstream path comes from the incoming request,\n * and a base path here would be silently prepended to endpoints the auth server\n * does not serve.\n *\n * `http://` is inferred for loopback only, and accepted only there. A proxy is\n * the one hop a refresh token cannot be carried over in the clear — it is the\n * hop that exists precisely so the cookie is first-party — and the failure is\n * invisible from the browser, which sees its own `https://` origin either way.\n */\nexport function authOrigin(authHost: string): string {\n const configured = (authHost ?? \"\").trim();\n\n if (!configured) {\n throw new TypeError(\"authHost is required\");\n }\n\n const loopback = /^(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d+)?$/i.test(\n configured.replace(/^https?:\\/\\//i, \"\").split(\"/\")[0],\n );\n\n const scheme = /^https?:\\/\\//i.test(configured) ? \"\" : `${loopback ? \"http\" : \"https\"}://`;\n\n let url: URL;\n try {\n url = new URL(`${scheme}${configured}`);\n } catch {\n throw new TypeError(`authHost \"${configured}\" is not a hostname or an origin`);\n }\n\n if (url.pathname !== \"/\" || url.search || url.hash) {\n throw new TypeError(\n `authHost \"${configured}\" must be a bare origin — the path comes from the request being proxied`,\n );\n }\n\n if (url.protocol !== \"https:\" && !loopback) {\n throw new TypeError(`authHost \"${configured}\" must be https outside loopback`);\n }\n\n return url.origin;\n}\n\n/**\n * A base path with a leading slash and no trailing one, so joining is\n * unambiguous.\n *\n * `\"/\"` normalises to `\"\"`, which mounts the endpoints at the origin root —\n * `/auth/v1/...` and `/oauth2/...` where the app itself is served. That is the\n * shape a Vite dev server has always used, and it stays available because in\n * development the app owns the whole origin and there is nothing to collide\n * with. A deployed app usually does not, which is what the prefix is for.\n */\nexport function normaliseBasePath(basePath: string): string {\n const trimmed = (basePath ?? \"\").trim().replace(/\\/+$/, \"\");\n\n if (trimmed === \"\") {\n return \"\";\n }\n\n if (!trimmed.startsWith(\"/\")) {\n throw new TypeError(`basePath \"${basePath}\" must start with \"/\"`);\n }\n\n return trimmed;\n}\n\n/** Whether `pathname` is `prefix` itself or something under it. */\nexport function isUnder(pathname: string, prefix: string): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`);\n}\n","import {\n DEFAULT_BASE_PATH,\n DEFAULT_FORWARDED_PATHS,\n authOrigin,\n normaliseBasePath,\n} from \"./target\";\n\n/**\n * The shape of one entry in Vite's `server.proxy`.\n *\n * Declared here rather than imported from Vite so that nothing which imports\n * this module needs Vite installed, and so the published types do not depend on\n * a particular version of it. It is structural: Vite accepts this object.\n */\nexport interface ViteProxyEntry {\n target: string;\n changeOrigin: boolean;\n rewrite: (path: string) => string;\n}\n\nexport interface ViteAuthProxyOptions {\n authHost: string;\n basePath?: string;\n paths?: readonly string[];\n}\n\n/**\n * The auth endpoints, proxied through a Vite dev server.\n *\n * ```ts\n * // vite.config.ts\n * server: { proxy: viteAuthProxy({ authHost: env.VITE_SB_AUTH_DOMAIN }) }\n * ```\n *\n * Vite already has a proxy; what it does not have is the knowledge of which\n * paths to carry and what to do with Host, and both of those are easy to get\n * wrong in ways that fail silently. So this is a config generator rather than a\n * request handler — `createAuthProxy` is for runtimes that have no proxy of\n * their own.\n *\n * Worth doing even where the browser would tolerate the cross-site setup,\n * because it is the same topology production runs on: a dev server that proxies\n * is rehearsing the deployment, and a dev server that does not is testing a\n * configuration no user will ever have. It is also the only way an embedded\n * sign-in flow works in Safari, which blocks third-party cookies outright.\n */\nexport function viteAuthProxy(\n options: ViteAuthProxyOptions,\n): Record<string, ViteProxyEntry> {\n const target = authOrigin(options.authHost);\n const basePath = normaliseBasePath(options.basePath ?? DEFAULT_BASE_PATH);\n const paths = options.paths ?? DEFAULT_FORWARDED_PATHS;\n\n const proxy: Record<string, ViteProxyEntry> = {};\n\n for (const prefix of paths) {\n proxy[`${basePath}${prefix}`] = {\n target,\n // The single most important line, and the one a hand-written config\n // leaves out. Without it the auth server is asked to answer as\n // `localhost:5173` — a Host it has no project for — and the reply is a\n // CORS refusal and an empty issuer rather than anything that says so.\n changeOrigin: true,\n // Only the base path comes off. The prefix below it is the path the auth\n // server actually serves.\n rewrite: (path: string) => (basePath ? path.replace(basePath, \"\") : path),\n };\n }\n\n return proxy;\n}\n"],"names":["DEFAULT_FORWARDED_PATHS","DEFAULT_BASE_PATH","authOrigin","authHost","configured","loopback","scheme","url","normaliseBasePath","basePath","trimmed","isUnder","pathname","prefix","viteAuthProxy","options","target","paths","proxy","path"],"mappings":"gFAiCO,MAAMA,EAA0B,CAAC,WAAY,SAAS,EAQhDC,EAAoB,UAe1B,SAASC,EAAWC,EAA0B,CACnD,MAAMC,GAAcD,GAAY,IAAI,KAAA,EAEpC,GAAI,CAACC,EACH,MAAM,IAAI,UAAU,sBAAsB,EAG5C,MAAMC,EAAW,6CAA6C,KAC5DD,EAAW,QAAQ,gBAAiB,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAA,EAGhDE,EAAS,gBAAgB,KAAKF,CAAU,EAAI,GAAK,GAAGC,EAAW,OAAS,OAAO,MAErF,IAAIE,EACJ,GAAI,CACFA,EAAM,IAAI,IAAI,GAAGD,CAAM,GAAGF,CAAU,EAAE,CACxC,MAAQ,CACN,MAAM,IAAI,UAAU,aAAaA,CAAU,kCAAkC,CAC/E,CAEA,GAAIG,EAAI,WAAa,KAAOA,EAAI,QAAUA,EAAI,KAC5C,MAAM,IAAI,UACR,aAAaH,CAAU,yEAAA,EAI3B,GAAIG,EAAI,WAAa,UAAY,CAACF,EAChC,MAAM,IAAI,UAAU,aAAaD,CAAU,kCAAkC,EAG/E,OAAOG,EAAI,MACb,CAYO,SAASC,EAAkBC,EAA0B,CAC1D,MAAMC,GAAWD,GAAY,IAAI,OAAO,QAAQ,OAAQ,EAAE,EAE1D,GAAIC,IAAY,GACd,MAAO,GAGT,GAAI,CAACA,EAAQ,WAAW,GAAG,EACzB,MAAM,IAAI,UAAU,aAAaD,CAAQ,uBAAuB,EAGlE,OAAOC,CACT,CAGO,SAASC,EAAQC,EAAkBC,EAAyB,CACjE,OAAOD,IAAaC,GAAUD,EAAS,WAAW,GAAGC,CAAM,GAAG,CAChE,CCtEO,SAASC,EACdC,EACgC,CAChC,MAAMC,EAASd,EAAWa,EAAQ,QAAQ,EACpCN,EAAWD,EAAkBO,EAAQ,UAAYd,CAAiB,EAClEgB,EAAQF,EAAQ,OAASf,EAEzBkB,EAAwC,CAAA,EAE9C,UAAWL,KAAUI,EACnBC,EAAM,GAAGT,CAAQ,GAAGI,CAAM,EAAE,EAAI,CAC9B,OAAAG,EAKA,aAAc,GAGd,QAAUG,GAAkBV,EAAWU,EAAK,QAAQV,EAAU,EAAE,EAAIU,CAAA,EAIxE,OAAOD,CACT"}
package/dist/proxy.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sources":["../src/proxy/target.ts","../src/proxy/vite.ts"],"sourcesContent":["/**\n * Where a proxied request is sent, and which requests are sent at all.\n *\n * Deliberately not shared with `resolveAuthBaseUrl` in the SDK, which answers a\n * different question. That one resolves what the BROWSER should call and its\n * most useful answer — a bare path like `/__auth` — is meaningless here: a\n * proxy runs on a server, where there is no page origin for a path to be\n * relative to. Sharing them would mean one function with a mode flag, and the\n * mode that is wrong in either direction is silent.\n */\n\n/**\n * The endpoints an app-level proxy has to carry, and the reason the list is\n * short.\n *\n * These are the requests the browser makes with `fetch` — the auth flow, the\n * token endpoint, userinfo, logout, branding CSS. They are the ones that need\n * to be same-origin, because they are the ones carrying cookies under\n * `SameSite=Lax`.\n *\n * Everything else on the auth server is a top-level navigation — `/authorize`,\n * the hosted sign-in page, `/end_session` as a redirect — and a `Lax` cookie is\n * sent on those already, whatever origin they are served from. Proxying them\n * would not help, and it would break: the authorization server builds those\n * URLs absolute, on its own hostname, so the browser leaves the proxy at the\n * first redirect anyway.\n *\n * The two prefixes are the same pair the dev-server proxy uses (auth-api,\n * `docs/auth-domains-and-token-storage.md` §3). That is not a coincidence to be\n * tidied away: local development against a shared sandbox domain is the same\n * cross-site problem this solves in production, and the two configurations\n * being identical is what makes the local one a rehearsal.\n */\nexport const DEFAULT_FORWARDED_PATHS = [\"/auth/v1\", \"/oauth2\"] as const;\n\n/**\n * Where the endpoints hang off the app's own origin.\n *\n * `__`-prefixed by convention — Clerk uses `/__clerk`, Firebase `/__/auth` —\n * because it has to be a path no real route of the app will ever want.\n */\nexport const DEFAULT_BASE_PATH = \"/__auth\";\n\n/**\n * The auth server, as an origin.\n *\n * Accepts `tenant.idp.us.pontive.app` or `https://tenant.idp.us.pontive.app`,\n * and nothing with a path: the upstream path comes from the incoming request,\n * and a base path here would be silently prepended to endpoints the auth server\n * does not serve.\n *\n * `http://` is inferred for loopback only, and accepted only there. A proxy is\n * the one hop a refresh token cannot be carried over in the clear — it is the\n * hop that exists precisely so the cookie is first-party — and the failure is\n * invisible from the browser, which sees its own `https://` origin either way.\n */\nexport function authOrigin(authHost: string): string {\n const configured = (authHost ?? \"\").trim();\n\n if (!configured) {\n throw new TypeError(\"authHost is required\");\n }\n\n const loopback = /^(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d+)?$/i.test(\n configured.replace(/^https?:\\/\\//i, \"\").split(\"/\")[0],\n );\n\n const scheme = /^https?:\\/\\//i.test(configured) ? \"\" : `${loopback ? \"http\" : \"https\"}://`;\n\n let url: URL;\n try {\n url = new URL(`${scheme}${configured}`);\n } catch {\n throw new TypeError(`authHost \"${configured}\" is not a hostname or an origin`);\n }\n\n if (url.pathname !== \"/\" || url.search || url.hash) {\n throw new TypeError(\n `authHost \"${configured}\" must be a bare origin — the path comes from the request being proxied`,\n );\n }\n\n if (url.protocol !== \"https:\" && !loopback) {\n throw new TypeError(`authHost \"${configured}\" must be https outside loopback`);\n }\n\n return url.origin;\n}\n\n/**\n * A base path with a leading slash and no trailing one, so joining is\n * unambiguous.\n *\n * `\"/\"` normalises to `\"\"`, which mounts the endpoints at the origin root —\n * `/auth/v1/...` and `/oauth2/...` where the app itself is served. That is the\n * shape a Vite dev server has always used, and it stays available because in\n * development the app owns the whole origin and there is nothing to collide\n * with. A deployed app usually does not, which is what the prefix is for.\n */\nexport function normaliseBasePath(basePath: string): string {\n const trimmed = (basePath ?? \"\").trim().replace(/\\/+$/, \"\");\n\n if (trimmed === \"\") {\n return \"\";\n }\n\n if (!trimmed.startsWith(\"/\")) {\n throw new TypeError(`basePath \"${basePath}\" must start with \"/\"`);\n }\n\n return trimmed;\n}\n\n/** Whether `pathname` is `prefix` itself or something under it. */\nexport function isUnder(pathname: string, prefix: string): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`);\n}\n","import {\n DEFAULT_BASE_PATH,\n DEFAULT_FORWARDED_PATHS,\n authOrigin,\n normaliseBasePath,\n} from \"./target\";\n\n/**\n * The shape of one entry in Vite's `server.proxy`.\n *\n * Declared here rather than imported from Vite so that nothing which imports\n * this module needs Vite installed, and so the published types do not depend on\n * a particular version of it. It is structural: Vite accepts this object.\n */\nexport interface ViteProxyEntry {\n target: string;\n changeOrigin: boolean;\n rewrite: (path: string) => string;\n}\n\nexport interface ViteAuthProxyOptions {\n authHost: string;\n basePath?: string;\n paths?: readonly string[];\n}\n\n/**\n * The auth endpoints, proxied through a Vite dev server.\n *\n * ```ts\n * // vite.config.ts\n * server: { proxy: viteAuthProxy({ authHost: env.VITE_SB_AUTH_DOMAIN }) }\n * ```\n *\n * Vite already has a proxy; what it does not have is the knowledge of which\n * paths to carry and what to do with Host, and both of those are easy to get\n * wrong in ways that fail silently. So this is a config generator rather than a\n * request handler — `createAuthProxy` is for runtimes that have no proxy of\n * their own.\n *\n * Worth doing even where the browser would tolerate the cross-site setup,\n * because it is the same topology production runs on: a dev server that proxies\n * is rehearsing the deployment, and a dev server that does not is testing a\n * configuration no user will ever have. It is also the only way an embedded\n * sign-in flow works in Safari, which blocks third-party cookies outright.\n */\nexport function viteAuthProxy(\n options: ViteAuthProxyOptions,\n): Record<string, ViteProxyEntry> {\n const target = authOrigin(options.authHost);\n const basePath = normaliseBasePath(options.basePath ?? DEFAULT_BASE_PATH);\n const paths = options.paths ?? DEFAULT_FORWARDED_PATHS;\n\n const proxy: Record<string, ViteProxyEntry> = {};\n\n for (const prefix of paths) {\n proxy[`${basePath}${prefix}`] = {\n target,\n // The single most important line, and the one a hand-written config\n // leaves out. Without it the auth server is asked to answer as\n // `localhost:5173` — a Host it has no project for — and the reply is a\n // CORS refusal and an empty issuer rather than anything that says so.\n changeOrigin: true,\n // Only the base path comes off. The prefix below it is the path the auth\n // server actually serves.\n rewrite: (path: string) => (basePath ? path.replace(basePath, \"\") : path),\n };\n }\n\n return proxy;\n}\n"],"names":["DEFAULT_FORWARDED_PATHS","DEFAULT_BASE_PATH","authOrigin","authHost","configured","loopback","scheme","url","normaliseBasePath","basePath","trimmed","isUnder","pathname","prefix","viteAuthProxy","options","target","paths","proxy","path"],"mappings":"AAiCO,MAAMA,IAA0B,CAAC,YAAY,SAAS,GAQhDC,IAAoB;AAe1B,SAASC,EAAWC,GAA0B;AACnD,QAAMC,KAAcD,KAAY,IAAI,KAAA;AAEpC,MAAI,CAACC;AACH,UAAM,IAAI,UAAU,sBAAsB;AAG5C,QAAMC,IAAW,6CAA6C;AAAA,IAC5DD,EAAW,QAAQ,iBAAiB,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EAAA,GAGhDE,IAAS,gBAAgB,KAAKF,CAAU,IAAI,KAAK,GAAGC,IAAW,SAAS,OAAO;AAErF,MAAIE;AACJ,MAAI;AACF,IAAAA,IAAM,IAAI,IAAI,GAAGD,CAAM,GAAGF,CAAU,EAAE;AAAA,EACxC,QAAQ;AACN,UAAM,IAAI,UAAU,aAAaA,CAAU,kCAAkC;AAAA,EAC/E;AAEA,MAAIG,EAAI,aAAa,OAAOA,EAAI,UAAUA,EAAI;AAC5C,UAAM,IAAI;AAAA,MACR,aAAaH,CAAU;AAAA,IAAA;AAI3B,MAAIG,EAAI,aAAa,YAAY,CAACF;AAChC,UAAM,IAAI,UAAU,aAAaD,CAAU,kCAAkC;AAG/E,SAAOG,EAAI;AACb;AAYO,SAASC,EAAkBC,GAA0B;AAC1D,QAAMC,KAAWD,KAAY,IAAI,OAAO,QAAQ,QAAQ,EAAE;AAE1D,MAAIC,MAAY;AACd,WAAO;AAGT,MAAI,CAACA,EAAQ,WAAW,GAAG;AACzB,UAAM,IAAI,UAAU,aAAaD,CAAQ,uBAAuB;AAGlE,SAAOC;AACT;AAGO,SAASC,EAAQC,GAAkBC,GAAyB;AACjE,SAAOD,MAAaC,KAAUD,EAAS,WAAW,GAAGC,CAAM,GAAG;AAChE;ACtEO,SAASC,EACdC,GACgC;AAChC,QAAMC,IAASd,EAAWa,EAAQ,QAAQ,GACpCN,IAAWD,EAAkBO,EAAQ,YAAYd,CAAiB,GAClEgB,IAAQF,EAAQ,SAASf,GAEzBkB,IAAwC,CAAA;AAE9C,aAAWL,KAAUI;AACnB,IAAAC,EAAM,GAAGT,CAAQ,GAAGI,CAAM,EAAE,IAAI;AAAA,MAC9B,QAAAG;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc;AAAA;AAAA;AAAA,MAGd,SAAS,CAACG,MAAkBV,IAAWU,EAAK,QAAQV,GAAU,EAAE,IAAIU;AAAA,IAAA;AAIxE,SAAOD;AACT;"}
1
+ {"version":3,"file":"proxy.js","sources":["../src/proxy/target.ts","../src/proxy/vite.ts"],"sourcesContent":["/**\n * Where a proxied request is sent, and which requests are sent at all.\n *\n * Deliberately not shared with `resolveAuthBaseUrl` in the SDK, which answers a\n * different question. That one resolves what the BROWSER should call and its\n * most useful answer — a bare path like `/__auth` — is meaningless here: a\n * proxy runs on a server, where there is no page origin for a path to be\n * relative to. Sharing them would mean one function with a mode flag, and the\n * mode that is wrong in either direction is silent.\n */\n\n/**\n * The endpoints an app-level proxy has to carry, and the reason the list is\n * short.\n *\n * These are the requests the browser makes with `fetch` — the auth flow, the\n * token endpoint, userinfo, logout, branding CSS. They are the ones that need\n * to be same-origin, because they are the ones carrying cookies under\n * `SameSite=Lax`.\n *\n * Everything else on the auth server is a top-level navigation — `/authorize`,\n * the hosted sign-in page, `/logout` as a redirect — and a `Lax` cookie is\n * sent on those already, whatever origin they are served from. Proxying them\n * would not help, and it would break: the authorization server builds those\n * URLs absolute, on its own hostname, so the browser leaves the proxy at the\n * first redirect anyway.\n *\n * The two prefixes are the same pair the dev-server proxy uses (auth-api,\n * `docs/auth-domains-and-token-storage.md` §3). That is not a coincidence to be\n * tidied away: local development against a shared sandbox domain is the same\n * cross-site problem this solves in production, and the two configurations\n * being identical is what makes the local one a rehearsal.\n */\nexport const DEFAULT_FORWARDED_PATHS = [\"/auth/v1\", \"/oauth2\"] as const;\n\n/**\n * Where the endpoints hang off the app's own origin.\n *\n * `__`-prefixed by convention — Clerk uses `/__clerk`, Firebase `/__/auth` —\n * because it has to be a path no real route of the app will ever want.\n */\nexport const DEFAULT_BASE_PATH = \"/__auth\";\n\n/**\n * The auth server, as an origin.\n *\n * Accepts `tenant.idp.us.pontive.app` or `https://tenant.idp.us.pontive.app`,\n * and nothing with a path: the upstream path comes from the incoming request,\n * and a base path here would be silently prepended to endpoints the auth server\n * does not serve.\n *\n * `http://` is inferred for loopback only, and accepted only there. A proxy is\n * the one hop a refresh token cannot be carried over in the clear — it is the\n * hop that exists precisely so the cookie is first-party — and the failure is\n * invisible from the browser, which sees its own `https://` origin either way.\n */\nexport function authOrigin(authHost: string): string {\n const configured = (authHost ?? \"\").trim();\n\n if (!configured) {\n throw new TypeError(\"authHost is required\");\n }\n\n const loopback = /^(localhost|127\\.0\\.0\\.1|\\[::1\\])(:\\d+)?$/i.test(\n configured.replace(/^https?:\\/\\//i, \"\").split(\"/\")[0],\n );\n\n const scheme = /^https?:\\/\\//i.test(configured) ? \"\" : `${loopback ? \"http\" : \"https\"}://`;\n\n let url: URL;\n try {\n url = new URL(`${scheme}${configured}`);\n } catch {\n throw new TypeError(`authHost \"${configured}\" is not a hostname or an origin`);\n }\n\n if (url.pathname !== \"/\" || url.search || url.hash) {\n throw new TypeError(\n `authHost \"${configured}\" must be a bare origin — the path comes from the request being proxied`,\n );\n }\n\n if (url.protocol !== \"https:\" && !loopback) {\n throw new TypeError(`authHost \"${configured}\" must be https outside loopback`);\n }\n\n return url.origin;\n}\n\n/**\n * A base path with a leading slash and no trailing one, so joining is\n * unambiguous.\n *\n * `\"/\"` normalises to `\"\"`, which mounts the endpoints at the origin root —\n * `/auth/v1/...` and `/oauth2/...` where the app itself is served. That is the\n * shape a Vite dev server has always used, and it stays available because in\n * development the app owns the whole origin and there is nothing to collide\n * with. A deployed app usually does not, which is what the prefix is for.\n */\nexport function normaliseBasePath(basePath: string): string {\n const trimmed = (basePath ?? \"\").trim().replace(/\\/+$/, \"\");\n\n if (trimmed === \"\") {\n return \"\";\n }\n\n if (!trimmed.startsWith(\"/\")) {\n throw new TypeError(`basePath \"${basePath}\" must start with \"/\"`);\n }\n\n return trimmed;\n}\n\n/** Whether `pathname` is `prefix` itself or something under it. */\nexport function isUnder(pathname: string, prefix: string): boolean {\n return pathname === prefix || pathname.startsWith(`${prefix}/`);\n}\n","import {\n DEFAULT_BASE_PATH,\n DEFAULT_FORWARDED_PATHS,\n authOrigin,\n normaliseBasePath,\n} from \"./target\";\n\n/**\n * The shape of one entry in Vite's `server.proxy`.\n *\n * Declared here rather than imported from Vite so that nothing which imports\n * this module needs Vite installed, and so the published types do not depend on\n * a particular version of it. It is structural: Vite accepts this object.\n */\nexport interface ViteProxyEntry {\n target: string;\n changeOrigin: boolean;\n rewrite: (path: string) => string;\n}\n\nexport interface ViteAuthProxyOptions {\n authHost: string;\n basePath?: string;\n paths?: readonly string[];\n}\n\n/**\n * The auth endpoints, proxied through a Vite dev server.\n *\n * ```ts\n * // vite.config.ts\n * server: { proxy: viteAuthProxy({ authHost: env.VITE_SB_AUTH_DOMAIN }) }\n * ```\n *\n * Vite already has a proxy; what it does not have is the knowledge of which\n * paths to carry and what to do with Host, and both of those are easy to get\n * wrong in ways that fail silently. So this is a config generator rather than a\n * request handler — `createAuthProxy` is for runtimes that have no proxy of\n * their own.\n *\n * Worth doing even where the browser would tolerate the cross-site setup,\n * because it is the same topology production runs on: a dev server that proxies\n * is rehearsing the deployment, and a dev server that does not is testing a\n * configuration no user will ever have. It is also the only way an embedded\n * sign-in flow works in Safari, which blocks third-party cookies outright.\n */\nexport function viteAuthProxy(\n options: ViteAuthProxyOptions,\n): Record<string, ViteProxyEntry> {\n const target = authOrigin(options.authHost);\n const basePath = normaliseBasePath(options.basePath ?? DEFAULT_BASE_PATH);\n const paths = options.paths ?? DEFAULT_FORWARDED_PATHS;\n\n const proxy: Record<string, ViteProxyEntry> = {};\n\n for (const prefix of paths) {\n proxy[`${basePath}${prefix}`] = {\n target,\n // The single most important line, and the one a hand-written config\n // leaves out. Without it the auth server is asked to answer as\n // `localhost:5173` — a Host it has no project for — and the reply is a\n // CORS refusal and an empty issuer rather than anything that says so.\n changeOrigin: true,\n // Only the base path comes off. The prefix below it is the path the auth\n // server actually serves.\n rewrite: (path: string) => (basePath ? path.replace(basePath, \"\") : path),\n };\n }\n\n return proxy;\n}\n"],"names":["DEFAULT_FORWARDED_PATHS","DEFAULT_BASE_PATH","authOrigin","authHost","configured","loopback","scheme","url","normaliseBasePath","basePath","trimmed","isUnder","pathname","prefix","viteAuthProxy","options","target","paths","proxy","path"],"mappings":"AAiCO,MAAMA,IAA0B,CAAC,YAAY,SAAS,GAQhDC,IAAoB;AAe1B,SAASC,EAAWC,GAA0B;AACnD,QAAMC,KAAcD,KAAY,IAAI,KAAA;AAEpC,MAAI,CAACC;AACH,UAAM,IAAI,UAAU,sBAAsB;AAG5C,QAAMC,IAAW,6CAA6C;AAAA,IAC5DD,EAAW,QAAQ,iBAAiB,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EAAA,GAGhDE,IAAS,gBAAgB,KAAKF,CAAU,IAAI,KAAK,GAAGC,IAAW,SAAS,OAAO;AAErF,MAAIE;AACJ,MAAI;AACF,IAAAA,IAAM,IAAI,IAAI,GAAGD,CAAM,GAAGF,CAAU,EAAE;AAAA,EACxC,QAAQ;AACN,UAAM,IAAI,UAAU,aAAaA,CAAU,kCAAkC;AAAA,EAC/E;AAEA,MAAIG,EAAI,aAAa,OAAOA,EAAI,UAAUA,EAAI;AAC5C,UAAM,IAAI;AAAA,MACR,aAAaH,CAAU;AAAA,IAAA;AAI3B,MAAIG,EAAI,aAAa,YAAY,CAACF;AAChC,UAAM,IAAI,UAAU,aAAaD,CAAU,kCAAkC;AAG/E,SAAOG,EAAI;AACb;AAYO,SAASC,EAAkBC,GAA0B;AAC1D,QAAMC,KAAWD,KAAY,IAAI,OAAO,QAAQ,QAAQ,EAAE;AAE1D,MAAIC,MAAY;AACd,WAAO;AAGT,MAAI,CAACA,EAAQ,WAAW,GAAG;AACzB,UAAM,IAAI,UAAU,aAAaD,CAAQ,uBAAuB;AAGlE,SAAOC;AACT;AAGO,SAASC,EAAQC,GAAkBC,GAAyB;AACjE,SAAOD,MAAaC,KAAUD,EAAS,WAAW,GAAGC,CAAM,GAAG;AAChE;ACtEO,SAASC,EACdC,GACgC;AAChC,QAAMC,IAASd,EAAWa,EAAQ,QAAQ,GACpCN,IAAWD,EAAkBO,EAAQ,YAAYd,CAAiB,GAClEgB,IAAQF,EAAQ,SAASf,GAEzBkB,IAAwC,CAAA;AAE9C,aAAWL,KAAUI;AACnB,IAAAC,EAAM,GAAGT,CAAQ,GAAGI,CAAM,EAAE,IAAI;AAAA,MAC9B,QAAAG;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc;AAAA;AAAA;AAAA,MAGd,SAAS,CAACG,MAAkBV,IAAWU,EAAK,QAAQV,GAAU,EAAE,IAAIU;AAAA,IAAA;AAIxE,SAAOD;AACT;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pontive/pontkit-loader",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "license": "MIT",
5
5
  "description": "Loads @pontive/pontkit-core from the CDN at the release the platform decides.",
6
6
  "type": "module",
@@ -32,6 +32,6 @@
32
32
  "access": "public"
33
33
  },
34
34
  "devDependencies": {
35
- "@pontive/pontkit-core": "1.1.1"
35
+ "@pontive/pontkit-core": "1.1.4"
36
36
  }
37
37
  }