palbase 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.js +2 -2
- package/dist/backend/engine.js +2 -2
- package/dist/backend/env.js +1 -1
- package/dist/backend/index.js +3 -3
- package/dist/backend/stack.js +1 -1
- package/dist/backend/test.js +2 -2
- package/dist/chunks/5M3HV3X4.js +2 -0
- package/dist/chunks/{WEI32SAJ.js → 5RTSNQ4X.js} +2 -2
- package/dist/chunks/{BRBCWPR3.js → 6RXVXPHC.js} +1 -1
- package/dist/chunks/{JSJVV43D.js → 73R33XMD.js} +1 -1
- package/dist/chunks/{TUGRIOFX.js → 7XVI5JLP.js} +2 -2
- package/dist/chunks/{KDWDPSL2.js → CA4VJGGG.js} +1 -1
- package/dist/chunks/{RO5Y5YU4.js → KHHJRNAO.js} +1 -1
- package/dist/chunks/{5VTGMNPL.js → KJWHR5BP.js} +6 -6
- package/dist/chunks/{PDOHT46N.js → KYJJJUEU.js} +2 -2
- package/dist/chunks/{K6RRNI23.js → M4XLAPDF.js} +2 -2
- package/dist/chunks/{RBA6V3UO.js → MAYLG7WE.js} +2 -2
- package/dist/chunks/NSQAN2ME.js +6 -0
- package/dist/chunks/{WINBISC2.js → Q4XTWEAW.js} +3 -3
- package/dist/chunks/{BO5KR2EQ.js → RYI2OB52.js} +2 -2
- package/dist/chunks/{P4Z5E6ZI.js → RZ525VLP.js} +2 -2
- package/dist/chunks/{PGPQGKH2.js → T2Q5CKLL.js} +2 -2
- package/dist/chunks/{EGNEXFTZ.js → Y6AQWQBE.js} +2 -2
- package/dist/chunks/{Z5JVQNAZ.js → ZSKMWUIQ.js} +2 -2
- package/dist/cli.js +101 -101
- package/dist/refuse/ai.js +1 -1
- package/dist/refuse/backend.js +1 -1
- package/dist/refuse/server.js +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/testing.js +2 -2
- package/dist/web/index.js +2 -2
- package/dist/web/palbe.js +2 -2
- package/dist/web/paywall.js +2 -2
- package/dist/web/ssr.js +2 -2
- package/dist/web/vite.js +2 -2
- package/package.json +4 -2
- package/types/internal/src/modules/purchases.d.ts +109 -1
- package/types/web/src/index.d.ts +1 -1
- package/types/web/src/purchases.d.ts +48 -5
- package/dist/chunks/DB3SIBKB.js +0 -2
- package/dist/chunks/FZ3MQOVA.js +0 -6
package/dist/refuse/ai.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/ai is for servers: it speaks with the project secret key, which never goes into a browser or a mobile app \u2014 call your backend, and let it ask the model");
|
package/dist/refuse/backend.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/backend is a server framework: it runs on your backend, never in a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs)");
|
package/dist/refuse/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/server is for servers: its secret key never goes into a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs) with the publishable key");
|
package/dist/server/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{a as c,b as d,c as e,d as f,e as g,f as h,g as i,h as j,i as k,j as l,k as m,l as n,m as o,n as p,o as q,p as r,q as s,r as t}from"../chunks/
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as c,b as d,c as e,d as f,e as g,f as h,g as i,h as j,i as k,j as l,k as m,l as n,m as o,n as p,o as q,p as r,q as s,r as t}from"../chunks/ZSKMWUIQ.js";import"../chunks/CA4VJGGG.js";import{m as b}from"../chunks/Y6AQWQBE.js";import"../chunks/RYI2OB52.js";import{b as a}from"../chunks/KYJJJUEU.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";export{j as AuthUnavailable,b as EVENT_TYPES,a as PalbaseError,o as ReservationSettled,i as TokenError,l as TokenVerifier,d as WebhookSignatureError,c as createServer,n as isEntitled,t as loadSecrets,q as pages,s as platformOwn,r as processOwn,m as requestAddress,k as sessionStanding,g as signatureHeader,f as verifySignature,e as verifyWebhook,h as verifyWebhookRequest,p as withReservation};
|
package/dist/server/testing.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{a,b,c,d}from"../chunks/
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a,b,c,d}from"../chunks/MAYLG7WE.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";export{a as TestApiError,d as api,b as createTestApi,c as testRun};
|
package/dist/web/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{a as h,b as g,c as
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as h,b as g,c as C,d as w,e as v,f as E,g as S,h as k,i as R}from"../chunks/5M3HV3X4.js";import{a as T,b,f as P}from"../chunks/5RTSNQ4X.js";import"../chunks/Q4XTWEAW.js";import"../chunks/RZ525VLP.js";import"../chunks/Y6AQWQBE.js";import"../chunks/RYI2OB52.js";import{b as f}from"../chunks/KYJJJUEU.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";var V="oai-events";async function A(e){if(typeof e?.start!="function")throw new TypeError("connectVoice: start(sdp) is the round trip to the app's backend, which starts the voice (chats.voice.start) and answers { id, sdp }");let o=e.rtc??L(),t=e.signal;t?.throwIfAborted();let s=e.audio??O(),c=e.microphone===void 0,a=e.microphone??await o.getUserMedia({audio:!0});if(t?.aborted){if(c)for(let n of a.getTracks())n.stop();throw t.reason}let r=new o.RTCPeerConnection,d=!1,p=()=>{if(!d){if(d=!0,u.close(),r.close(),c)for(let n of a.getTracks())n.stop();s.srcObject!==null&&(s.srcObject=null)}};r.addEventListener("track",n=>{s.srcObject=n.streams[0]??new MediaStream([n.track]),s.play?.()?.catch?.(()=>{})}),r.addEventListener("connectionstatechange",()=>e.onState?.(r.connectionState));for(let n of a.getAudioTracks())r.addTrack(n,a);let u=r.createDataChannel(V);u.addEventListener("message",n=>{let i=M(n.data);i!==void 0&&e.onError?.(i)});let l=()=>p();t?.addEventListener("abort",l,{once:!0});try{await r.setLocalDescription(await r.createOffer()),t?.throwIfAborted(),await x(r,e.iceTimeoutMs??1e4,t);let n=r.localDescription?.sdp;if(!n)throw new Error("connectVoice: the peer connection made no offer");let i=await e.start(n);if(t?.throwIfAborted(),typeof i?.id!="string"||i.id===""||typeof i.sdp!="string"||i.sdp==="")throw new TypeError("connectVoice: start answered no voice \u2014 it is { id, sdp }, chats.voice.start's answer as the backend got it");return await r.setRemoteDescription({type:"answer",sdp:i.sdp}),t?.removeEventListener("abort",l),{id:i.id,peer:r,audio:s,microphone:a,get muted(){return a.getAudioTracks().every(y=>!y.enabled)},mute(y){for(let m of a.getAudioTracks())m.enabled=!y},close:p}}catch(n){throw t?.removeEventListener("abort",l),p(),t?.aborted?t.reason:n}}function x(e,o,t){return e.iceGatheringState==="complete"?Promise.resolve():t?.aborted?Promise.reject(t.reason):new Promise((s,c)=>{let a=()=>{clearTimeout(p),e.removeEventListener("icegatheringstatechange",r),t?.removeEventListener("abort",d)},r=()=>{e.iceGatheringState==="complete"&&(a(),s())},d=()=>{a(),c(t?.reason)},p=setTimeout(()=>{a(),c(new Error(`connectVoice: the network candidates were not gathered in ${o} ms`))},o);e.addEventListener("icegatheringstatechange",r),t?.addEventListener("abort",d,{once:!0})})}function M(e){if(typeof e=="string")try{let o=JSON.parse(e);return o.type!=="error"?void 0:typeof o.error?.message=="string"?o.error.message:typeof o.error?.code=="string"?o.error.code:"the voice failed"}catch{return}}function L(){let e=globalThis;if(typeof e.RTCPeerConnection!="function"||typeof e.navigator?.mediaDevices?.getUserMedia!="function")throw new TypeError("connectVoice: this runtime has no WebRTC (RTCPeerConnection, navigator.mediaDevices): a chat's voice is a browser's");let o=e.navigator.mediaDevices;return{RTCPeerConnection:e.RTCPeerConnection,getUserMedia:t=>o.getUserMedia(t)}}function O(){let e=globalThis.document;if(!e)throw new TypeError("connectVoice: give audio \u2014 the element the voice plays in \u2014 where there is no document");let o=e.createElement("audio");return o.autoplay=!0,o}export{E as Analytics,T as BackendError,w as Channel,P as GatewayError,f as PalbaseError,S as Purchases,v as RealtimeSocket,h as SessionChangedError,A as connectVoice,R as createClient,b as isBackendError,C as localStore,g as memoryStore,k as redemptionToken};
|
package/dist/web/palbe.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{c as e,d as r,i as t}from"../chunks/
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{c as e,d as r,i as t}from"../chunks/5RTSNQ4X.js";import"../chunks/RZ525VLP.js";import"../chunks/RYI2OB52.js";import"../chunks/KYJJJUEU.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
|
package/dist/web/paywall.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{a as e,b as a,c as t,d as l,e as o,f as p,g as r,h as y,i as s,j as P,k as i,l as n,m as w,n as f,o as d,p as m,q as u,r as A,s as c,t as v}from"../chunks/
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as e,b as a,c as t,d as l,e as o,f as p,g as r,h as y,i as s,j as P,k as i,l as n,m as w,n as f,o as d,p as m,q as u,r as A,s as c,t as v}from"../chunks/Q4XTWEAW.js";import"../chunks/KYJJJUEU.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";export{w as PAYWALL_COMPONENTS,i as PAYWALL_ICONS,n as PAYWALL_SCHEMA,c as Paywall,a as assetId,p as attributesHeader,f as countdownValues,v as defaultPaywall,e as fontFamily,s as formatPeriod,y as formatPrice,o as htmlDocument,P as packageValues,d as packagesOf,r as parseDuration,t as prepareAssets,A as renderPaywall,m as resolvePaywall,u as resolvePaywallWithPaths,l as unzip};
|
package/dist/web/ssr.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import{
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{i as f}from"../chunks/5M3HV3X4.js";import"../chunks/5RTSNQ4X.js";import"../chunks/Q4XTWEAW.js";import"../chunks/RZ525VLP.js";import"../chunks/Y6AQWQBE.js";import"../chunks/RYI2OB52.js";import"../chunks/KYJJJUEU.js";import"../chunks/KHHJRNAO.js";import"../chunks/73R33XMD.js";var C=Object.freeze({"Cache-Control":"private, no-cache, no-store, must-revalidate, max-age=0",Expires:"0",Pragma:"no-cache"}),x={path:"/",sameSite:"lax",secure:!0,httpOnly:!1,maxAge:400*24*60*60},u=3180,k=5*6e4;function d(t){let e=/^pb_([a-z0-9]+)_c/.exec(t)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");return`pb-${e}-session`}var y=t=>{let e=new TextEncoder().encode(JSON.stringify(t)),o="";for(let s of e)o+=String.fromCharCode(s);return btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},b=t=>{try{let e=atob(t.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(new TextDecoder().decode(Uint8Array.from(e,s=>s.charCodeAt(0))));return typeof o.accessToken!="string"||typeof o.refreshToken!="string"||typeof o.expiresAt!="number"||typeof o.userId!="string"?null:o}catch{return null}};function m(t,e,o={},s=!1){let c={...x,...o},g=async()=>new Map((await e.getAll()).map(n=>[n.name,n.value])),S=n=>n===t||n.startsWith(`${t}.`)&&/^\d+$/.test(n.slice(t.length+1)),h=async n=>{if(!e.setAll)return;let i=n===null?[]:n.length<=u?[[t,n]]:Array.from({length:Math.ceil(n.length/u)},(r,l)=>[`${t}.${l}`,n.slice(l*u,(l+1)*u)]),p=new Set(i.map(([r])=>r)),a=i.map(([r,l])=>({name:r,value:l,options:c}));for(let r of(await g()).keys())S(r)&&!p.has(r)&&a.push({name:r,value:"",options:{...c,maxAge:0}});a.length>0&&await e.setAll(a,{...C})};return{async load(){let n=await g(),i=n.get(t);if(i===void 0){let p="";for(let a=0;n.has(`${t}.${a}`);a++)p+=n.get(`${t}.${a}`);i=p}return i?b(i):null},save:n=>h(y(n)),clear:()=>h(null),shared:s}}function A(t){let{cookies:e,cookieOptions:o,...s}=t,c=t.refresh??(e.setAll?"before":"never");return f({...s,refresh:c,storage:m(d(t.publishableKey),e,o)})}function O(){let t=()=>{let e=globalThis.document;if(!e)throw new Error("documentCookies: there is no document here \u2014 a server gives its request's cookies to createServerClient");return e};return{getAll:()=>t().cookie.split(";").map(e=>e.trim()).filter(e=>e.includes("=")).map(e=>{let o=e.indexOf("=");return{name:e.slice(0,o),value:e.slice(o+1)}}),setAll(e){for(let o of e){let s=o.options,c=[`Path=${s.path??"/"}`,s.domain?`Domain=${s.domain}`:"",s.maxAge!==void 0?`Max-Age=${s.maxAge}`:"",s.expires?`Expires=${s.expires.toUTCString()}`:"",s.sameSite?`SameSite=${s.sameSite.charAt(0).toUpperCase()}${s.sameSite.slice(1)}`:"",s.secure?"Secure":""].filter(Boolean);t().cookie=[`${o.name}=${o.value}`,...c].join("; ")}}}}function $(t){let{cookieOptions:e,...o}=t,s=globalThis.location?.protocol==="https:";return f({...o,storage:m(d(t.publishableKey),O(),{secure:s,...e},!0)})}async function v(t){let e=await t.auth.currentSession();if(!e||(e.expiresAt-Date.now()<=k&&await t.auth.refreshSession().catch(()=>{}),!await t.auth.currentSession()))return null;try{return(await t.auth.api.verifyTokenUser()).data}catch(o){if(o.status===401)return null;throw o}}export{C as NO_STORE_HEADERS,x as SESSION_COOKIE_OPTIONS,m as cookieSessionStore,$ as createBrowserClient,A as createServerClient,O as documentCookies,v as keepSession,d as sessionCookieName};
|
package/dist/web/vite.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! palbase 0.8.
|
|
2
|
-
import"../chunks/
|
|
1
|
+
/*! palbase 0.8.1 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import"../chunks/73R33XMD.js";import{execFile as $}from"node:child_process";import{existsSync as y,mkdtempSync as k,readFileSync as S,rmSync as x,writeFileSync as P}from"node:fs";import{createRequire as O}from"node:module";import{tmpdir as W}from"node:os";import{dirname as g,join as o,relative as u,resolve as v,sep as d}from"node:path";var E=/\.(?:ts|js|mts|mjs)$/;function F(n){if(!/^[a-z][a-z0-9-]*$/.test(n.app))throw new TypeError(`palbase({ app }): ${JSON.stringify(n.app)} is an app's slug (palbase apps:list)`);let c=process.cwd(),p="",i="",f=()=>v(c,n.dir??"palbase"),m=()=>{let e=n.environments[p];if(!e)throw new Error(`palbase: the mode "${p}" is not built against any environment \u2014 say which in vite.config: palbase({ environments: { ${JSON.stringify(p)}: '<environment slug>' } })`);return e};return{name:"palbase",enforce:"pre",config(e,s){p=s.mode,i=s.command??"";let r=e.build?.rollupOptions?.onwarn;return{build:{rollupOptions:{onwarn(t,a){let l=String(t.exporter??t.id??"");if(t.code==="MISSING_EXPORT"&&l.includes(`${d}environments${d}`))throw new Error(`palbase: ${t.message} \u2014 ${m()}'s backend has no such route (palbase apps:sync brings what it has)`);r?r(t,a):a(t)}}}}},configResolved(e){c=e.root,p=e.mode,i=e.command??i},async buildStart(){i!=="build"||n.typecheck===!1||await j(c,m(),n.tsconfig)},resolveId(e,s){if(!s)return null;let r=f();if(e==="palbase"||e.startsWith("palbase/")){let w=u(r,s);return w.startsWith("..")||w===""?null:this.resolve(e,o(c,"index.html"),{skipSelf:!0})}if(!(e.startsWith(".")||e.startsWith("/")))return null;let t=v(g(s),e);if(E.test(t)||(t+=".ts"),g(t)!==r&&g(t)!==o(r,"palbe"))return null;let a=u(r,t),l=`${n.app}.ts`;if(a!==l&&!a.startsWith(`palbe${d}`))return null;let h=m(),b=o(r,"environments",h,a===l?l:o("palbe",a.slice(`palbe${d}`.length)));if(!y(b))throw new Error(`palbase: ${u(c,b)} is not there \u2014 palbase apps:sync writes it (is ${n.app} set in ${h}, and has ${h} that machine?)`);return b}}}async function j(n,c,p){let i=p?v(n,p):["tsconfig.app.json","tsconfig.json"].map(e=>o(n,e)).find(y);if(!i)return;if(!y(i))throw new Error(`palbase({ tsconfig }): ${u(n,i)} is not there`);let f;try{let e=O(o(n,"package.json")).resolve("typescript/package.json"),s=JSON.parse(S(e,"utf8")).bin?.tsc;if(!s)throw new Error("no tsc");f=o(g(e),s)}catch{throw new Error("palbase: the build type-checks the app against its environment with the app's TypeScript, and the app has none (npm i -D typescript) \u2014 or say palbase({ typecheck: false })")}let m=k(o(W(),"palbase-typecheck-"));try{let e=o(m,"tsconfig.json");P(e,JSON.stringify({extends:i,compilerOptions:{noEmit:!0,composite:!1,incremental:!1,moduleSuffixes:[`.${c}`,""]}}));let s=await new Promise(r=>$(process.execPath,[f,"-p",e,"--pretty","false"],{cwd:n,maxBuffer:16<<20},(t,a,l)=>r({code:t?typeof t.code=="number"?t.code:1:0,text:`${a}${l}`.trim()})));if(s.code!==0)throw new Error(`palbase: the app does not type-check against ${c}, the environment this build is made for \u2014 a route its backend does not have, or a call that does not fit it:
|
|
3
3
|
${s.text}`)}finally{x(m,{recursive:!0,force:!0})}}export{F as palbase};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "palbase",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Palbase for JavaScript: the web client (palbase/web), the server SDK (palbase/server), the backend framework (palbase/backend), AI (palbase/ai) and the CLI (npx palbase).",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://palbase.studio",
|
|
@@ -109,7 +109,9 @@
|
|
|
109
109
|
"README.md"
|
|
110
110
|
],
|
|
111
111
|
"dependencies": {
|
|
112
|
-
"
|
|
112
|
+
"@types/node": "26.6.4",
|
|
113
|
+
"bun-types": "1.4.2",
|
|
114
|
+
"palgres": "0.8.1",
|
|
113
115
|
"reflect-metadata": "^0.2.2",
|
|
114
116
|
"typescript": "~6.0.3",
|
|
115
117
|
"zod": "^4.6.5"
|
|
@@ -4861,7 +4861,7 @@ export type StripeAccount = {
|
|
|
4861
4861
|
*/
|
|
4862
4862
|
connected_by?: string;
|
|
4863
4863
|
/**
|
|
4864
|
-
* The key's last characters, to tell it apart.
|
|
4864
|
+
* The key's last characters, to tell it apart (a key's connection).
|
|
4865
4865
|
*/
|
|
4866
4866
|
key_hint?: string;
|
|
4867
4867
|
/**
|
|
@@ -4880,6 +4880,10 @@ export type StripeAccount = {
|
|
|
4880
4880
|
* Where Stripe reports changes on the account: the endpoint the module made there (POST /purchases/webhooks/stripe).
|
|
4881
4881
|
*/
|
|
4882
4882
|
webhook_url?: string;
|
|
4883
|
+
/**
|
|
4884
|
+
* How the account was connected: `app` — Palbase's Stripe App, installed with one click (no key, no endpoint on the account) — or `key` — a restricted key handed over.
|
|
4885
|
+
*/
|
|
4886
|
+
via?: "app" | "key";
|
|
4883
4887
|
};
|
|
4884
4888
|
/**
|
|
4885
4889
|
* A Stripe event, as Stripe signs and sends it: only its id, type and the id of the object it names are read; the object is read again from Stripe.
|
|
@@ -5237,6 +5241,54 @@ export type RedemptionRequest = {
|
|
|
5237
5241
|
*/
|
|
5238
5242
|
key?: string;
|
|
5239
5243
|
};
|
|
5244
|
+
/**
|
|
5245
|
+
* A link to install Palbase's Stripe App, in a mode.
|
|
5246
|
+
*/
|
|
5247
|
+
export type StripeAppGrantRequest = {
|
|
5248
|
+
/**
|
|
5249
|
+
* Live mode, or Stripe's test mode (false).
|
|
5250
|
+
*/
|
|
5251
|
+
livemode: boolean;
|
|
5252
|
+
};
|
|
5253
|
+
/**
|
|
5254
|
+
* A one-time link to install Palbase's Stripe App for the project.
|
|
5255
|
+
*/
|
|
5256
|
+
export type StripeAppInstall = {
|
|
5257
|
+
/**
|
|
5258
|
+
* Palbase's install page, the grant in its fragment: open it in a browser; it names the project, then goes on to Stripe, where the account's owner picks the account and accepts what the App may do.
|
|
5259
|
+
*/
|
|
5260
|
+
install_url: string;
|
|
5261
|
+
/**
|
|
5262
|
+
* When the link stops working (30 minutes; for an environment's token, no later than the token).
|
|
5263
|
+
*/
|
|
5264
|
+
expires_at: string;
|
|
5265
|
+
};
|
|
5266
|
+
/**
|
|
5267
|
+
* An install started with its link's grant.
|
|
5268
|
+
*/
|
|
5269
|
+
export type StripeAppStartRequest = {
|
|
5270
|
+
/**
|
|
5271
|
+
* The link's grant: `<project id>.<token>`, from its fragment.
|
|
5272
|
+
*/
|
|
5273
|
+
grant: string;
|
|
5274
|
+
};
|
|
5275
|
+
/**
|
|
5276
|
+
* An install started: the project the account will be connected to, and Stripe's page to go on to.
|
|
5277
|
+
*/
|
|
5278
|
+
export type StripeAppStart = {
|
|
5279
|
+
/**
|
|
5280
|
+
* The Palbase project's name.
|
|
5281
|
+
*/
|
|
5282
|
+
project: string;
|
|
5283
|
+
/**
|
|
5284
|
+
* Live mode, or Stripe's test mode.
|
|
5285
|
+
*/
|
|
5286
|
+
livemode: boolean;
|
|
5287
|
+
/**
|
|
5288
|
+
* Stripe's install page: its state is the install's nonce, which the browser keeps.
|
|
5289
|
+
*/
|
|
5290
|
+
authorize_url: string;
|
|
5291
|
+
};
|
|
5240
5292
|
/** The events this module sends the project's webhooks (x-palbase-events), by type: each one's payload, the event's data. */
|
|
5241
5293
|
export interface Events {
|
|
5242
5294
|
/**
|
|
@@ -5594,6 +5646,38 @@ export declare function client(t: Transport): {
|
|
|
5594
5646
|
body: ConnectStripeKeyRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
5595
5647
|
signal?: AbortSignal;
|
|
5596
5648
|
}): Promise<Reply<200, StripeAccount>>;
|
|
5649
|
+
/**
|
|
5650
|
+
* The Stripe App's install page
|
|
5651
|
+
*
|
|
5652
|
+
* The page an install link opens: its script reads the grant from the fragment, starts the install (POST /purchases/stripe/app/install) and names the Palbase project the Stripe account will be connected to before the installer goes on to Stripe. No credential: the grant is the authorization.
|
|
5653
|
+
*/
|
|
5654
|
+
getStripeAppInstallPage(input?: {
|
|
5655
|
+
signal?: AbortSignal;
|
|
5656
|
+
}): Promise<Reply<200, Response>>;
|
|
5657
|
+
/**
|
|
5658
|
+
* Start a Stripe App install
|
|
5659
|
+
*
|
|
5660
|
+
* Starts an install with its link's grant, once: the grant is traded for the install's nonce, kept in the browser (an HttpOnly cookie of Palbase's address) and carried by Stripe (the state) — the way back is taken only in this browser, and the grant never reaches Stripe. Answers the project's name and Stripe's install page. A grant of no project, used, expired or started already: 410 `grant_invalid`, the same answer for each.
|
|
5661
|
+
*/
|
|
5662
|
+
startStripeAppInstall(input: {
|
|
5663
|
+
body: StripeAppStartRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
5664
|
+
signal?: AbortSignal;
|
|
5665
|
+
}): Promise<Reply<200, StripeAppStart>>;
|
|
5666
|
+
/**
|
|
5667
|
+
* The Stripe App's return
|
|
5668
|
+
*
|
|
5669
|
+
* Where Stripe sends a Stripe App's installer back, with the install's code and its state (the project and the install's nonce): taken only in the browser that started the install — its cookie is the nonce —, where the grant, tried once more, names the project; the code is traded at Stripe for the install's tokens, sealed under the project's key, and the account is the project's connection. A cancelled install (`error`) spends its grant; an account already connected through the App to another project is refused. Answers a page the installer reads. No credential: the grant and the browser's nonce are the authorization.
|
|
5670
|
+
*/
|
|
5671
|
+
completeStripeAppInstall(input?: {
|
|
5672
|
+
query?: {
|
|
5673
|
+
code?: string; /** The link's state: the project and its grant. */
|
|
5674
|
+
state?: string; /** What the App may do, as Stripe granted it. */
|
|
5675
|
+
scope?: string; /** Stripe's error, when the installer did not finish. */
|
|
5676
|
+
error?: string; /** And its words. */
|
|
5677
|
+
error_description?: string;
|
|
5678
|
+
}; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
5679
|
+
signal?: AbortSignal;
|
|
5680
|
+
}): Promise<Reply<200, Response>>;
|
|
5597
5681
|
/**
|
|
5598
5682
|
* Read a customer
|
|
5599
5683
|
*
|
|
@@ -6353,6 +6437,18 @@ export declare function client(t: Transport): {
|
|
|
6353
6437
|
}; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
6354
6438
|
signal?: AbortSignal;
|
|
6355
6439
|
}): Promise<Reply<201, StripeGrant>>;
|
|
6440
|
+
/**
|
|
6441
|
+
* Install the Stripe App
|
|
6442
|
+
*
|
|
6443
|
+
* A one-time link, good for 30 minutes, to connect the project's Stripe account with one click: Palbase's Stripe App, installed at Stripe in the mode asked — no key pasted, nothing made on the account (the App's events come to Palbase's own endpoint). The link is Palbase's install page, the grant in its fragment (no browser sends it): the page names the project the account will be connected to, trades the grant — once — for the install's nonce, which the browser keeps and Stripe carries back, and goes on to Stripe. Stripe sends the installer back to Palbase (GET /purchases/stripe/app/callback), in the same browser, which connects the account in place of any connected before. One Stripe account, in a mode, is one Palbase project's App connection. A restricted key (POST /purchases/stripe/grants) stays the other way. A project holds 10 open grants at most (429 `too_many_grants`); a Palbase that runs no App in that mode answers 503 `stripe_app_unavailable`.
|
|
6444
|
+
*/
|
|
6445
|
+
createStripeAppInstall(input: {
|
|
6446
|
+
headers?: {
|
|
6447
|
+
"Idempotency-Key"?: string;
|
|
6448
|
+
};
|
|
6449
|
+
body: StripeAppGrantRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
6450
|
+
signal?: AbortSignal;
|
|
6451
|
+
}): Promise<Reply<201, StripeAppInstall>>;
|
|
6356
6452
|
/**
|
|
6357
6453
|
* Manage what was bought on the web
|
|
6358
6454
|
*
|
|
@@ -6392,5 +6488,17 @@ export declare function client(t: Transport): {
|
|
|
6392
6488
|
body: StripeEvent; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
6393
6489
|
signal?: AbortSignal;
|
|
6394
6490
|
}): Promise<Reply<200, undefined>>;
|
|
6491
|
+
/**
|
|
6492
|
+
* Receive the Stripe App's events
|
|
6493
|
+
*
|
|
6494
|
+
* Where Stripe sends the events of every account that installed Palbase's Stripe App, signed for Palbase's own endpoint of either mode (Stripe-Signature) — no key. Each is handed to the projects connected through the App to its account in its mode, and applied there as a project's Stripe event (ReceiveStripeEvent): the object it names is read again from Stripe as the account, an event of another environment's object is ignored there, and each is kept once per project by its event id. An uninstall (`apps.install.deleted`, `account.application.deauthorized`) refuses the connection. Stripe hears 2xx only once every project took it.
|
|
6495
|
+
*/
|
|
6496
|
+
receiveStripeAppEvent(input: {
|
|
6497
|
+
headers: {
|
|
6498
|
+
"Stripe-Signature": string;
|
|
6499
|
+
};
|
|
6500
|
+
body: StripeEvent; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
|
|
6501
|
+
signal?: AbortSignal;
|
|
6502
|
+
}): Promise<Reply<200, undefined>>;
|
|
6395
6503
|
};
|
|
6396
6504
|
export type Client = ReturnType<typeof client>;
|
package/types/web/src/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { Channel, RealtimeSocket, type ChannelOptions, type PushReply } from './
|
|
|
5
5
|
export { Analytics, type AnalyticsOptions } from './analytics.js';
|
|
6
6
|
export type { AgentEvent, ChatAttachment, ChatEvent, ChatGoal, ChatItem, ChatMessageView, ChatPart, ChatPartsPage, ChatPartsQuery, ChatResponse, ChatState, ChatStreamPart, ChatThinking, ChatToolCall, ChatVoice, GatewayChat, GoalEvent, HistoryEvent, HistoryItem, Publication, ThinkingEvent, ToolEvent, TranscriptEvent, TurnEnd, TurnEvent, VoiceEvent, } from './chat.js';
|
|
7
7
|
export { connectVoice, type StartedVoice, type VoiceConnection, type VoiceOptions } from './voice.js';
|
|
8
|
-
export { Purchases, type CustomerInfo, type CustomerInfoListener, type MergeGrant, type Offerings } from './purchases.js';
|
|
8
|
+
export { Purchases, redemptionToken, type CheckoutSource, type CustomerInfo, type CustomerInfoListener, type MergeGrant, type Offerings, type RedemptionLink } from './purchases.js';
|
|
9
9
|
export type { Paywall, PaywallRenderOptions } from './paywall/placement.js';
|
|
10
10
|
export type { PaywallAttribute } from './paywall/attributes.js';
|
|
11
11
|
export type { PaywallPackage, PaywallView } from './paywall/render.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { purchases as purchasesModule } from '../../internal/src/modules/index.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type Fetch, type Transport } from '../../internal/src/transport.js';
|
|
3
3
|
import type { SessionManager } from './session.js';
|
|
4
4
|
import type { RealtimeSocket } from './socket.js';
|
|
5
5
|
import type { PaywallAttribute } from './paywall/attributes.js';
|
|
@@ -8,6 +8,9 @@ type P = typeof purchasesModule;
|
|
|
8
8
|
export type CustomerInfo = purchasesModule.CustomerInfo;
|
|
9
9
|
export type Offerings = purchasesModule.Offerings;
|
|
10
10
|
export type MergeGrant = purchasesModule.MergeGrant;
|
|
11
|
+
export type RedemptionLink = purchasesModule.RedemptionLink;
|
|
12
|
+
/** Where a checkout is opened: an app linking out to buy on the web says its platform and its store's storefront (ISO 3166-1 alpha-3: `USA`). */
|
|
13
|
+
export type CheckoutSource = purchasesModule.CheckoutSource;
|
|
11
14
|
/** Told what the customer has: on the first read, then each time it changes; null while no one is signed in. */
|
|
12
15
|
export type CustomerInfoListener = (info: CustomerInfo | null) => void;
|
|
13
16
|
export declare class Purchases {
|
|
@@ -59,17 +62,53 @@ export declare class Purchases {
|
|
|
59
62
|
signal?: AbortSignal;
|
|
60
63
|
}): Promise<Paywall | null>;
|
|
61
64
|
/**
|
|
62
|
-
* Opens Stripe Checkout
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
65
|
+
* Opens Stripe Checkout to buy a product's plan sold on the web: the URL to
|
|
66
|
+
* send the buyer to. Stripe sends them back to successUrl or cancelUrl —
|
|
67
|
+
* one of the project's registered apps. Signed in — a guest too — the
|
|
68
|
+
* purchase is the customer's once Stripe reports it: onCustomerInfo hears
|
|
69
|
+
* it. With no one signed in the buyer is no one yet: Checkout asks their
|
|
70
|
+
* email, no free trial is given, and what they buy waits for the app user
|
|
71
|
+
* who redeems it — its link is on the success page (redemptionLink: put
|
|
72
|
+
* `{CHECKOUT_SESSION_ID}` in successUrl, Stripe writes the session's id
|
|
73
|
+
* there) and in their email. The key the success page asks it with is
|
|
74
|
+
* kept in this tab's sessionStorage, which the redirect to Stripe and back
|
|
75
|
+
* keeps. `source` says where the checkout was opened, when an app links
|
|
76
|
+
* out.
|
|
66
77
|
*/
|
|
67
78
|
checkout(opts: {
|
|
68
79
|
product: string;
|
|
69
80
|
plan: string;
|
|
70
81
|
successUrl: string;
|
|
71
82
|
cancelUrl: string;
|
|
83
|
+
source?: CheckoutSource;
|
|
72
84
|
}): Promise<string>;
|
|
85
|
+
/**
|
|
86
|
+
* On a checkout's success page, for a buyer with no account: the one-time
|
|
87
|
+
* link — good for an hour — that hands what they bought to the app user
|
|
88
|
+
* who opens it on their phone (show it, and its QR code on a computer).
|
|
89
|
+
* sessionId is Stripe's (`{CHECKOUT_SESSION_ID}` in successUrl); the key
|
|
90
|
+
* is the one checkout() kept in this tab, or `key` when the app kept it
|
|
91
|
+
* itself — without it the page has none to show (`redemption_key_missing`:
|
|
92
|
+
* the buyer's email has it). Stripe may not have told of the payment yet:
|
|
93
|
+
* it is asked again for up to waitSeconds (20). Each call makes a new
|
|
94
|
+
* link — ten at most, within an hour of the payment.
|
|
95
|
+
*/
|
|
96
|
+
redemptionLink(sessionId: string, opts?: {
|
|
97
|
+
key?: string;
|
|
98
|
+
waitSeconds?: number;
|
|
99
|
+
signal?: AbortSignal;
|
|
100
|
+
}): Promise<RedemptionLink>;
|
|
101
|
+
/**
|
|
102
|
+
* Redeems a web purchase's link for the signed-in user — a guest too, whose
|
|
103
|
+
* purchases go with it to the account it signs in to: what it bought is
|
|
104
|
+
* theirs; what they have now. Takes the link the app was opened with
|
|
105
|
+
* (`<scheme>://palbase/redeem?token=…`, or its page's
|
|
106
|
+
* `https://…/purchases/redeem?token=…`) or its token. A link works once (409
|
|
107
|
+
* `already_redeemed`); one past its hour is refused (410
|
|
108
|
+
* `redemption_expired`) and sends a new one to the buyer's email — the
|
|
109
|
+
* error's `body.resent` says so.
|
|
110
|
+
*/
|
|
111
|
+
redeem(link: string): Promise<CustomerInfo>;
|
|
73
112
|
/** Stripe's customer portal for what the customer bought on the web: the URL to send them to, and back to returnUrl. */
|
|
74
113
|
portal(returnUrl: string): Promise<string>;
|
|
75
114
|
/**
|
|
@@ -85,6 +124,8 @@ export declare class Purchases {
|
|
|
85
124
|
* grant, it is the same merge.
|
|
86
125
|
*/
|
|
87
126
|
merge(grant: MergeGrant | string): Promise<CustomerInfo>;
|
|
127
|
+
/** Where this tab keeps a checkout's redemption key. */
|
|
128
|
+
private keyName;
|
|
88
129
|
/**
|
|
89
130
|
* Listens to what the signed-in customer has: told it once read, then each
|
|
90
131
|
* time it changes — a purchase in any store, a renewal or its end, a
|
|
@@ -104,4 +145,6 @@ export declare class Purchases {
|
|
|
104
145
|
private offer;
|
|
105
146
|
private tell;
|
|
106
147
|
}
|
|
148
|
+
/** A redemption link's token: of `<scheme>://palbase/redeem?token=…`, of its page `…/purchases/redeem?token=…`, or the token itself. */
|
|
149
|
+
export declare function redemptionToken(link: string): string | undefined;
|
|
107
150
|
export {};
|
package/dist/chunks/DB3SIBKB.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! palbase 0.8.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
-
import{e as B,g as G,h as H}from"./WEI32SAJ.js";import{u as J}from"./WINBISC2.js";import{b as M,c as w,h as F}from"./EGNEXFTZ.js";import{a as $,b as S}from"./BO5KR2EQ.js";import{b as O,d as b}from"./PDOHT46N.js";function re(n){let e=n,t=e?.body,s=t&&typeof t=="object"?t.reason:void 0;return s==="user_deleted"?"userDeleted":s==="user_banned"?"userBanned":e?.code==="session_expired"||e?.code==="token_expired"?"expired":"revoked"}var y=class extends Error{code="session_changed";constructor(e){super(e),this.name="SessionChangedError"}};function V(){let n=null;return{load:()=>n,save:e=>{n=e},clear:()=>{n=null},shared:!1}}function W(n){let e=null,t=!0,s=()=>{try{return globalThis.localStorage}catch{return}};return{shared:!0,load(){try{let i=s()?.getItem(n);return i==null?t?null:e:JSON.parse(i)}catch{return e}},save(i){e=i;try{let r=s();if(!r)throw new Error("no storage");r.setItem(n,JSON.stringify(i)),t=!0}catch{t=!1}},clear(){e=null,t=!0;try{s()?.removeItem(n)}catch{}},watch(i){let r=globalThis;if(typeof r.addEventListener!="function")return()=>{};let a=o=>{(o.key===n||o.key===null)&&i()};return r.addEventListener("storage",a),()=>r.removeEventListener?.("storage",a)}}}function oe(n){try{let e=n.split(".")[1]??"",t=atob(e.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(e.length/4)*4,"=")),s=JSON.parse(t).sub;return typeof s=="string"?s:""}catch{return""}}var ae=6e4,le=15e3;function ce(n,e,t){let s=n?globalThis.navigator?.locks:void 0;return s?s.request(e,t):t()}var k=class{current=null;loaded;inflight=null;endReason=null;listeners=new Set;store;refresher;isRejected;now;lockName;refreshTimeoutMs;mode;constructor(e,t,s,i={}){this.store=e,this.refresher=t,this.isRejected=s,this.now=i.now??Date.now,this.lockName=i.lockName??"palbase.session.refresh",this.refreshTimeoutMs=i.refreshTimeoutMs??le,this.mode=i.refresh??"behind",this.loaded=Promise.resolve(e.load()).then(r=>{this.current=r}),e.watch?.(()=>{this.reconcile()})}async session(){return await this.loaded,this.current}snapshot(){return this.current}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async set(e,t,s){await this.loaded;let i=t==="TOKEN_REFRESHED"?this.current:null,r={accessToken:e.access_token,refreshToken:e.refresh_token,expiresAt:this.now()+e.expires_in*1e3,userId:s?.id??i?.userId??oe(e.access_token),user:s??i?.user};return this.current=r,await this.store.save(r),this.emit(t,r),r}async setUser(e,t){await this.loaded,!(!this.current||!t||this.current.userId!==t.userId)&&(this.current={...this.current,user:e},await this.store.save(this.current),this.emit("USER_UPDATED",this.current))}async clear(e,t){await this.loaded;let s=this.current;this.current=null,this.inflight=null;let i=await this.store.load();(!i||!s||i.userId===s.userId)&&await this.store.clear(),s&&(e==="SESSION_EXPIRED"&&(this.endReason=t??"revoked"),this.emit(e,null))}async accessToken(){await this.loaded;let e=this.current;if(!e)return;let t=e.expiresAt-this.now();if(t>ae)return e.accessToken;if(this.mode==="never")return t>0?e.accessToken:void 0;if(t>0&&this.mode==="behind")return this.refresh().catch(()=>{}),e.accessToken;if(t>0)try{return(await this.refresh()).accessToken}catch(s){if(this.current===e)return e.accessToken;throw s}return(await this.refresh()).accessToken}refresh(){if(this.mode==="never")return Promise.reject(new Error("this client does not renew its session (refresh: 'never'): where the session cannot be written back, the request's middleware renews it"));if(this.inflight)return this.inflight;let e=ce(this.store.shared===!0,this.lockName,async()=>{await this.loaded;let t=this.current;if(!t)throw new y("no session to refresh");let s=await this.adoptStored(t);if(s)return s;try{let i=await this.withTimeout(this.refresher(t.refreshToken));if(this.current?.refreshToken!==t.refreshToken)throw new y("the session changed while it was refreshed");return await this.set(i,"TOKEN_REFRESHED")}catch(i){throw this.isRejected(i)&&this.current?.refreshToken===t.refreshToken&&await this.clear("SESSION_EXPIRED",re(i)),i}});return this.inflight=e,e.finally(()=>{this.inflight===e&&(this.inflight=null)}).catch(()=>{}),e}async adoptStored(e){let t=await this.store.load();if(!t)throw this.current=null,this.emit("SIGNED_OUT",null),new y("signed out in another tab");if(t.userId!==e.userId)throw this.current=t,this.emit("SIGNED_OUT",null),this.emit("SIGNED_IN",t),new y("another user signed in in another tab");if(t.refreshToken!==e.refreshToken&&t.expiresAt>=e.expiresAt)return this.current=t,this.emit("TOKEN_REFRESHED",t),t}async reconcile(){await this.loaded;let e=this.current,t=await this.store.load();if(!e){t&&(this.current=t,this.emit("SIGNED_IN",t));return}await this.adoptStored(e).catch(()=>{})}withTimeout(e){let t,s=new Promise((i,r)=>{t=setTimeout(()=>r(new Error(`the refresh did not answer within ${this.refreshTimeoutMs/1e3} s`)),this.refreshTimeoutMs)});return Promise.race([e,s]).finally(()=>clearTimeout(t))}emit(e,t){(e==="SIGNED_IN"||e==="SIGNED_OUT")&&(this.endReason=null);for(let s of this.listeners)try{s(e,t)}catch{}}};var N=class{state="closed";refusal;logSeq;joinRef=null;listeners=new Map;closers=new Set;joinWaiters=[];name;socket;constructor(e,t,s={}){this.name=e,this.socket=t,this.logSeq=s.after}get topic(){return`realtime:${this.name}`}join(){if(this.state==="joined")return Promise.resolve();let e=new Promise((t,s)=>this.joinWaiters.push({resolve:t,reject:s}));return this.state!=="joining"&&this.socket.join(this),e}leave(){this.socket.leave(this)}push(e,t){return this.socket.request(this,e,t)}on(e,t){let s=this.listeners.get(e);return s||this.listeners.set(e,s=new Set),s.add(t),()=>s.delete(t)}onClosed(e){return this.closers.add(e),()=>this.closers.delete(e)}deliver(e,t){e==="broadcast"&&typeof t.seq=="number"&&(this.logSeq=t.seq);for(let s of this.listeners.get(e)??[])try{s(t)}catch{}}settled(e,t){e&&typeof t.log_seq=="number"&&(this.logSeq=t.log_seq),this.state=e?"joined":"refused",this.refusal=e?void 0:t;let s=this.joinWaiters.splice(0);for(let i of s)e?i.resolve():i.reject(new Error(`join ${this.name} refused: ${JSON.stringify(t)}`))}closed(e){this.state="closed",this.joinRef=null;let t=this.joinWaiters.splice(0);for(let s of t)s.reject(new Error(`join ${this.name}: ${e}`));for(let s of[...this.closers])try{s()}catch{}}},R=class{ws=null;opening=null;ref=0;channels=new Map;replies=new Map;heartbeat=null;heartbeatRef=null;reconnectTimer=null;attempts=0;closedByUs=!1;reconnects=0;opts;constructor(e){this.opts=e}channel(e,t){let s=this.channels.get(e);return s||this.channels.set(e,s=new N(e,this,t)),s}disconnect(){this.closedByUs=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.stopHeartbeat();let e=this.ws;this.ws=null,this.opening=null,e?.close(1e3);for(let[,t]of this.replies)t("error",{reason:"socket closed"});this.replies.clear();for(let t of this.channels.values())t.closed("the socket was closed")}async tokenChanged(){if(!this.ws||this.ws.readyState!==1)return;let e=await this.opts.accessToken();if(e)for(let t of this.channels.values())t.state==="joined"&&this.push(t.joinRef,t.topic,"access_token",{access_token:e})}join(e){e.state="joining",this.open().then(()=>this.sendJoin(e)).catch(t=>e.settled(!1,{reason:t instanceof Error?t.message:String(t)}))}leave(e){e.state==="joined"&&this.ws?.readyState===1&&this.push(e.joinRef,e.topic,"phx_leave",{}),e.state="closed",this.channels.delete(e.name)}async request(e,t,s){let i=this.ws;if(this.channels.get(e.name)!==e||e.state!=="joined"||i?.readyState!==1)return{status:"error",response:{reason:"not joined"}};let r=this.nextRef(),a=JSON.stringify([e.joinRef,r,e.topic,t,s]),o=this.awaitReply(r);return i.send(a),o}open(){if(this.ws?.readyState===1)return Promise.resolve();if(this.opening)return this.opening;this.closedByUs=!1;let e=this.opts.webSocket??globalThis.WebSocket,t=`${this.opts.baseUrl.replace(/^http/,"ws")}/realtime/v1/websocket?vsn=2.0.0&apikey=${encodeURIComponent(this.opts.publishableKey)}`,s=new Promise((i,r)=>{let a=new e(t);this.ws=a,a.onopen=()=>{this.attempts=0,this.startHeartbeat(),i()},a.onmessage=o=>this.receive(String(o.data)),a.onerror=()=>r(new Error("the realtime socket could not be opened")),a.onclose=()=>this.dropped(a)});return this.opening=s,s.finally(()=>{this.opening===s&&(this.opening=null)}).catch(()=>{}),s}dropped(e){if(this.ws!==e)return;this.ws=null,this.stopHeartbeat();for(let[,i]of this.replies)i("error",{reason:"socket closed"});this.replies.clear();for(let i of this.channels.values())i.state==="joined"&&(i.state="joining");if(this.closedByUs||![...this.channels.values()].some(i=>i.state==="joining"))return;let t=this.opts.backoff??[500,1e3,2e3,5e3,1e4,3e4],s=t[Math.min(this.attempts,t.length-1)]*(.8+Math.random()*.4);this.attempts++,this.reconnectTimer=T(setTimeout(()=>{this.reconnectTimer=null,this.reconnects++;let i=[...this.channels.values()].filter(r=>r.state==="joining");this.open().then(()=>Promise.all(i.map(r=>this.sendJoin(r)))).catch(()=>{})},s))}async sendJoin(e){let t=await this.opts.accessToken(),s=this.nextRef();e.joinRef=s;let i=this.awaitReply(s),r={broadcast:{self:!1}};e.logSeq!==void 0&&(r.log={after:e.logSeq}),this.push(s,e.topic,"phx_join",{access_token:t,config:r},s);let{status:a,response:o}=await i;if(this.channels.get(e.name)!==e||e.state!=="joining"){a==="ok"&&this.ws?.readyState===1&&this.push(s,e.topic,"phx_leave",{});return}e.settled(a==="ok",o)}awaitReply(e){return new Promise(t=>{let s=T(setTimeout(()=>{this.replies.delete(e),t({status:"timeout",response:{reason:"no reply"}})},this.opts.replyTimeoutMs??1e4));this.replies.set(e,(i,r)=>{clearTimeout(s),this.replies.delete(e),t({status:i,response:r})})})}receive(e){let t;try{t=JSON.parse(e)}catch{return}if(!Array.isArray(t)||t.length!==5||typeof t[2]!="string"||typeof t[3]!="string")return;let[,s,i,r,a]=t,o=typeof a=="object"&&a!==null?a:{};if(r==="phx_reply"&&typeof s=="string"){if(s===this.heartbeatRef){this.heartbeatRef=null;return}this.replies.get(s)?.(String(o.status),o.response??{});return}let c=[...this.channels.values()].find(l=>l.topic===i);if(c){if(r==="phx_close"){c.state="closed";return}if(r==="phx_error"){c.state="joining",T(setTimeout(()=>this.channels.get(c.name)===c&&c.state==="joining"&&this.ws?.readyState===1&&void this.sendJoin(c),1e3));return}c.deliver(r,o)}}push(e,t,s,i,r=this.nextRef()){this.ws?.send(JSON.stringify([e,r,t,s,i]))}nextRef(){return String(++this.ref)}startHeartbeat(){this.stopHeartbeat(),this.heartbeat=T(setInterval(()=>{if(this.heartbeatRef!==null){this.heartbeatRef=null,this.ws?.close(4e3);return}this.heartbeatRef=this.nextRef(),this.push(null,"phoenix","heartbeat",{},this.heartbeatRef)},this.opts.heartbeatMs??25e3))}stopHeartbeat(){this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null,this.heartbeatRef=null}};function T(n){return n.unref?.(),n}var he=30*6e4,X=1e3,de=100,fe=60*1024,P=()=>globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;function I(){try{return globalThis.localStorage}catch{return}}var _=class{api;closingApi;flushMs;flushAt;now;anonKey;sessionKey;events=[];samples=[];timer;memoryAnon;memorySession;appVersion;stopAuto;session;identifyPending=!1;constructor(e,t,s,i={}){this.session=t,this.api=M.client(e),this.closingApi=M.client({send:r=>e.send({...r,keepalive:!0})}),this.flushMs=i.flushMs??5e3,this.flushAt=i.flushAt??20,this.now=i.now??Date.now,this.anonKey=`palbase.analytics.anonymous.${s}`,this.sessionKey=`palbase.analytics.session.${s}`,t.onChange(r=>{r==="SIGNED_IN"?(this.identifyPending=!0,this.soon()):r==="SIGNED_OUT"&&(this.identifyPending=!1,this.reset())})}capture(e,t){let s=this.now();this.hold({event:e,distinct_id:this.distinctId(),properties:t,timestamp:s,session_id:this.sessionId(s),...this.appVersion?{app_version:this.appVersion}:{}})}page(e={}){let t=globalThis.location,s=globalThis.document,i=e.url??(t?`${t.origin}${t.pathname}`:"");if(!i)return;let r=e.referrer??ve(s?.referrer);this.capture("$pageview",{...e.properties,url:i,...e.title??s?.title?{title:e.title??s?.title}:{},...r?{referrer:r}:{}})}async identify(e){this.identifyPending=!1;let t=this.session.snapshot()?.userId;t&&(await this.flush(),await this.sendIdentify(this.api,t,e))}async sendIdentify(e,t,s){try{await e.identify({body:{distinct_id:t,anonymous_id:this.anonymousId(),traits:s,timestamp:this.now(),sent_at:this.now()}})}catch{}}reset(){this.memoryAnon=void 0,this.memorySession=void 0;try{I()?.removeItem(this.anonKey),I()?.removeItem(this.sessionKey)}catch{}}async flush(e=!1){this.timer&&clearTimeout(this.timer),this.timer=void 0;let t=e?this.closingApi:this.api,s=this.now(),i=this.session.snapshot()?.userId;for(this.identifyPending&&i&&(this.identifyPending=!1,await this.sendIdentify(t,i));this.events.length>0;){let r=this.take(this.events,e);try{await t.batch({body:{events:r.map(a=>({...a,sent_at:s}))}})}catch{}}for(;this.samples.length>0;){let r=this.take(this.samples,e);try{await t.sendPerf({body:{items:r}})}catch{}}}start(e={}){this.stopAuto?.(),this.appVersion=e.appVersion;let t=globalThis;if(typeof t.addEventListener!="function"||typeof globalThis.document>"u")return()=>{};let s=[];e.pageViews!==!1&&s.push(this.watchPages(t)),e.webVitals!==!1&&s.push(me((a,o)=>this.sample("web_vital",a,o))),e.network!==!1&&s.push(this.watchFetch(t));let i=()=>{document.visibilityState==="hidden"&&this.flush(!0)},r=()=>{this.flush(!0)};return document.addEventListener("visibilitychange",i),t.addEventListener("pagehide",r),s.push(()=>{document.removeEventListener("visibilitychange",i),t.removeEventListener("pagehide",r)}),this.stopAuto=()=>{for(let a of s.splice(0))a();this.stopAuto=void 0},this.stopAuto}hold(e){this.events.length>=X&&this.events.shift(),this.events.push(e),this.soon()}sample(e,t,s,i={}){this.samples.length>=X&&this.samples.shift(),this.samples.push({row_id:P(),trace_type:e,name:t,value:Math.max(0,s),timestamp:this.now(),distinct_id:this.distinctId(),...i}),this.soon()}soon(){if(this.events.length+this.samples.length>=this.flushAt){this.flush();return}this.timer||(this.timer=setTimeout(()=>{this.flush()},this.flushMs),this.timer.unref?.())}take(e,t){let s=e.splice(0,de);if(!t)return s;for(;s.length>1&&JSON.stringify(s).length>fe;)e.unshift(s.pop());return s}distinctId(){return this.session.snapshot()?.userId??this.anonymousId()}anonymousId(){let e=I();try{let t=e?.getItem(this.anonKey);if(t)return t;let s=`anon_${P()}`;if(e?.setItem(this.anonKey,s),e?.getItem(this.anonKey)===s)return s}catch{}return this.memoryAnon??=`anon_${P()}`,this.memoryAnon}sessionId(e){let t=I(),s=this.memorySession;try{let r=t?.getItem(this.sessionKey);r&&(s=JSON.parse(r))}catch{}let i=s&&e-s.last<he?{id:s.id,last:e}:{id:`ses_${P()}`,last:e};this.memorySession=i;try{t?.setItem(this.sessionKey,JSON.stringify(i))}catch{}return i.id}watchPages(e){let t="",s=()=>{let o=`${e.location.origin}${e.location.pathname}`;o!==t&&(t=o,setTimeout(()=>this.page({url:o}),0))},i=e.history,r=i.pushState.bind(i),a=i.replaceState.bind(i);return i.pushState=(...o)=>{r(...o),s()},i.replaceState=(...o)=>{a(...o),s()},e.addEventListener("popstate",s),s(),()=>{i.pushState=r,i.replaceState=a,e.removeEventListener("popstate",s)}}watchFetch(e){let t=e.fetch;if(typeof t!="function")return()=>{};let s=async(i,r)=>{let a=performance.now(),o=i instanceof Request?i:void 0,c=(r?.method??o?.method??"GET").toUpperCase(),l;try{l=new URL(o?.url??String(i),e.location.href)}catch{l=void 0}let h=!!l&&l.pathname.startsWith("/analytics/")||ye(r?.headers??o?.headers);try{let d=await t(i,r);return l&&!h&&this.sample("network",`${c} ${l.origin}${l.pathname}`,performance.now()-a,{attrs:{status:String(d.status)},...d.headers.get("x-request-id")?{request_id:d.headers.get("x-request-id")}:{}}),d}catch(d){throw l&&!h&&this.sample("network",`${c} ${l.origin}${l.pathname}`,performance.now()-a,{attrs:{status:"0"}}),d}};return e.fetch=s,()=>{e.fetch===s&&(e.fetch=t)}}},pe=n=>n.entryType==="layout-shift"&&"value"in n&&"hadRecentInput"in n,ge=n=>n.entryType==="event"||n.entryType==="first-input";function E(n,e){if(!(typeof PerformanceObserver>"u"))try{let t=new PerformanceObserver(s=>e(s.getEntries()));return t.observe({type:n,buffered:!0}),t}catch{return}}function me(n){if(typeof document>"u"||typeof performance>"u"||typeof performance.getEntriesByType!="function")return()=>{};let e=0,t=0,s=0,i=[E("largest-contentful-paint",l=>{for(let h of l)e=Math.max(e,h.startTime)}),E("layout-shift",l=>{for(let h of l)pe(h)&&!h.hadRecentInput&&(t+=h.value)}),E("event",l=>{for(let h of l)ge(h)&&(s=Math.max(s,h.duration))}),E("paint",l=>{for(let h of l)h.name==="first-contentful-paint"&&n("FCP",h.startTime)})],r=performance.getEntriesByType("navigation")[0];r&&r.responseStart>0&&n("TTFB",r.responseStart);let a=!1,o=()=>{a||(a=!0,e>0&&n("LCP",e),n("CLS",t),s>0&&n("INP",s))},c=()=>{document.visibilityState==="hidden"&&o()};return document.addEventListener("visibilitychange",c),()=>{o(),document.removeEventListener("visibilitychange",c);for(let l of i)l?.disconnect()}}function ye(n){if(!n)return!1;try{return new Headers(n).has("next-router-prefetch")}catch{return!1}}function ve(n){if(!n)return"";try{let e=new URL(n);return`${e.origin}${e.pathname}`}catch{return n.split(/[?#]/,1)[0]??""}}var C=class{api;session;socket;ref;fetch;appVersion;app;listeners=new Set;watch;following;last;constructor(e,t,s,i,r,a,o){this.api=F.client(e),this.session=t,this.socket=s,this.ref=i,this.fetch=r,this.appVersion=a,this.app=o}async me(){let e=this.session.snapshot()?.userId,t=(await this.api.getMyCustomerInfo()).data;return this.watch&&this.watch.userId===e&&this.offer(this.watch,t),t}async offerings(e="web"){return(await this.api.getOfferings({query:{channel:e}})).data}async paywall(e,t={}){return J(this.api,this.ref,e,s=>this.checkout(s),{signal:t.signal,fetch:this.fetch,attributes:t.attributes,locale:t.locale,appVersion:this.appVersion,app:this.app})}async checkout(e){let t={product:e.product,plan:e.plan,success_url:e.successUrl,cancel_url:e.cancelUrl};return(await this.api.createCheckout({body:t})).data.url}async portal(e){return(await this.api.createPortalSession({body:{return_url:e}})).data.url}async mergeGrant(){return(await this.api.createMergeGrant()).data}async merge(e){let t=this.session.snapshot()?.userId,s=(await this.api.mergeGuest({body:{grant:typeof e=="string"?e:e.grant}})).data;return this.watch&&this.watch.userId===t&&this.offer(this.watch,s),s}onCustomerInfo(e){if(this.listeners.add(e),this.listeners.size===1)this.start();else if(this.last!==void 0){let t=this.last;queueMicrotask(()=>this.listeners.has(e)&&Y(e,t))}return()=>{this.listeners.delete(e)&&this.listeners.size===0&&this.stop()}}start(){this.following=this.session.onChange((e,t)=>{(e==="SIGNED_IN"||e==="SIGNED_OUT"||e==="SESSION_EXPIRED")&&this.follow(t)}),this.session.session().then(e=>{this.following&&!this.watch&&this.last===void 0&&this.follow(e)})}stop(){this.following?.(),this.following=void 0,this.unfollow(),this.last=void 0}follow(e){if(this.unfollow(),!e){this.tell(null);return}let t=this.socket.channel(`purchases:${this.ref}:${e.userId}`),s={userId:e.userId,channel:t,off:()=>{},revision:-1,reading:!1,wanted:Number.NEGATIVE_INFINITY},i=[t.on("broadcast",r=>{r.event==="changed"&&this.changed(s,L(r.payload))}),t.on("state_snapshot",r=>this.held(s,L(z(r.entries)))),t.on("state_diff",r=>this.held(s,L(z(r.set))))];s.off=()=>i.forEach(r=>r()),this.watch=s,t.join().catch(()=>{}),this.read(s)}unfollow(){let e=this.watch;e&&(this.watch=void 0,e.off(),e.channel.leave())}changed(e,t){this.watch!==e||t!==void 0&&t<=e.revision||(e.reading?e.wanted=Math.max(e.wanted,t??Number.POSITIVE_INFINITY):this.read(e))}held(e,t){t!==void 0&&this.changed(e,t)}async read(e){e.reading=!0;try{for(;;){e.wanted=Number.NEGATIVE_INFINITY;try{let t=(await this.api.getMyCustomerInfo()).data;if(this.watch!==e)return;this.offer(e,t)}catch{}if(this.watch!==e||e.wanted<=e.revision)return}}finally{e.reading=!1}}offer(e,t){this.watch!==e||t.revision<=e.revision||(e.revision=t.revision,this.tell(t))}tell(e){if(!(this.last===null&&e===null)){this.last=e;for(let t of[...this.listeners])Y(t,e)}}};function Y(n,e){try{n(e)}catch{}}function z(n){let e=typeof n=="object"&&n!==null?n.revision:void 0;return typeof e=="object"&&e!==null?e.v:void 0}function L(n){let e=typeof n=="object"&&n!==null?n.revision:void 0;return typeof e=="number"&&Number.isFinite(e)?e:void 0}var A=class{api;open;session;credentials;mfa;passkey;magicLink;phone;password;email;sessions;constructor(e,t,s,i){this.api=w.client(e),this.open=w.client(t),this.session=s,this.credentials=i;let r=this.api,a=this.open;this.mfa={challenge:async(o,c,l)=>this.signedIn((await a.mfaChallenge({body:{mfa_token:o,type:c,code:l}})).data),recovery:async(o,c)=>this.signedIn((await a.mfaRecovery({body:{mfa_token:o,code:c}})).data),sendSmsCode:async o=>{await a.mfaSmsChallenge({body:{mfa_token:o}})},sendEmailCode:async o=>{await a.mfaEmailChallenge({body:{mfa_token:o}})},enrollTotp:async()=>{let o=(await r.mfaEnroll({body:{type:"totp"}})).data;return{enrollmentId:o.enrollment_id,secret:o.secret,otpUrl:o.otp_url,qrCode:o.qr_code,recoveryCodes:o.recovery_codes}},verifyTotp:async o=>{await r.mfaVerifyEnrollment({body:{code:o}})},enrollSms:async o=>(await r.mfaSmsEnroll({body:{phone:o}})).data,verifySms:async o=>{await r.mfaSmsVerifyEnrollment({body:{code:o}})},enrollEmail:async()=>{await r.mfaEmailEnroll()},factors:async()=>(await r.mfaListFactors()).data,removeFactor:async(o,c)=>{await r.mfaRemoveFactor({path:{id:o},body:{current_password:c}})},regenerateRecoveryCodes:async()=>(await r.mfaRegenerateRecoveryCodes()).data},this.passkey={register:async o=>{let c=(await r.webauthnRegisterBegin({body:{name:o}})).data,l=await this.authenticator().create({publicKey:Z(c.options.publicKey)});return(await r.webauthnRegisterFinish({body:ee(l)})).data},signIn:async(o={})=>{let c=(await a.webauthnLoginBegin({body:o.userId?{user_id:o.userId}:{}})).data,l=await this.authenticator().get({publicKey:Q(c.options.publicKey)}),h=await a.webauthnLoginFinish({query:o.userId?{user_id:o.userId}:void 0,body:te(l)});return this.signedIn(h.data)},signUp:async(o,c)=>{let l=(await a.webauthnSignupBegin({body:{identifier:o,user_name:c}})).data,h=await this.authenticator().create({publicKey:Z(l.options.publicKey)});await a.webauthnSignupFinish({query:{user_id:l.user_id},body:ee(h)});let d=(await a.webauthnLoginBegin({body:{user_id:l.user_id}})).data,m=await this.authenticator().get({publicKey:Q(d.options.publicKey)});return this.signedIn((await a.webauthnLoginFinish({query:{user_id:l.user_id},body:te(m)})).data)},list:async()=>(await r.webauthnListCredentials()).data,remove:async o=>{await r.webauthnDeleteCredential({path:{id:o}})}},this.magicLink={send:async(o,c={})=>{await a.magicLinkRequest({body:{email:o,...c.redirectTo?{redirect_to:c.redirectTo}:{}}})},verify:async o=>this.signedIn((await a.magicLinkVerify({body:{token:o}})).data)},this.phone={sendCode:async o=>(await a.requestPhoneOtp({body:{phone:o,channel:"sms"}})).data,verifyCode:async(o,c)=>this.signInResult((await a.verifyPhoneOtp({body:{phone:o,token:c}})).data)},this.password={requestReset:async(o,c={})=>{await a.passwordResetRequest({body:{email:o,...c.redirectTo?{redirect_to:c.redirectTo}:{}}})},confirmReset:async(o,c)=>{await a.passwordResetConfirm({body:{token:o,new_password:c}})},change:async o=>(await r.passwordChange({body:o})).data,set:async o=>(await r.setPassword({body:o})).data},this.email={verify:async o=>{await a.verifyEmail({body:o})},resendVerification:async o=>(await a.resendVerification({body:{email:o}})).data},this.sessions={list:async()=>(await r.listSessions()).data,revoke:async o=>{await r.revokeSession({path:{id:o}})},revokeAll:async()=>{await r.revokeAllSessions()}}}onAuthStateChange(e){return this.session.onChange(e)}currentSession(){return this.session.session()}get sessionEndReason(){return this.session.endReason}async signUp(e){let t=(await this.open.signup({body:e})).data;return t.access_token&&t.refresh_token&&t.expires_in!==void 0&&await this.session.set({access_token:t.access_token,refresh_token:t.refresh_token,expires_in:t.expires_in},"SIGNED_IN",t.user),t}async signIn(e,t){return this.signInResult((await this.open.login({body:{email:e,password:t}})).data)}async signOut(){try{await this.session.session()&&await this.api.logout()}finally{await this.session.clear("SIGNED_OUT")}}async getUser(){let e=this.session.snapshot(),t=(await this.api.getMe()).data;return await this.session.setUser(t,e),t}async refreshSession(){return this.session.refresh()}async deleteAccount(e){await this.api.deleteAccount(e===void 0?void 0:{body:{password:e}}),await this.session.clear("SIGNED_OUT")}async signInResult(e){return"mfa_required"in e&&e.mfa_required?{mfaRequired:{mfaToken:e.mfa_token,factors:e.factors}}:{user:await this.signedIn(e)}}async setSession(e){return this.signedIn(e)}async signedIn(e){let t=await this.session.set({access_token:e.access_token,refresh_token:e.refresh_token,expires_in:e.expires_in},"SIGNED_IN",e.user);if(e.user)return e.user;let s=(await this.api.verifyTokenUser()).data;return await this.session.setUser(s,t),s}authenticator(){if(!this.credentials)throw new Error("passkeys need navigator.credentials (or createClient({ webauthn }))");return this.credentials}},x=n=>{let e=atob(n.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(n.length/4)*4,"=")),t=new Uint8Array(e.length);for(let s=0;s<e.length;s++)t[s]=e.charCodeAt(s);return t.buffer},g=n=>{if(!n)return;let e=n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength),t="";for(let s of e)t+=String.fromCharCode(s);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},se=n=>Array.isArray(n)?n.map(e=>({...e,id:x(String(e.id))})):void 0;function Z(n){let e=n.user;return{...n,challenge:x(String(n.challenge)),user:{...e,id:x(String(e.id))},excludeCredentials:se(n.excludeCredentials)}}function Q(n){return{...n,challenge:x(String(n.challenge)),allowCredentials:se(n.allowCredentials)}}function ee(n){let e=n,t=e.response;return{id:e.id,rawId:g(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:g(t.clientDataJSON),attestationObject:g(t.attestationObject),transports:t.getTransports?.()}}}function te(n){let e=n,t=e.response;return{id:e.id,rawId:g(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:g(t.clientDataJSON),authenticatorData:g(t.authenticatorData),signature:g(t.signature),userHandle:g(t.userHandle)}}}var we=/^pb_[a-z0-9]+_s/,be=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Se=new Set(["invalid_token","token_expired","session_expired","session_revoked","missing_token"]),ke=new Set(["invalid_token","token_reuse","token_expired","session_revoked","session_expired","session_device_changed"]);function Te(n){return n.status===400&&n.code==="invalid_request"}function Be(n){if(we.test(n.publishableKey)||"secretKey"in n)throw new TypeError("a secret key never goes into a client app: palbase/web takes the publishable key (pb_<ref>_c\u2026); servers use palbase/server");let e=/^pb_([a-z0-9]+)_c/.exec(n.publishableKey)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");if(n.appId!==void 0&&!be.test(n.appId))throw new TypeError("appId is the registered app's id, a UUID (settings.appId of palbase apps:sync), not its slug");let t=ne(n.language),s=(u,f)=>{let p=n.fetch??globalThis.fetch;if(t===void 0)return p(u,f);let v=new Headers(f?.headers);return v.has("accept-language")||v.set("accept-language",t),p(u,{...f,headers:v})},i=new URL(n.url).origin,r=n.storage??(Pe()?W(`palbase.session.${i}`):V()),a=n.retry??$,o=S(b({baseUrl:n.url,credentials:{publishableKey:n.publishableKey},fetch:s}),a),c=w.client(o),l=new k(r,async u=>(await c.refreshToken({body:{refresh_token:u}})).data,u=>u instanceof O&&(u.status===401&&ke.has(u.code)||Te(u)),{lockName:`palbase.session.refresh.${i}`,refresh:n.refresh}),h=b({baseUrl:n.url,credentials:{publishableKey:n.publishableKey,accessToken:()=>l.accessToken()},fetch:s,xmlHttpRequest:n.xmlHttpRequest??(n.fetch===void 0?globalThis.XMLHttpRequest:void 0)}),d=S(U(h,l),a),m=new R({baseUrl:n.url,publishableKey:n.publishableKey,accessToken:()=>l.accessToken(),webSocket:n.webSocket});l.onChange(u=>{u==="SIGNED_OUT"||u==="SESSION_EXPIRED"||u==="SIGNED_IN"?m.disconnect():u==="TOKEN_REFRESHED"&&m.tokenChanged()});let j=new _(U(h,l),l,i);n.analytics&&j.start(n.analytics===!0?{}:n.analytics);let q=new Map,ie=u=>{let f=new URL(u).origin,p=q.get(f);return p||(p=S(U(b({baseUrl:f,credentials:{accessToken:()=>l.accessToken()},fetch:s}),l),a),q.set(f,p)),p},D=B(d),K=Object.assign(Object.create(G),{auth:new A(d,o,l,n.webauthn??globalThis.navigator?.credentials),socket:m,transport:d,analytics:j,purchases:new C(d,l,m,e,s,n.appVersion,n.appId),setLanguage(u){t=ne(u??void 0)},chatToolCall:(u,f,p={})=>D.toolCall(u,f,p.signal),chatWorkspaceFile:(u,f,p,v={})=>D.workspaceFile(u,f,p,v.signal)});return H(K,i,ie,d,m,()=>l.snapshot()?.userId),K}var Re=/^[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*$/;function ne(n){if(n===void 0)return;let e=typeof n=="string"?[n]:[...n];if(e.length!==0){for(let t of e)if(!Re.test(t))throw new TypeError(`language ${JSON.stringify(t)} is a BCP 47 tag ("tr", "pt-BR")`);return e.map((t,s)=>s===0?t:`${t};q=${Math.max(.1,1-s/10).toFixed(1)}`).join(", ")}}function Pe(){try{return typeof globalThis.localStorage<"u"}catch{return!1}}function U(n,e){return{async send(t){let s=await e.session();try{return await n.send(t)}catch(i){let r=t.auth.some(a=>a.includes("userJWT"));if(!(i instanceof O)||i.status!==401||!Se.has(i.code)||!r||!s)throw i;try{e.snapshot()?.refreshToken===s.refreshToken&&await e.refresh()}catch{throw i}if(e.snapshot()?.userId!==s.userId)throw i;return n.send(t)}}}}export{y as a,V as b,W as c,N as d,R as e,_ as f,C as g,Be as h};
|
package/dist/chunks/FZ3MQOVA.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*! palbase 0.8.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
-
import"./JSJVV43D.js";import{realpathSync as Ve}from"node:fs";import{resolve as ue}from"node:path";import wt from"typescript";import{existsSync as Se,readFileSync as Ue}from"node:fs";import{dirname as de,join as pe,relative as qe,resolve as ye,sep as ee}from"node:path";var h=class extends Error{constructor(t){super(t),this.name="ContractAnalysisError"}},W=new Set(["palbase/backend","@palbase/backend","palgres"]),Je=new Set(["Get","Post","Put","Patch","Delete","Query","Upload"]);function Te(e){if(typeof e.createProgram!="function"||typeof e.getDecorators!="function"||typeof e.readConfigFile!="function")throw new h(`the contract is read with TypeScript's compiler API, and the TypeScript given (v${e.version??"unknown"}) has none \u2014 TypeScript 7 is the Go-native compiler, whose package exposes version metadata only`)}function he(e,t){Te(e);let n=pe(t,"tsconfig.json"),r={target:e.ScriptTarget.ES2022,module:e.ModuleKind.ESNext,moduleResolution:e.ModuleResolutionKind.Bundler,experimentalDecorators:!0,allowImportingTsExtensions:!0},s=[];if(Se(n)){let i=e.readConfigFile(n,e.sys.readFile);if(i.error)throw new h(`${n}: ${e.flattenDiagnosticMessageText(i.error.messageText,`
|
|
3
|
-
`)}`);let o=e.parseJsonConfigFileContent(i.config,e.sys,t);r=o.options,s=o.fileNames.filter(a=>/\.d\.[cm]?ts$/.test(a))}return{options:{...r,strictNullChecks:!0,noEmit:!0,skipLibCheck:!0},ambient:s}}function be(e,t,n,r,s){Te(e);let i=e.createProgram([...new Set(n)],r,s);return{ts:e,root:t,program:i,checker:i.getTypeChecker(),packages:new Map}}function $(e,t){let n=ye(t);return!n.includes(`${ee}node_modules${ee}`)&&!/\.d\.[cm]?ts$/.test(n)&&(n===e.root||n.startsWith(e.root+ee))}function v(e,t){return!!t&&$(e,t.getSourceFile().fileName)}function xe(e,t){let n=[],r=de(ye(t)),s=null;for(;;){let i=e.packages.get(r);if(i!==void 0){s=i;break}n.push(r);let o=pe(r,"package.json");if(Se(o)){try{let c=JSON.parse(Ue(o,"utf8")).name;s=typeof c=="string"?c:null}catch{s=null}break}let a=de(r);if(a===r)break;r=a}for(let i of n)e.packages.set(i,s);return s}function te(e,t){if($(e,t))return!1;let n=xe(e,t)??"";return n==="palbase"?/[\\/]types[\\/]backend[\\/]/.test(t):W.has(n)}function we(e,t){if($(e,t))return!1;let n=xe(e,t)??"";return W.has(n)||n==="palbase"||n.startsWith("@palbase/")}function O(e,t){let n=t.getSourceFile(),{line:r}=n.getLineAndCharacterOfPosition(t.getStart(n));return`${qe(e.root,n.fileName)}:${r+1}`}function T(e,t){for(;t;){if(e.isParenthesizedExpression(t)||e.isAsExpression(t)||e.isNonNullExpression(t)||e.isAwaitExpression(t)||e.isTypeAssertionExpression(t)||e.isSatisfiesExpression(t)){t=t.expression;continue}return t}return t}function G(e,t){if(t&&t.flags&e.ts.SymbolFlags.Alias){let n=e.checker.getAliasedSymbol(t);if(n&&n.declarations)return n}return t}function D(e,t){let n=G(e,e.checker.getSymbolAtLocation(t));return n&&(n.valueDeclaration||n.declarations&&n.declarations[0])||null}function me(e,t){let n=t;for(;n&&!e.isImportDeclaration(n)&&!e.isExportDeclaration(n);)n=n.parent;return n&&(e.isImportDeclaration(n)||e.isExportDeclaration(n))&&n.moduleSpecifier&&e.isStringLiteral(n.moduleSpecifier)?n.moduleSpecifier.text:null}function I(e,t){let n=e.ts;if(t=T(n,t),!t)return null;if(n.isPropertyAccessExpression(t)){let i=e.checker.getSymbolAtLocation(t.expression);return i&&(i.declarations||[]).some(a=>n.isNamespaceImport(a)&&W.has(me(n,a)??""))?t.name.text:null}if(!n.isIdentifier(t))return null;let r=e.checker.getSymbolAtLocation(t),s=new Set;for(;r&&!s.has(r);){s.add(r);for(let i of r.declarations||[]){if((n.isImportSpecifier(i)||n.isExportSpecifier(i))&&W.has(me(n,i)??""))return(i.propertyName||i.name).text;if(te(e,i.getSourceFile().fileName))return r.name}if(!(r.flags&n.SymbolFlags.Alias))return null;r=e.checker.getImmediateAliasedSymbol(r)}return null}function ge(e,t){let n=t.expression;return I(e,e.ts.isCallExpression(n)?n.expression:n)}function P(e,t){return t&&(e.isIdentifier(t)||e.isPrivateIdentifier(t)||e.isStringLiteral(t)||e.isNumericLiteral(t))?t.text:null}function Z(e,t){let n=e.ts,r=[];for(let s of t.statements){if(!n.isClassDeclaration(s)||!(n.getDecorators(s)||[]).some(o=>ge(e,o)==="Controller"))continue;if(!s.name)throw new h(`${O(e,s)} \u2014 a @Controller class needs a name \u2014 its routes' errors are bound to it by name`);let i=[];for(let o of s.members)if(!(!n.isMethodDeclaration(o)||!o.body)&&(n.getDecorators(o)||[]).some(a=>Je.has(ge(e,a)??""))){if(P(n,o.name)===null)throw new h(`${O(e,o)} \u2014 a route method needs a plain name; the contract reaches it by name`);i.push(o)}r.push({cls:s,routes:i})}return r}var Qe=new Set([2307,2580,2582,2583,2584,2591,2592,2593,2688,2867,2868,7016]);function We(e){let t=e.getSymbol();return t?.getName()==="Response"&&(t.declarations??[]).length>0&&(t.declarations??[]).every(n=>n.getSourceFile().isDeclarationFile)}function ke(e){let{ts:t,program:n,checker:r}=e,s=!1;return function(o,a){let c=o.getSourceFile().fileName,l=o.name.getText(o.getSourceFile()),u=f=>{throw new h(`${c} \u2014 ${a}.${l}: cannot infer a safe response contract (${f}). Use a named Zod return schema for this response; any/unknown is never emitted as a successful contract.`)};if(!s){let f=[];for(let S of n.getSourceFiles()){if(f.length>=5)break;S.isDeclarationFile||n.isSourceFileFromExternalLibrary(S)||/[\\/]node_modules[\\/]/.test(S.fileName)||we(e,S.fileName)||f.push(...n.getSemanticDiagnostics(S).filter(x=>x.category===t.DiagnosticCategory.Error&&!Qe.has(x.code)))}f.length&&u(t.formatDiagnostics(f.slice(0,5),{getCanonicalFileName:S=>S,getCurrentDirectory:()=>e.root,getNewLine:()=>`
|
|
4
|
-
`})),s=!0}let m=r.getSignatureFromDeclaration(o),g=m&&r.getAwaitedType(r.getReturnTypeOfSignature(m));if(!g)return u("unresolved return type");if(g.flags&(t.TypeFlags.Void|t.TypeFlags.Undefined))return{kind:"void"};if(We(g))return{kind:"raw"};let p=new Set,d=0;function C(f,S){if(++d>2e3||p.size>24)return u(`${S}: contract is too large; name its schema`);let x=f.flags,y=t.TypeFlags;if(x&(y.Any|y.Unknown|y.Never|y.TypeParameter))return u(`${S}: ${r.typeToString(f)}`);let fe=b=>{let w=r.getPropertiesOfType(b);if(!(b.flags&y.Object)||w.length!==1||w[0].name!=="__pg"||!(w[0].flags&t.SymbolFlags.Optional)||r.getIndexInfosOfType(b).length)return!1;let N=r.getTypeOfSymbolAtLocation(w[0],o);return(N.isUnion()?N.types:[N]).every(k=>k.flags&(y.StringLiteral|y.Undefined))};if(f.isIntersection()){let b=f.types.filter(w=>!fe(w));if(b.length===1&&b.length<f.types.length)return C(b[0],S)}if(fe(f))return u(`${S}: unknown PostgreSQL payload; name its response schema`);if(x&y.StringLiteral)return`z.literal(${JSON.stringify(f.value)})`;if(x&y.NumberLiteral)return`z.literal(${JSON.stringify(f.value)})`;if(x&y.BooleanLiteral)return`z.literal(${r.typeToString(f)==="true"})`;if(x&y.String)return"z.string()";if(x&y.TemplateLiteral){let b=f;if(b.types.length>8||!b.types.every(k=>k.flags&y.String))return u(`${S}: template literal requires an explicit schema`);let w=k=>k.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),N="^"+w(b.texts[0]);for(let k of b.texts.slice(1,-1))if(k){let Y=w(k);N+=`(?:(?!${Y})[\\s\\S])*${Y}`}return N+="[\\s\\S]*"+w(b.texts.at(-1))+"$(?![\\s\\S])",N.length>4096?u(`${S}: template pattern is too large`):`z.string().regex(new RegExp(${JSON.stringify(N)}))`}if(x&y.Number)return"z.number().finite()";if(x&y.Boolean)return"z.boolean()";if(x&y.Null)return"z.null()";if(x&y.Undefined)return"z.undefined()";if(p.has(f))return u(`${S}: recursive response`);p.add(f);try{if(f.isUnion()){if(f.types.length>32)return u(`${S}: union has more than 32 alternatives`);let A=f.types.some(M=>M.flags&y.Null),Q=f.types.some(M=>M.flags&y.Undefined),j=f.types.filter(M=>!(M.flags&(y.Null|y.Undefined)));return(j.length===0?A?"z.null()":"z.undefined()":j.length===1?C(j[0],S):`z.union([${j.map(M=>C(M,S)).join(",")}])`)+(A&&j.length?".nullable()":"")+(Q?".optional()":"")}if(r.isTupleType(f))return u(`${S}: tuple requires an explicit schema`);if(r.isArrayType(f)){let A=r.getTypeArguments(f)[0];return A.flags&y.Never?"z.array(z.string()).length(0)":`z.array(${C(A,`${S}[]`)})`}let b=f.isIntersection()&&f.types.every(A=>A.flags&y.Object);if(!(x&y.Object)&&!b||f.getCallSignatures().length||f.getConstructSignatures().length)return u(`${S}: non-JSON type ${r.typeToString(f)}`);let w=f.symbol?.declarations?.[0];if(w&&(t.isClassDeclaration(w)||t.isClassExpression(w)))return u(`${S}: class instance ${r.typeToString(f)}`);let N=r.getPropertiesOfType(f),k=r.getIndexInfosOfType(f);return k.length?k.length!==1||!(k[0].keyType.flags&y.String)||N.length?u(`${S}: mixed or non-string index signature`):`z.record(z.string(), ${C(k[0].type,`${S}.*`)})`:N.length?`z.object({${N.map(A=>{if(A.escapedName.toString().startsWith("__@"))return u(`${S}: symbol property`);let Q=A.getName(),j=C(r.getTypeOfSymbolAtLocation(A,o),`${S}.${Q}`);return`${JSON.stringify(Q)}:${j}${A.flags&t.SymbolFlags.Optional?".optional()":""}`}).join(",")}}).strict()`:u(`${S}: empty structural type`)}finally{p.delete(f)}}return{kind:"expression",expression:C(g,"return")}}}import{resolve as Ge}from"node:path";var ne=Symbol("not a named schema");function Ee(e,t,n,r){let{ts:s}=e,i=r.getSourceFile(),o=r.name.getText(i),a=d=>new h(`${i.fileName} \u2014 ${n}.${o}: ${d}`);function c(d){if(s.isTypeReferenceNode(d)&&d.typeName.getText(i)==="Promise"&&d.typeArguments&&d.typeArguments.length===1)return c(d.typeArguments[0]);if(d.kind===s.SyntaxKind.VoidKeyword||d.kind===s.SyntaxKind.UndefinedKeyword)return null;let C=s.isArrayTypeNode(d)?d.elementType:s.isTypeReferenceNode(d)&&d.typeName.getText(i)==="Array"&&d.typeArguments&&d.typeArguments.length===1?d.typeArguments[0]:void 0,f=l(C??d);return f===ne?f:{...f,isArray:C!==void 0}}function l(d){if(s.isTypeReferenceNode(d)&&!d.typeArguments)return{typeName:d.typeName.getText(i),node:d.typeName};if(s.isTypeReferenceNode(d)&&d.typeArguments&&d.typeArguments.length===1){let C=d.typeName.getText(i);if(/^(z\.)?(infer|output|input)$/.test(C)){let f=d.typeArguments[0];if(s.isTypeQueryNode(f))return{typeName:f.exprName.getText(i),node:f.exprName};if(s.isTypeReferenceNode(f)&&!f.typeArguments)return{typeName:f.typeName.getText(i),node:f.typeName}}}if(d.kind===s.SyntaxKind.VoidKeyword)throw a("void cannot appear inside an array/Promise here");return ne}let u=()=>t(r,n);if(!r.type)return u();let m=c(r.type);if(m===null)return{kind:"void"};if(m===ne)return u();let g=Ze(e,m.node);if(!g)return u();let p=He(e,g.symbol);return p?{kind:"schema",...p,array:m.isArray}:u()}function Ze(e,t){let{ts:n,checker:r}=e,s=r.getSymbolAtLocation(n.isQualifiedName(t)?t.right:t),i=G(e,s);if(!i||!(i.flags&n.SymbolFlags.Variable))return null;let o=i.valueDeclaration;return!o||!n.isVariableDeclaration(o)||!r.getTypeOfSymbolAtLocation(i,o).getProperty("~standard")?null:{symbol:i}}function He(e,t){let n=t.valueDeclaration?.getSourceFile();if(!n||n.isDeclarationFile)return null;let r=e.checker.getSymbolAtLocation(n);if(!r)return null;let s=e.checker.getExportsOfModule(r).filter(i=>G(e,i)===t).map(i=>i.name);return s.length===0?null:{file:Ge(n.fileName),exportName:s.includes(t.name)?t.name:s[0]}}var oe={BadRequest:{code:"bad_request",status:400,codeArg:null},Unauthorized:{code:"unauthorized",status:401,codeArg:1},Forbidden:{code:"forbidden",status:403,codeArg:1},NotFound:{code:"not_found",status:404,codeArg:1},Conflict:{code:"conflict",status:409,codeArg:1},UniqueViolation:{code:"unique_violation",status:409,codeArg:2},SerializationFailure:{code:"serialization_failure",status:409,codeArg:null},DeadlockDetected:{code:"deadlock_detected",status:409,codeArg:null},TooManyRequests:{code:"too_many_requests",status:429,codeArg:null}},Xe=new Set(["HttpError","PalError"]),Ye=[{member:"page",container:null,error:{name:"BadRequest",code:"bad_request",status:400}},{member:"$page",container:null,error:{name:"BadRequest",code:"bad_request",status:400}},{member:"update",container:/^RepositoryOf(\$\d+)?$/,error:{name:"NotFound",code:"not_found",status:404}},{member:"update",container:/^RepositoryOf(\$\d+)?$/,error:{name:"BadRequest",code:"bad_request",status:400}},{member:"updateScoped",container:/^RepositoryOf(\$\d+)?$/,error:{name:"BadRequest",code:"bad_request",status:400}}],et=new Map([["expectOne",0],["expectNone",0],["expectAtLeast",1],["expectAtMost",1]]);function Le(e){let t={...e,ids:new WeakMap,nextId:1,providerSet:null,concrete:null,summaries:new Map,warnings:new Map,statusOf:null,round:0,cyclic:!1,grew:!1};return{analyze(n){let r;for(;t.round+=1,t.cyclic=!1,t.grew=!1,r=xt(t,n),!(!t.cyclic||!t.grew););for(let s of t.summaries.values())s.final=!0;return r},warnings(){return[...t.warnings.values()]}}}function tt(e,t,n){throw new h(`${O(e,t)} \u2014 ${n}`)}function U(e,t){let n=e.ids.get(t);return n||(n=e.nextId++,e.ids.set(t,n)),n}function ce(e,t){return(e.getCombinedModifierFlags(t)&e.ModifierFlags.Static)!==0}function De(e,t){return(e.getCombinedModifierFlags(t)&e.ModifierFlags.Abstract)!==0}function F(e,t){return!!t&&(e.isClassDeclaration(t)||e.isClassExpression(t))}function Pe(e,t){if(!t)return null;if(F(e,t))return t;if((e.isVariableDeclaration(t)||e.isPropertyDeclaration(t)||e.isPropertyAssignment(t))&&t.initializer){let n=T(e,t.initializer);if(e.isClassExpression(n))return n}return null}function nt(e,t){if(t.name)return t.name.text;let n=t.parent;if(n&&(e.isVariableDeclaration(n)||e.isPropertyDeclaration(n)||e.isPropertyAssignment(n))&&n.name&&P(e,n.name))return P(e,n.name)??void 0}function _(e,t){let n=e.ts,r=T(n,t);if(!r)return null;let s=Pe(n,D(e,n.isPropertyAccessExpression(r)?r.name:r));return s&&v(e,s)?s:null}function q(e,t){let n=e.ts,r=(t.heritageClauses||[]).find(i=>i.token===n.SyntaxKind.ExtendsKeyword),s=r&&r.types[0]&&r.types[0].expression;return s?_(e,s):null}function $e(e,t,n){for(let r=q(e,t);r;r=q(e,r))if(r===n)return!0;return!1}function V(e,t,n,r){let s=e.ts;for(let i=t;i;i=q(e,i))for(let o of i.members)if(!(P(s,o.name)!==n||ce(s,o)!==r)){if((s.isMethodDeclaration(o)||s.isGetAccessorDeclaration(o))&&o.body)return{fn:o,owner:i};if(s.isPropertyDeclaration(o)&&o.initializer){let a=T(s,o.initializer);if(s.isArrowFunction(a)||s.isFunctionExpression(a))return{fn:a,owner:i}}}return null}function rt(e){let t=e.ts;if(e.providerSet)return e.providerSet;let n=new Set;for(let r of e.program.getSourceFiles())if($(e,r.fileName)){for(let s of r.statements)if(t.isClassDeclaration(s))for(let i of t.getDecorators(s)||[]){let o=i.expression;if(!t.isCallExpression(o)||I(e,o.expression)!=="Module")continue;let a=T(t,o.arguments[0]);if(!(!a||!t.isObjectLiteralExpression(a)))for(let c of a.properties){if(!t.isPropertyAssignment(c)||P(t,c.name)!=="providers")continue;let l=T(t,c.initializer);if(t.isArrayLiteralExpression(l))for(let u of l.elements){let m=_(e,u);m&&n.add(m)}}}}return e.providerSet=n,n}function Ce(e){let t=e.ts;if(e.concrete)return e.concrete;let n=[],r=s=>{F(t,s)&&!De(t,s)&&n.push(s),t.forEachChild(s,r)};for(let s of e.program.getSourceFiles())$(e,s.fileName)&&r(s);return e.concrete=n,n}function Fe(e,t){let n=t.name?e.checker.getSymbolAtLocation(t.name):t.symbol;return n?e.checker.getDeclaredTypeOfSymbol(n):null}function st(e,t){let n=t&&(t.getSymbol()||t.aliasSymbol),r=n&&(n.declarations||[]).find(s=>F(e.ts,s));return r&&F(e.ts,r)&&v(e,r)?r:null}function re(e,t){return t.type?e.checker.getTypeFromTypeNode(t.type):e.checker.getTypeAtLocation(t.name||t)}function J(e,t,n){let r=e.ts;if(!t)return;if(t.isUnion()){for(let l of t.types)J(e,l,n);return}let s=r.TypeFlags,i=s.StringLike|s.NumberLike|s.BigIntLike|s.BooleanLike|s.EnumLike|s.ESSymbolLike|s.VoidLike|s.Null;if(t.flags&(s.Any|s.Unknown|i))return;let o=t.getSymbol();if(!o)return;let a=(o.declarations||[]).find(l=>F(r,l));if(a&&F(r,a)){if(!v(e,a))return;De(r,a)||n.add(a);for(let l of Ce(e))$e(e,l,a)&&n.add(l);return}if((o.declarations||[]).some(l=>v(e,l)))for(let l of Ce(e)){let u=Fe(e,l);u&&e.checker.isTypeAssignableTo(u,t)&&n.add(l)}}function ae(e,t,n){let r=st(e,t);if(r){let s=rt(e);if(s.has(r)){n.add(r);return}let i=[...s].filter(o=>o!==r&&$e(e,o,r));if(i.length===1){n.add(i[0]);return}}J(e,t,n)}function it(e,t){for(let n=e;n;n=n.parent)if(n===t)return!0;return!1}function Oe(e,t){return t.fn&&it(e,t.fn)?t:{receiver:null,owner:null,fn:null}}function E(e,t,n,r=new Set){let s=e.ts,i=new Set;if(t=T(s,t),!t)return i;let o=`${U(e,t)}@${n.receiver?U(e,n.receiver):0}`;if(r.has(o))return i;r.add(o);let a=c=>{for(let l of c)i.add(l)};if(s.isNewExpression(t)){let c=_(e,t.expression);return c&&i.add(c),i}if(t.kind===s.SyntaxKind.ThisKeyword)return n.receiver&&i.add(n.receiver),i;if(s.isConditionalExpression(t))return a(E(e,t.whenTrue,n,r)),a(E(e,t.whenFalse,n,r)),i;if(s.isBinaryExpression(t)){let c=t.operatorToken.kind,l=s.SyntaxKind;if(c===l.QuestionQuestionToken||c===l.BarBarToken||c===l.AmpersandAmpersandToken)return a(E(e,t.left,n,r)),a(E(e,t.right,n,r)),i;if(c===l.CommaToken||c===l.EqualsToken)return a(E(e,t.right,n,r)),i}if(s.isCallExpression(t)){for(let c of X(e,t,n))for(let l of H(s,c.fn))a(E(e,l,c.ctx,r));if(i.size>0)return i}else if(s.isIdentifier(t)||s.isPropertyAccessExpression(t)){let c=D(e,s.isPropertyAccessExpression(t)?t.name:t);if(c&&s.isVariableDeclaration(c))return c.initializer&&a(E(e,c.initializer,Oe(c,n),r)),(!((s.getCombinedNodeFlags(c)&s.NodeFlags.Const)!==0)||!c.initializer)&&J(e,re(e,c),i),i;if(c&&s.isParameter(c)){let l=re(e,c);return c.parent&&s.isConstructorDeclaration(c.parent)?ae(e,l,i):J(e,l,i),i}if(c&&s.isPropertyDeclaration(c))return c.initializer?a(E(e,c.initializer,{receiver:c.parent,owner:c.parent,fn:null},r)):ae(e,re(e,c),i),i;if(c&&s.isGetAccessorDeclaration(c)&&c.body){for(let l of H(s,c))a(E(e,l,{receiver:c.parent,owner:c.parent,fn:c},r));if(i.size>0)return i}if(c&&s.isPropertyAssignment(c)&&(a(E(e,c.initializer,{receiver:null,owner:null,fn:null},r)),i.size>0))return i}return J(e,e.checker.getTypeAtLocation(t),i),i}function H(e,t){if(e.isArrowFunction(t)&&!e.isBlock(t.body))return[t.body];let n=e.isFunctionLike(t)?t.body:void 0;if(!n)return[];let r=[],s=i=>{if(e.isReturnStatement(i)){i.expression&&r.push(i.expression);return}e.isFunctionLike(i)||F(e,i)||e.forEachChild(i,s)};return e.forEachChild(n,s),r}function Re(e,t){return e.isPropertyAccessExpression(t)?t.name.text:e.isElementAccessExpression(t)&&e.isStringLiteralLike(t.argumentExpression)?t.argumentExpression.text:null}function ze(e,t){return e.isPropertyAccessExpression(t)?t.name:t.argumentExpression}function ot(e,t){let n=e.ts,r=Re(n,t);if(r===null)return[];let s=e.checker.getSymbolAtLocation(ze(n,t)),i=new Map;for(let o of s&&s.declarations||[]){if(!te(e,o.getSourceFile().fileName))continue;let a=o.parent,c=a&&a.name&&n.isIdentifier(a.name)?a.name.text:"";for(let l of Ye)l.member===r&&(!l.container||l.container.test(c))&&i.set(l.error.code,l.error)}return[...i.values()]}function at(e,t){let n=e.checker.getSymbolAtLocation(ze(e.ts,t));return n?(n.declarations||[]).some(r=>v(e,r)):!0}function je(e,t,n){let r=e.ts,s=[];for(let i=t;i;i=q(e,i)){for(let a of i.members){if(!r.isPropertyDeclaration(a)||!a.initializer||ce(r,a))continue;let c=T(r,a.initializer);r.isArrowFunction(c)||r.isFunctionExpression(c)||s.push({fn:a.initializer,ctx:{receiver:n,owner:i,fn:null}})}let o=i.members.find(a=>r.isConstructorDeclaration(a)&&!!a.body);if(o){s.push({fn:o,ctx:{receiver:n,owner:i,fn:o}});break}}return s}function X(e,t,n){let r=e.ts,s=T(r,t.expression);if(s.kind===r.SyntaxKind.SuperKeyword){let c=n.owner&&q(e,n.owner);return c?je(e,c,n.receiver):[]}let i=Re(r,s);if(i!==null){let c=s,l=T(r,c.expression);if(l.kind===r.SyntaxKind.SuperKeyword){let g=n.owner&&q(e,n.owner),p=g&&V(e,g,i,!1);return p?[{fn:p.fn,ctx:{receiver:n.receiver,owner:p.owner,fn:p.fn}}]:[]}let u=r.isIdentifier(l)||r.isPropertyAccessExpression(l)?_(e,l):null;if(u){let g=V(e,u,i,!0);return g?[{fn:g.fn,ctx:{receiver:null,owner:g.owner,fn:g.fn}}]:[]}if(!at(e,c))return[];let m=[];for(let g of E(e,l,n)){let p=V(e,g,i,!1);p&&m.push({fn:p.fn,ctx:{receiver:g,owner:p.owner,fn:p.fn}})}if(m.length>0)return m}let o=e.checker.getResolvedSignature(t),a=o&&o.declaration;if(a&&!r.isJSDocSignature(a)&&a.body&&v(e,a)){let c=a,l=c.parent&&F(r,c.parent)?c.parent:null,u=l&&!ce(r,c)?l:null;return[{fn:c,ctx:{receiver:u,owner:l,fn:c}}]}return[]}function Ne(e,t,n){let r=e.ts,s=T(r,t);if(!s)return[];if(r.isPropertyAccessExpression(s)){let i=D(e,s.name);if(!(i&&v(e,i)&&(r.isMethodDeclaration(i)||r.isPropertyDeclaration(i))))return[];let a=[];for(let c of E(e,s.expression,n)){let l=V(e,c,s.name.text,!1);l&&a.push({fn:l.fn,ctx:{receiver:c,owner:l.owner,fn:l.fn}})}return a}if(r.isIdentifier(s)){let i=D(e,s);if(!i||!v(e,i))return[];if(r.isFunctionDeclaration(i)&&i.body)return[{fn:i,ctx:{receiver:null,owner:null,fn:i}}];if(r.isVariableDeclaration(i)&&i.initializer){let o=T(r,i.initializer);if(r.isArrowFunction(o)||r.isFunctionExpression(o))return[{fn:o,ctx:{receiver:null,owner:null,fn:o}}]}}return[]}function K(e,t,n){let r=e.ts,s=T(r,t);if(!s)return null;if(n==="string"&&(r.isStringLiteral(s)||r.isNoSubstitutionTemplateLiteral(s)))return[s.text];if(n==="number"&&r.isNumericLiteral(s))return[Number(s.text)];let i=e.checker.getTypeAtLocation(s),o=[];for(let a of i.isUnion()?i.types:[i])if(n==="string"&&a.isStringLiteral())o.push(a.value);else if(n==="number"&&a.isNumberLiteral())o.push(a.value);else return null;return o.length>0?[...new Set(o)]:null}function Ae(e,t,n){let r=O(e,t);e.warnings.has(r)||e.warnings.set(r,`${r} \u2014 ${n}`)}function ct(e,t){let n=T(e,t);return!n||e.isIdentifier(n)&&n.text==="undefined"||n.kind===e.SyntaxKind.VoidExpression}function ve(e){let t=e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("");return/^[A-Za-z]/.test(t)?t:`E${t}`}function Me(e,t,n,r,s){if(Xe.has(t)){let c=K(e,n[0],"number"),l=K(e,n[1],"string");return!l||!c||c.length!==1?(Ae(e,r,`new ${t}(status, code, \u2026) with a code or status decided at runtime cannot be typed; clients receive it as their untyped case. To type it, give the code and status literal types (or declare it with defineError)`),[]):l.map(u=>({name:s&&l.length===1?s:ve(u),code:u,status:c[0]}))}let i=Object.prototype.hasOwnProperty.call(oe,t)?oe[t]:null;if(!i)return[];let o=[i.code];if(i.codeArg!==null&&n.length>i.codeArg&&!ct(e.ts,n[i.codeArg])&&(o=K(e,n[i.codeArg],"string"),!o))return Ae(e,r,`new ${t}(\u2026) with a code decided at runtime cannot be typed; clients receive it as their untyped case. To type it, give the code a literal type (or declare it with defineError)`),[];let a=o;return a.map(c=>({name:s&&a.length===1?s:c===i.code?t:ve(c),code:c,status:i.status}))}function le(e,t){let n=e.ts,r=t.initializer&&T(n,t.initializer);return r&&n.isCallExpression(r)&&I(e,r.expression)==="defineError"?r:null}function Ie(e,t,n){let r=K(e,n.arguments[0],"string"),s=K(e,n.arguments[1],"number"),i=r&&r.length===1?r[0]:null,o=s&&s.length===1?s[0]:null;return(i===null||o===null)&&tt(e,n,`defineError(...) for "${t.name.getText()}" declares a typed error, so its code and status must be known when the project is built (a literal, or a constant of literal type)`),{name:t.name.getText(),code:i,status:o}}function lt(e,t){let n=null,r=s=>{if(!(n||e.isFunctionLike(s))){if(e.isCallExpression(s)&&s.expression.kind===e.SyntaxKind.SuperKeyword){n=s;return}e.forEachChild(s,r)}};return t.body&&e.forEachChild(t.body,r),n}function Be(e,t,n,r){let s=e.ts,i=(t.heritageClauses||[]).find(d=>d.token===s.SyntaxKind.ExtendsKeyword),o=i&&i.types[0]&&i.types[0].expression;if(!o)return[];let a=t.members.find(d=>s.isConstructorDeclaration(d)&&!!d.body),c=n,l=r;if(a){let d=lt(s,a);if(!d)return[];c=d.arguments,l=d}let u=nt(s,t),m=I(e,o);if(m)return Me(e,m,c,l,u);let g=D(e,o);if(g&&s.isVariableDeclaration(g)){let d=le(e,g);return d?[{...Ie(e,g,d),name:u||g.name.getText()}]:[]}let p=_(e,o);if(p){let d=Be(e,p,c,l);return d.length===1&&u?[{...d[0],name:u}]:d}return[]}function ut(e,t){let n=e.ts,r=t.arguments||[],s=I(e,t.expression);if(s)return Me(e,s,r,t);let i=T(n,t.expression),o=D(e,n.isPropertyAccessExpression(i)?i.name:i);if(!o)return[];if(n.isVariableDeclaration(o)){let c=le(e,o);if(c)return[Ie(e,o,c)]}let a=Pe(n,o);return a&&v(e,a)?Be(e,a,r,t):[]}function z(e,t,n,r,s,i,o=new Set){let a=e.ts;if(t=T(a,t),!t)return;let c=`${U(e,t)}@${n.receiver?U(e,n.receiver):0}`;if(!o.has(c)){if(o.add(c),a.isNewExpression(t)){let l=O(e,t);R(e,r,s,i,ut(e,t).map(u=>({...u,site:l})));return}if(a.isConditionalExpression(t)){z(e,t.whenTrue,n,r,s,i,o),z(e,t.whenFalse,n,r,s,i,o);return}if(a.isBinaryExpression(t)){let l=a.SyntaxKind,u=t.operatorToken.kind;(u===l.QuestionQuestionToken||u===l.BarBarToken)&&z(e,t.left,n,r,s,i,o),z(e,t.right,n,r,s,i,o);return}if(a.isCallExpression(t)){for(let l of X(e,t,n))for(let u of H(a,l.fn))z(e,u,l.ctx,r,s,i,o);return}if(a.isIdentifier(t)||a.isPropertyAccessExpression(t)){let l=D(e,a.isPropertyAccessExpression(t)?t.name:t);if(l&&(a.isVariableDeclaration(l)||a.isPropertyDeclaration(l))&&l.initializer){let u=a.isVariableDeclaration(l)?Oe(l,n):n;z(e,l.initializer,u,r,s,i,o)}}}}function se(e,t){let n=e.ts;if(!n.isFunctionLike(t))return!1;if((n.getCombinedModifierFlags(t)&n.ModifierFlags.Async)!==0)return!0;let r=e.checker.getSignatureFromDeclaration(t);if(!r)return!1;let s=e.checker.getReturnTypeOfSignature(r),i=e.checker.getPromisedTypeOfPromise;return i?i.call(e.checker,s)!==void 0:e.checker.getAwaitedType(s)!==s}function ft(e,t,n){let r=null;for(let s=t.parent;s&&s!==n;s=s.parent)e.isFunctionLike(s)&&(e.getCombinedModifierFlags(s)&e.ModifierFlags.Async)!==0&&(r=s);return r}function dt(e,t,n){for(let r=t.parent;r&&r!==n;r=r.parent)if(e.isAwaitExpression(r)||e.isForOfStatement(r)&&r.awaitModifier)return!0;return!1}function mt(e,t,n,r){for(let s=t.scopes.length-1;s>=0;s--){let i=t.scopes[s],o=ft(e.ts,n,i.node),a=r||o!==null;if(i.kind==="try"){if(!a||dt(e.ts,o||n,i.node))return i.sink}else if(i.kind==="settle"){if(a)return null}else if(i.kind==="catch"&&a&&!i.rethrows)return null}return t.root}function gt(e){let t=e.ts;if(e.statusOf)return e.statusOf;let n=new Map;for(let[s,i]of Object.entries(oe))n.set(i.code,{status:i.status,site:`palbase/backend ${s}`});let r=s=>{if(t.isVariableDeclaration(s)&&t.isIdentifier(s.name)){let i=le(e,s),o=i&&K(e,i.arguments[0],"string"),a=i&&K(e,i.arguments[1],"number");o&&a&&o.length===1&&a.length===1&&!n.has(o[0])&&n.set(o[0],{status:a[0],site:O(e,s)})}t.forEachChild(s,r)};for(let s of e.program.getSourceFiles())$(e,s.fileName)&&r(s);return e.statusOf=n,n}function St(e,t){let n=gt(e),r=n.get(t.code);if(!r){n.set(t.code,{status:t.status,site:t.site});return}if(r.status!==t.status)throw new h(`"${t.code}" is thrown with status ${t.status} (${t.site}) but the code carries status ${r.status} (${r.site}) \u2014 a client matches an error by its code, so one code carries one status. Throw the code's own class, or give the error its own code`)}function R(e,t,n,r,s){for(let o of s)St(e,o);let i=mt(e,t,n,r);if(i)for(let o of s)i.has(o.code)||i.set(o.code,o)}function Ke(e,t,n){if(!n)return!1;let r=!1,s=o=>{let a=!1,c=l=>{a||(e.isIdentifier(l)&&l.text===n?a=!0:e.forEachChild(l,c))};return c(o),a},i=o=>{r||e.isFunctionLike(o)&&o!==t||(e.isThrowStatement(o)&&o.expression&&s(o.expression)?r=!0:e.forEachChild(o,i))};return i(t),r}function pt(e,t){let n=T(e,t);if(n&&(e.isArrowFunction(n)||e.isFunctionExpression(n))){let r=n.parameters[0];return r?e.isIdentifier(r.name)?e.isBlock(n.body)?Ke(e,n.body,r.name.text):!1:!0:!1}return!0}function yt(e,t,n){let r=e.ts;if(!r.isPropertyAccessExpression(t)||t.name.text!==n)return!1;let s=T(r,t.expression);if(!r.isIdentifier(s)||s.text!=="Promise")return!1;let i=D(e,s);return!i||!v(e,i)}function B(e,t,n){let r=e.ts,s=`${U(e,t)}@${n.receiver?U(e,n.receiver):0}`,i=e.summaries.get(s);if(i&&(i.final||i.round===e.round))return i.busy&&(e.cyclic=!0),i.errors;i={errors:i?new Map(i.errors):new Map,busy:!0,round:e.round,final:!1},e.summaries.set(s,i);let o=i.errors.size,a={root:i.errors,scopes:[]};if(r.isFunctionLike(t)){let c=t;for(let l of c.parameters||[])l.initializer&&L(e,l.initializer,n,a);c.body&&L(e,c.body,n,a)}else L(e,t,n,a);return i.busy=!1,i.errors.size!==o&&(e.grew=!0),i.errors}function ie(e,t){return{root:e.root,scopes:[...e.scopes,t]}}function L(e,t,n,r){let s=e.ts;if(s.isTryStatement(t)){let o=new Map;L(e,t.tryBlock,n,ie(r,{kind:"try",node:t.tryBlock,sink:o}));let a=t.catchClause;(!a||(a.variableDeclaration&&s.isIdentifier(a.variableDeclaration.name)?Ke(s,a.block,a.variableDeclaration.name.text):a.variableDeclaration))&&R(e,r,t,!1,[...o.values()]),a&&L(e,a.block,n,r),t.finallyBlock&&L(e,t.finallyBlock,n,r);return}if(s.isThrowStatement(t))t.expression&&z(e,t.expression,n,r,t,!1);else if(s.isCallExpression(t)){let o=T(s,t.expression);if(yt(e,o,"allSettled")){L(e,t.expression,n,r);let u=ie(r,{kind:"settle",node:t});for(let m of t.arguments)L(e,m,n,u);return}let a=s.isPropertyAccessExpression(o)?o.name.text==="catch"?0:o.name.text==="then"&&t.arguments.length>1?1:-1:-1;if(a>=0){let u=o,m=pt(s,t.arguments[a]);L(e,u.expression,n,ie(r,{kind:"catch",node:u.expression,rethrows:m}));for(let g of t.arguments)L(e,g,n,r);return}let c=s.isPropertyAccessExpression(o)?et.get(o.name.text):void 0;c!==void 0&&t.arguments[c]&&z(e,t.arguments[c],n,r,t,!0);let l=ot(e,o);if(l.length>0){let u=O(e,t);R(e,r,t,!0,l.map(m=>({...m,site:u})))}for(let u of X(e,t,n))R(e,r,t,se(e,u.fn),[...B(e,u.fn,u.ctx).values()]);for(let u of t.arguments)for(let m of Ne(e,u,n))R(e,r,u,se(e,m.fn),[...B(e,m.fn,m.ctx).values()])}else if(s.isNewExpression(t)){let o=_(e,t.expression);if(o)for(let a of je(e,o,o))R(e,r,t,!1,[...B(e,a.fn,a.ctx).values()]);for(let a of t.arguments||[])for(let c of Ne(e,a,n))R(e,r,a,se(e,c.fn),[...B(e,c.fn,c.ctx).values()])}else if(s.isPropertyAccessExpression(t)&&!(t.parent&&s.isCallExpression(t.parent)&&t.parent.expression===t)){let o=D(e,t.name);if(o&&s.isGetAccessorDeclaration(o)&&o.body&&v(e,o))for(let a of E(e,t.expression,n)){let c=V(e,a,t.name.text,!1);c&&R(e,r,t,!1,[...B(e,c.fn,{receiver:a,owner:c.owner,fn:c.fn}).values()])}}if(F(s,t))return;let i=s.isFunctionExpression(t)||s.isFunctionDeclaration(t)?{receiver:null,owner:null,fn:t}:n;s.forEachChild(t,o=>L(e,o,i,r))}function _e(e,t,n){let r=e.ts;if(n.has(t))return[];if(n.add(t),I(e,t.expression)==="Resolve")return[t];let s=[];for(let i of X(e,t,{receiver:null,owner:null,fn:null}))for(let o of H(r,i.fn)){let a=T(r,o);r.isCallExpression(a)&&s.push(..._e(e,a,n))}return s}function Tt(e,t){let n=e.ts,r=[];for(let s of t.parameters)for(let i of n.getDecorators(s)||[]){let o=T(n,i.expression);if(n.isCallExpression(o))for(let a of _e(e,o,new Set)){let c=_(e,a.arguments[0]);if(!c)continue;let l=new Set;ae(e,Fe(e,c),l);for(let u of l){let m=V(e,u,"resolve",!1);m&&r.push({fn:m.fn,ctx:{receiver:u,owner:m.owner,fn:m.fn}})}}}return r}function ht(e){return e.charAt(0).toLowerCase()+e.slice(1)}function bt(e,t,n){let r=new Map;for(let i of Tt(e,n))for(let o of B(e,i.fn,i.ctx).values())r.has(o.code)||r.set(o.code,o);for(let i of B(e,n,{receiver:t,owner:t,fn:n}).values())r.has(i.code)||r.set(i.code,i);let s=new Map;for(let i of r.values()){let o=ht(i.name),a=s.get(o);if(a)throw new h(`${t.name.text}.${P(e.ts,n.name)} can throw two errors named "${i.name}" \u2014 "${a.code}" (${a.site}) and "${i.code}" (${i.site}). Every client names an error case after it; give one of them its own defineError`);s.set(o,i)}return[...r.values()].map(({name:i,code:o,status:a})=>({name:i,code:o,status:a}))}function xt(e,t){let n=[];for(let{cls:r,routes:s}of Z(e,t)){let i={};for(let o of s)i[P(e.ts,o.name)]=bt(e,r,o);n.push({className:r.name.text,ops:i})}return n}function _t(e,t,n={}){let r=n.typescript??wt,s=Ve(ue(e)),{options:i,ambient:o}=he(r,s);return kt(be(r,s,[Ve(ue(t)),...o],i))}function kt(e){let t=e.ts,n=ke(e),r=Le(e),s=[],i=e.program.getSourceFiles().filter(a=>$(e,a.fileName)).sort((a,c)=>a.fileName<c.fileName?-1:a.fileName>c.fileName?1:0),o=[];for(let a of i){let c=Z(e,a);if(c.length===0)continue;let l=new Map;for(let{cls:u,routes:m}of c)for(let g of m)try{l.set(`${u.name.text}.${P(t,g.name)}`,Ee(e,n,u.name.text,g))}catch(p){if(!(p instanceof h))throw p;o.push(p.message)}if(!(o.length>0))for(let{className:u,ops:m}of r.analyze(a))for(let[g,p]of Object.entries(m))s.push({file:ue(a.fileName),className:u,method:g,returns:l.get(`${u}.${g}`),throws:p})}if(o.length===1)throw new h(o[0]);if(o.length>1)throw new h(`${o.length} routes have no contract:
|
|
5
|
-
${o.map(a=>`- ${a}`).join(`
|
|
6
|
-
`)}`);return{routes:s,warnings:r.warnings()}}export{h as ContractAnalysisError,_t as analyzeProject,kt as analyzeRoutes};
|