palbase 0.18.4 → 0.18.6

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.
Files changed (54) hide show
  1. package/dist/ai/index.js +2 -2
  2. package/dist/backend/engine.js +2 -2
  3. package/dist/backend/env.js +1 -1
  4. package/dist/backend/index.js +3 -3
  5. package/dist/backend/stack.js +1 -1
  6. package/dist/backend/test.js +2 -2
  7. package/dist/chunks/{N5WYA3DM.js → 4HYASQT5.js} +2 -2
  8. package/dist/chunks/{HKOGKWNU.js → 5N36M3Y3.js} +3 -3
  9. package/dist/chunks/{NEBALOPJ.js → 6HESVOSN.js} +1 -1
  10. package/dist/chunks/6IHNI2FC.js +21 -0
  11. package/dist/chunks/{KPTP2RTE.js → 6JA355QW.js} +1 -1
  12. package/dist/chunks/{RKPLX5YV.js → 7HE22VDH.js} +1 -1
  13. package/dist/chunks/{SSL3F7OB.js → ARDQJVIP.js} +2 -2
  14. package/dist/chunks/{GLPFMTZP.js → BDD3FVHP.js} +2 -2
  15. package/dist/chunks/{6RKQ5ANL.js → C53PUTQR.js} +2 -2
  16. package/dist/chunks/{6CJHLHPT.js → E4CPOSFA.js} +2 -2
  17. package/dist/chunks/IO3G5VIC.js +2 -0
  18. package/dist/chunks/{GF42QGWO.js → L4SDE4IC.js} +2 -2
  19. package/dist/chunks/{MAYJWEPM.js → NIDBDL7O.js} +1 -1
  20. package/dist/chunks/{CHDD73OG.js → OGP5DLL6.js} +2 -2
  21. package/dist/chunks/{XE6LFBDN.js → OL33SRTB.js} +2 -2
  22. package/dist/chunks/{7CTORXHD.js → Q2O72MGS.js} +1 -1
  23. package/dist/chunks/{W65B2VZ3.js → RGZZCQMZ.js} +2 -2
  24. package/dist/chunks/{V4TFN353.js → RHLHSALC.js} +2 -2
  25. package/dist/chunks/{VUXQEYPQ.js → RUE6N2T6.js} +2 -2
  26. package/dist/chunks/{PIWNLITG.js → S76H65KW.js} +2 -2
  27. package/dist/chunks/{KMA7REYL.js → U4R3KQT6.js} +1 -1
  28. package/dist/chunks/{Q33BWD44.js → U6UXSVEZ.js} +2 -2
  29. package/dist/chunks/{5BTTH7AT.js → Y76SPW2M.js} +1 -1
  30. package/dist/cli.js +53 -53
  31. package/dist/refuse/ai.js +1 -1
  32. package/dist/refuse/backend.js +1 -1
  33. package/dist/refuse/server.js +1 -1
  34. package/dist/server/index.js +2 -2
  35. package/dist/server/testing.js +2 -2
  36. package/dist/web/index.js +2 -2
  37. package/dist/web/message.js +2 -2
  38. package/dist/web/palbe.js +2 -2
  39. package/dist/web/paywall.js +2 -2
  40. package/dist/web/push-sw.js +1 -1
  41. package/dist/web/ssr.js +2 -2
  42. package/dist/web/vite.js +2 -2
  43. package/package.json +2 -2
  44. package/types/backend/src/decorators.d.ts +10 -0
  45. package/types/backend/src/openapi.d.ts +1 -0
  46. package/types/internal/src/messaging/engine.d.ts +6 -2
  47. package/types/internal/src/messaging/store.d.ts +21 -2
  48. package/types/internal/src/modules/auth.d.ts +26 -4
  49. package/types/internal/src/modules/messaging.d.ts +39 -6
  50. package/types/web/src/auth.d.ts +8 -0
  51. package/types/web/src/index.d.ts +1 -1
  52. package/types/web/src/messaging.d.ts +24 -2
  53. package/dist/chunks/HHYRMVWF.js +0 -2
  54. package/dist/chunks/UPS6BGJD.js +0 -21
package/dist/refuse/ai.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.18.6 — 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");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.18.6 — 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)");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.18.6 — 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");
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{a as e,b as f,c as g,d as h,e as i,f as j,g as k,h as l,i as m,j as n,k as o,l as p,m as q,n as r,o as s,p as t,q as u,r as v,s as w,t as x,u as y}from"../chunks/6CJHLHPT.js";import{a as c,b as d}from"../chunks/KPTP2RTE.js";import"../chunks/7CTORXHD.js";import"../chunks/5BTTH7AT.js";import{n as b}from"../chunks/HHYRMVWF.js";import"../chunks/N5WYA3DM.js";import{b as a}from"../chunks/W65B2VZ3.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.js";export{o as AuthUnavailable,b as EVENT_TYPES,c as FieldError,d as Fields,a as PalbaseError,t as ReservationSettled,n as TokenError,q as TokenVerifier,f as Transit,e as TransitRefusal,g as TransitRequest,i as WebhookSignatureError,h as createServer,s as isEntitled,y as loadSecrets,v as pages,x as platformOwn,w as processOwn,r as requestAddress,p as sessionStanding,l as signatureHeader,k as verifySignature,j as verifyWebhook,m as verifyWebhookRequest,u as withReservation};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{a as e,b as f,c as g,d as h,e as i,f as j,g as k,h as l,i as m,j as n,k as o,l as p,m as q,n as r,o as s,p as t,q as u,r as v,s as w,t as x,u as y}from"../chunks/E4CPOSFA.js";import{a as c,b as d}from"../chunks/6JA355QW.js";import"../chunks/Q2O72MGS.js";import"../chunks/Y76SPW2M.js";import{n as b}from"../chunks/IO3G5VIC.js";import"../chunks/4HYASQT5.js";import{b as a}from"../chunks/RGZZCQMZ.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.js";export{o as AuthUnavailable,b as EVENT_TYPES,c as FieldError,d as Fields,a as PalbaseError,t as ReservationSettled,n as TokenError,q as TokenVerifier,f as Transit,e as TransitRefusal,g as TransitRequest,i as WebhookSignatureError,h as createServer,s as isEntitled,y as loadSecrets,v as pages,x as platformOwn,w as processOwn,r as requestAddress,p as sessionStanding,l as signatureHeader,k as verifySignature,j as verifyWebhook,m as verifyWebhookRequest,u as withReservation};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{a,b,c,d,e}from"../chunks/XE6LFBDN.js";import"../chunks/KPTP2RTE.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.js";export{b as TestApiError,e as api,c as createTestApi,a as testFields,d as testRun};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{a,b,c,d,e}from"../chunks/OL33SRTB.js";import"../chunks/6JA355QW.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.js";export{b as TestApiError,e as api,c as createTestApi,a as testFields,d as testRun};
package/dist/web/index.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{a as L,b as j,c as q,d as G,e as D,f as N,g as U,h as F,i as B,j as H,k as J,l as K,m as W,n as X,o as Y,p as Z,q as ee,r as te,s as ne,t as re,u as oe,v as se,w as ae}from"../chunks/HKOGKWNU.js";import{a as _,b as Q,f as z}from"../chunks/PIWNLITG.js";import"../chunks/VUXQEYPQ.js";import"../chunks/SSL3F7OB.js";import"../chunks/NEBALOPJ.js";import{b as E,c as T,d as O,f as x,g as A,j as R,k as V,l as $,m as S,o as v}from"../chunks/7CTORXHD.js";import"../chunks/GF42QGWO.js";import"../chunks/HHYRMVWF.js";import"../chunks/N5WYA3DM.js";import{b as I}from"../chunks/W65B2VZ3.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.js";var ie="oai-events";async function ce(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 r=e.rtc??ye(),t=e.signal;t?.throwIfAborted();let f=e.audio??fe(),u=e.microphone===void 0,c=e.microphone??await r.getUserMedia({audio:!0});if(t?.aborted){if(u)for(let n of c.getTracks())n.stop();throw t.reason}let o=new r.RTCPeerConnection,s=!1,l=()=>{if(!s){if(s=!0,m.close(),o.close(),u)for(let n of c.getTracks())n.stop();f.srcObject!==null&&(f.srcObject=null)}};o.addEventListener("track",n=>{f.srcObject=n.streams[0]??new MediaStream([n.track]),f.play?.()?.catch?.(()=>{})}),o.addEventListener("connectionstatechange",()=>e.onState?.(o.connectionState));for(let n of c.getAudioTracks())o.addTrack(n,c);let m=o.createDataChannel(ie);m.addEventListener("message",n=>{let p=pe(n.data);p!==void 0&&e.onError?.(p)});let d=()=>l();t?.addEventListener("abort",d,{once:!0});try{await o.setLocalDescription(await o.createOffer()),t?.throwIfAborted(),await de(o,e.iceTimeoutMs??1e4,t);let n=o.localDescription?.sdp;if(!n)throw new Error("connectVoice: the peer connection made no offer");let p=await e.start(n);if(t?.throwIfAborted(),typeof p?.id!="string"||p.id===""||typeof p.sdp!="string"||p.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 o.setRemoteDescription({type:"answer",sdp:p.sdp}),t?.removeEventListener("abort",d),{id:p.id,peer:o,audio:f,microphone:c,get muted(){return c.getAudioTracks().every(h=>!h.enabled)},mute(h){for(let w of c.getAudioTracks())w.enabled=!h},close:l}}catch(n){throw t?.removeEventListener("abort",d),l(),t?.aborted?t.reason:n}}function de(e,r,t){return e.iceGatheringState==="complete"?Promise.resolve():t?.aborted?Promise.reject(t.reason):new Promise((f,u)=>{let c=()=>{clearTimeout(l),e.removeEventListener("icegatheringstatechange",o),t?.removeEventListener("abort",s)},o=()=>{e.iceGatheringState==="complete"&&(c(),f())},s=()=>{c(),u(t?.reason)},l=setTimeout(()=>{c(),u(new Error(`connectVoice: the network candidates were not gathered in ${r} ms`))},r);e.addEventListener("icegatheringstatechange",o),t?.addEventListener("abort",s,{once:!0})})}function pe(e){if(typeof e=="string")try{let r=JSON.parse(e);return r.type!=="error"?void 0:typeof r.error?.message=="string"?r.error.message:typeof r.error?.code=="string"?r.error.code:"the voice failed"}catch{return}}function ye(){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 r=e.navigator.mediaDevices;return{RTCPeerConnection:e.RTCPeerConnection,getUserMedia:t=>r.getUserMedia(t)}}function fe(){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 r=e.createElement("audio");return r.autoplay=!0,r}var i=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0;function le(e,r,t){let f=i(i(i(e)?.components)?.schemas)??{},u=(d,n)=>{let p=new Set,h=(C,g,y)=>{let a=i(C);if(!a)return;if(typeof a.$ref=="string"){if(y.has(a.$ref)||!a.$ref.startsWith("#/components/schemas/"))return;h(f[a.$ref.slice(21)],g,new Set(y).add(a.$ref));return}if(a[E]===!0){p.add(g);return}for(let b of["anyOf","oneOf","allOf"]){let k=a[b];if(Array.isArray(k))for(let M of k)h(M,g,y)}let P=i(a.properties);if(P)for(let[b,k]of Object.entries(P))h(k,`${g}/${S(b)}`,y);i(a.items)&&h(a.items,`${g}/*`,y);for(let b of["additionalProperties","patternProperties","prefixItems"])if(a[b]!==void 0&&w(a[b],new Set(y)))throw new Error(`${t}: an encrypted field is a named property \u2014 not every key of a record, nor a tuple's place`)},w=(C,g)=>{if(Array.isArray(C))return C.some(a=>w(a,g));let y=i(C);return y?y[E]===!0?!0:typeof y.$ref=="string"&&!g.has(y.$ref)&&y.$ref.startsWith("#/components/schemas/")?(g.add(y.$ref),w(f[y.$ref.slice(21)],g)):Object.values(y).some(a=>typeof a=="object"&&a!==null&&w(a,g)):!1};return h(d,n,new Set),[...p]},c=d=>i(i(i(d)?.["application/json"])?.schema),o=[];o.push(...u(c(i(r.requestBody)?.content),"/body"));for(let d of Array.isArray(r.parameters)?r.parameters:[]){let n=i(d);if(!n)continue;let p=u(n.schema,`/query/${S(String(n.name))}`);if(p.length!==0){if(n.in!=="query")throw new Error(`${t}: ${String(n.in)} parameter ${String(n.name)} is marked encrypted \u2014 a body's or a query's field is`);if(p.some(h=>h.split("/").length!==3))throw new Error(`${t}: an encrypted query field is one of the query's own names`);o.push(...p)}}let s=i(r.responses)??{},l=Object.keys(s).filter(d=>/^2\d\d$/.test(d)).sort((d,n)=>d==="200"?-1:n==="200"?1:d.localeCompare(n)),m=l.length>0?u(c(i(s[l[0]])?.content),"/response"):[];if(o.length+m.length!==0){if(r["x-palbase-sse"]!==void 0&&m.length>0)throw new Error(`${t}: a streamed answer carries no encrypted field`);if(r["x-palbase-upload"]!==void 0)throw new Error(`${t}: an upload goes through storage, which seals nothing \u2014 it carries no encrypted field`);return{request:o,response:m}}}async function ue(e){let r=`${e.method.toUpperCase()} ${e.path}`,t=i(i(i(i(e.contract)?.paths)?.[e.path])?.[e.method.toLowerCase()]),f=t?le(e.contract,t,r):void 0;if(!f)return{body:e.body,query:e.query,open:async s=>s};let{key:u,header:c}=await A(e.key.kid,O(e.key.publicKey),x(e.projectId,e.method,e.path,e.params??[])),o=(s,l)=>s==null?s:v(s,l,f.request,(m,d)=>R(u,m,d));return{header:c,body:await o(e.body,"/body"),query:await o(e.query,"/query"),open:s=>s===void 0?Promise.resolve(s):v(s,"/response",f.response,async(l,m)=>{if(!V(m))throw new T("unopenable",`${r}: ${l} came plain where the contract says it is encrypted`);return $(u,l,m)})}}export{U as Analytics,_ as BackendError,G as Channel,F as Consent,ne as ConversationList,re as ConversationView,Z as Flags,z as GatewayError,J as InApp,B as Inbox,N as Installation,te as Messaging,W as Notify,I as PalbaseError,X as Purchases,D as RealtimeSocket,H as SESSION_START,se as ScheduledList,L as SessionChangedError,oe as ThreadView,K as WebPush,ce as connectVoice,ae as createClient,ue as encryptedCall,ee as indexedDBKeyValue,Q as isBackendError,q as localStore,j as memoryStore,Y as redemptionToken};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{a as I,b as j,c as q,d as G,e as D,f as N,g as U,h as F,i as B,j as H,k as J,l as K,m as W,n as X,o as Y,p as Z,q as ee,r as te,s as ne,t as re,u as oe,v as se,w as ae,x as ie}from"../chunks/5N36M3Y3.js";import{a as _,b as Q,f as z}from"../chunks/S76H65KW.js";import"../chunks/RUE6N2T6.js";import"../chunks/ARDQJVIP.js";import"../chunks/6HESVOSN.js";import{b as E,c as T,d as O,f as x,g as A,j as R,k as V,l as $,m as S,o as v}from"../chunks/Q2O72MGS.js";import"../chunks/L4SDE4IC.js";import"../chunks/IO3G5VIC.js";import"../chunks/4HYASQT5.js";import{b as M}from"../chunks/RGZZCQMZ.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.js";var ce="oai-events";async function de(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 r=e.rtc??le(),t=e.signal;t?.throwIfAborted();let l=e.audio??ue(),f=e.microphone===void 0,c=e.microphone??await r.getUserMedia({audio:!0});if(t?.aborted){if(f)for(let n of c.getTracks())n.stop();throw t.reason}let o=new r.RTCPeerConnection,s=!1,u=()=>{if(!s){if(s=!0,m.close(),o.close(),f)for(let n of c.getTracks())n.stop();l.srcObject!==null&&(l.srcObject=null)}};o.addEventListener("track",n=>{l.srcObject=n.streams[0]??new MediaStream([n.track]),l.play?.()?.catch?.(()=>{})}),o.addEventListener("connectionstatechange",()=>e.onState?.(o.connectionState));for(let n of c.getAudioTracks())o.addTrack(n,c);let m=o.createDataChannel(ce);m.addEventListener("message",n=>{let p=ye(n.data);p!==void 0&&e.onError?.(p)});let d=()=>u();t?.addEventListener("abort",d,{once:!0});try{await o.setLocalDescription(await o.createOffer()),t?.throwIfAborted(),await pe(o,e.iceTimeoutMs??1e4,t);let n=o.localDescription?.sdp;if(!n)throw new Error("connectVoice: the peer connection made no offer");let p=await e.start(n);if(t?.throwIfAborted(),typeof p?.id!="string"||p.id===""||typeof p.sdp!="string"||p.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 o.setRemoteDescription({type:"answer",sdp:p.sdp}),t?.removeEventListener("abort",d),{id:p.id,peer:o,audio:l,microphone:c,get muted(){return c.getAudioTracks().every(h=>!h.enabled)},mute(h){for(let w of c.getAudioTracks())w.enabled=!h},close:u}}catch(n){throw t?.removeEventListener("abort",d),u(),t?.aborted?t.reason:n}}function pe(e,r,t){return e.iceGatheringState==="complete"?Promise.resolve():t?.aborted?Promise.reject(t.reason):new Promise((l,f)=>{let c=()=>{clearTimeout(u),e.removeEventListener("icegatheringstatechange",o),t?.removeEventListener("abort",s)},o=()=>{e.iceGatheringState==="complete"&&(c(),l())},s=()=>{c(),f(t?.reason)},u=setTimeout(()=>{c(),f(new Error(`connectVoice: the network candidates were not gathered in ${r} ms`))},r);e.addEventListener("icegatheringstatechange",o),t?.addEventListener("abort",s,{once:!0})})}function ye(e){if(typeof e=="string")try{let r=JSON.parse(e);return r.type!=="error"?void 0:typeof r.error?.message=="string"?r.error.message:typeof r.error?.code=="string"?r.error.code:"the voice failed"}catch{return}}function le(){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 r=e.navigator.mediaDevices;return{RTCPeerConnection:e.RTCPeerConnection,getUserMedia:t=>r.getUserMedia(t)}}function ue(){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 r=e.createElement("audio");return r.autoplay=!0,r}var i=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0;function fe(e,r,t){let l=i(i(i(e)?.components)?.schemas)??{},f=(d,n)=>{let p=new Set,h=(C,g,y)=>{let a=i(C);if(!a)return;if(typeof a.$ref=="string"){if(y.has(a.$ref)||!a.$ref.startsWith("#/components/schemas/"))return;h(l[a.$ref.slice(21)],g,new Set(y).add(a.$ref));return}if(a[E]===!0){p.add(g);return}for(let b of["anyOf","oneOf","allOf"]){let k=a[b];if(Array.isArray(k))for(let L of k)h(L,g,y)}let P=i(a.properties);if(P)for(let[b,k]of Object.entries(P))h(k,`${g}/${S(b)}`,y);i(a.items)&&h(a.items,`${g}/*`,y);for(let b of["additionalProperties","patternProperties","prefixItems"])if(a[b]!==void 0&&w(a[b],new Set(y)))throw new Error(`${t}: an encrypted field is a named property \u2014 not every key of a record, nor a tuple's place`)},w=(C,g)=>{if(Array.isArray(C))return C.some(a=>w(a,g));let y=i(C);return y?y[E]===!0?!0:typeof y.$ref=="string"&&!g.has(y.$ref)&&y.$ref.startsWith("#/components/schemas/")?(g.add(y.$ref),w(l[y.$ref.slice(21)],g)):Object.values(y).some(a=>typeof a=="object"&&a!==null&&w(a,g)):!1};return h(d,n,new Set),[...p]},c=d=>i(i(i(d)?.["application/json"])?.schema),o=[];o.push(...f(c(i(r.requestBody)?.content),"/body"));for(let d of Array.isArray(r.parameters)?r.parameters:[]){let n=i(d);if(!n)continue;let p=f(n.schema,`/query/${S(String(n.name))}`);if(p.length!==0){if(n.in!=="query")throw new Error(`${t}: ${String(n.in)} parameter ${String(n.name)} is marked encrypted \u2014 a body's or a query's field is`);if(p.some(h=>h.split("/").length!==3))throw new Error(`${t}: an encrypted query field is one of the query's own names`);o.push(...p)}}let s=i(r.responses)??{},u=Object.keys(s).filter(d=>/^2\d\d$/.test(d)).sort((d,n)=>d==="200"?-1:n==="200"?1:d.localeCompare(n)),m=u.length>0?f(c(i(s[u[0]])?.content),"/response"):[];if(o.length+m.length!==0){if(r["x-palbase-sse"]!==void 0&&m.length>0)throw new Error(`${t}: a streamed answer carries no encrypted field`);if(r["x-palbase-upload"]!==void 0)throw new Error(`${t}: an upload goes through storage, which seals nothing \u2014 it carries no encrypted field`);return{request:o,response:m}}}async function me(e){let r=`${e.method.toUpperCase()} ${e.path}`,t=i(i(i(i(e.contract)?.paths)?.[e.path])?.[e.method.toLowerCase()]),l=t?fe(e.contract,t,r):void 0;if(!l)return{body:e.body,query:e.query,open:async s=>s};let{key:f,header:c}=await A(e.key.kid,O(e.key.publicKey),x(e.projectId,e.method,e.path,e.params??[])),o=(s,u)=>s==null?s:v(s,u,l.request,(m,d)=>R(f,m,d));return{header:c,body:await o(e.body,"/body"),query:await o(e.query,"/query"),open:s=>s===void 0?Promise.resolve(s):v(s,"/response",l.response,async(u,m)=>{if(!V(m))throw new T("unopenable",`${r}: ${u} came plain where the contract says it is encrypted`);return $(f,u,m)})}}export{U as Analytics,_ as BackendError,G as Channel,F as Consent,ne as ConversationList,oe as ConversationView,re as DeletedGroupList,Z as Flags,z as GatewayError,J as InApp,B as Inbox,N as Installation,te as Messaging,W as Notify,M as PalbaseError,X as Purchases,D as RealtimeSocket,H as SESSION_START,ae as ScheduledList,I as SessionChangedError,se as ThreadView,K as WebPush,de as connectVoice,ie as createClient,me as encryptedCall,ee as indexedDBKeyValue,Q as isBackendError,q as localStore,j as memoryStore,Y as redemptionToken};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{a as i}from"../chunks/SSL3F7OB.js";import{a as e,b as s,c as t,d as p,e as o,f as a,h as r,j as n,k as y,p as M,q as l,t as g}from"../chunks/NEBALOPJ.js";import"../chunks/KMA7REYL.js";export{n as MESSAGE_COMPONENTS,a as MESSAGE_ICONS,r as MESSAGE_SCHEMA,s as assetId,y as countdownValues,e as fontFamily,o as htmlDocument,t as prepareAssets,i as presentMessage,g as renderMessage,M as resolveMessage,l as resolveMessageWithPaths,p as unzip};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{a as i}from"../chunks/ARDQJVIP.js";import{a as e,b as s,c as t,d as p,e as o,f as a,h as r,j as n,k as y,p as M,q as l,t as g}from"../chunks/6HESVOSN.js";import"../chunks/U4R3KQT6.js";export{n as MESSAGE_COMPONENTS,a as MESSAGE_ICONS,r as MESSAGE_SCHEMA,s as assetId,y as countdownValues,e as fontFamily,o as htmlDocument,t as prepareAssets,i as presentMessage,g as renderMessage,M as resolveMessage,l as resolveMessageWithPaths,p as unzip};
package/dist/web/palbe.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{c as e,d as r,i as t}from"../chunks/PIWNLITG.js";import"../chunks/7CTORXHD.js";import"../chunks/GF42QGWO.js";import"../chunks/N5WYA3DM.js";import"../chunks/W65B2VZ3.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{c as e,d as r,i as t}from"../chunks/S76H65KW.js";import"../chunks/Q2O72MGS.js";import"../chunks/L4SDE4IC.js";import"../chunks/4HYASQT5.js";import"../chunks/RGZZCQMZ.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{a as f,b as d,c as m,d as u,e as A,f as c,g as R}from"../chunks/VUXQEYPQ.js";import{a as e,b as a,c as t,d as l,e as r,f as o,g as p,i as y,k as s,l as P,n,o as i,s as w}from"../chunks/NEBALOPJ.js";import"../chunks/W65B2VZ3.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.js";export{y as PAYWALL_COMPONENTS,o as PAYWALL_ICONS,p as PAYWALL_SCHEMA,c as Paywall,a as assetId,f as attributesHeader,s as countdownValues,R as defaultPaywall,e as fontFamily,u as formatPeriod,m as formatPrice,r as htmlDocument,A as packageValues,P as packagesOf,d as parseDuration,t as prepareAssets,w as renderPaywall,n as resolvePaywall,i as resolvePaywallWithPaths,l as unzip};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{a as f,b as d,c as m,d as u,e as A,f as c,g as R}from"../chunks/RUE6N2T6.js";import{a as e,b as a,c as t,d as l,e as r,f as o,g as p,i as y,k as s,l as P,n,o as i,s as w}from"../chunks/6HESVOSN.js";import"../chunks/RGZZCQMZ.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.js";export{y as PAYWALL_COMPONENTS,o as PAYWALL_ICONS,p as PAYWALL_SCHEMA,c as Paywall,a as assetId,f as attributesHeader,s as countdownValues,R as defaultPaywall,e as fontFamily,u as formatPeriod,m as formatPrice,r as htmlDocument,A as packageValues,P as packagesOf,d as parseDuration,t as prepareAssets,w as renderPaywall,n as resolvePaywall,i as resolvePaywallWithPaths,l as unzip};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
2
  "use strict";(()=>{function g(n,s){if(n)try{let i=new URL(n,s);if(i.protocol==="https:"||i.protocol==="http:"&&(i.hostname==="localhost"||i.hostname==="127.0.0.1"))return i.href}catch{}}function p(n){let s=new URL(n.location.href).searchParams,i=s.get("url")??"",u=s.get("key")??"",a=(t,e)=>!t||!i?Promise.resolve():n.fetch(`${i.replace(/\/$/,"")}/notify/receipts`,{method:"POST",headers:{"content-type":"application/json",apikey:u},body:JSON.stringify({receipts:[{receipt:t,status:e}]}),keepalive:!0}).catch(()=>{}),l=async(t,e)=>{for(let o of await n.clients.matchAll({type:"window",includeUncontrolled:!0}))o.postMessage({type:"palbase.push",event:t,url:e.url,data:e.data})};n.addEventListener("push",(t=>{let e={};try{e=t.data?.json()??{}}catch{}let o={url:e.url,receipt:e.receipt,data:e.data},d=async()=>e.data?.type==="messaging.message"&&(await n.clients.matchAll({type:"window",includeUncontrolled:!0})).some(r=>r.focused===!0);t.waitUntil(d().then(r=>r?void 0:n.registration.showNotification(e.title??"",{body:e.body,image:e.image,tag:e.tag,data:o})).then(()=>Promise.all([a(e.receipt,"delivered"),l("received",o)])))})),n.addEventListener("notificationclick",(t=>{t.notification.close();let e=t.notification.data??{},o=g(e.url,n.location.origin),d=async()=>{if(!o)return;let c=(await n.clients.matchAll({type:"window",includeUncontrolled:!0})).find(f=>f.url===o);c?await c.focus():await n.clients.openWindow(o)};t.waitUntil(Promise.all([a(e.receipt,"opened"),d(),l("opened",e)]))})),n.addEventListener("notificationclose",(t=>{t.waitUntil(a(t.notification.data?.receipt,"dismissed"))}))}typeof self<"u"&&typeof self.registration=="object"&&!("document"in self)&&p(self);})();
package/dist/web/ssr.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! palbase 0.18.4 — Palbase SDK License (see LICENSE) */
2
- import{w as f}from"../chunks/HKOGKWNU.js";import"../chunks/PIWNLITG.js";import"../chunks/VUXQEYPQ.js";import"../chunks/SSL3F7OB.js";import"../chunks/NEBALOPJ.js";import"../chunks/7CTORXHD.js";import"../chunks/GF42QGWO.js";import"../chunks/HHYRMVWF.js";import"../chunks/N5WYA3DM.js";import"../chunks/W65B2VZ3.js";import"../chunks/MAYJWEPM.js";import"../chunks/KMA7REYL.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};
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import{x as f}from"../chunks/5N36M3Y3.js";import"../chunks/S76H65KW.js";import"../chunks/RUE6N2T6.js";import"../chunks/ARDQJVIP.js";import"../chunks/6HESVOSN.js";import"../chunks/Q2O72MGS.js";import"../chunks/L4SDE4IC.js";import"../chunks/IO3G5VIC.js";import"../chunks/4HYASQT5.js";import"../chunks/RGZZCQMZ.js";import"../chunks/NIDBDL7O.js";import"../chunks/U4R3KQT6.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.18.4 — Palbase SDK License (see LICENSE) */
2
- import"../chunks/KMA7REYL.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:
1
+ /*! palbase 0.18.6 — Palbase SDK License (see LICENSE) */
2
+ import"../chunks/U4R3KQT6.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.18.4",
3
+ "version": "0.18.6",
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",
@@ -135,7 +135,7 @@
135
135
  "dependencies": {
136
136
  "@types/node": "26.6.4",
137
137
  "bun-types": "1.4.2",
138
- "palgres": "0.18.4",
138
+ "palgres": "0.18.6",
139
139
  "reflect-metadata": "^0.2.2",
140
140
  "typescript": "~6.0.3",
141
141
  "zod": "^4.6.5"
@@ -37,6 +37,16 @@ export interface AuthConfig {
37
37
  * a signed-in user.
38
38
  */
39
39
  aal?: 'aal1' | 'aal2' | 'aal3';
40
+ /**
41
+ * How recent the user's last authentication must be, in seconds: their
42
+ * sign-in, or a step-up since (the token's auth_time, which a refresh keeps).
43
+ * For an action that asks the person again — sending money, changing the
44
+ * account's email: `{ aal: 'aal2', maxAge: 300 }` is "a second factor within
45
+ * the last 5 minutes". An older one is refused with 401
46
+ * insufficient_user_authentication and WWW-Authenticate's max_age (RFC 9470);
47
+ * the app steps the user up and calls again. Implies a signed-in user.
48
+ */
49
+ maxAge?: number;
40
50
  /**
41
51
  * Palbase checks no role or permission: a route naming one is refused at
42
52
  * boot, so none runs believing it was checked — check the role in the service.
@@ -10,6 +10,7 @@ export interface RouteFacts {
10
10
  required: boolean;
11
11
  verifiedEmail: boolean;
12
12
  aal: 'aal1' | 'aal2' | 'aal3';
13
+ maxAge: number | null;
13
14
  };
14
15
  /** The limit the route spends, or false when it has none. */
15
16
  limit: readonly RateLimitConfig[] | false;
@@ -1,7 +1,7 @@
1
1
  import type * as api from '../modules/messaging.js';
2
2
  import type { Kept } from './local.js';
3
3
  import { Outbox, type OutboxItem, type SendOutcome } from './outbox.js';
4
- import { Store, type Changes, type Message, type Touched } from './store.js';
4
+ import { Store, type Changes, type DeletedGroup, type Message, type Touched } from './store.js';
5
5
  export type Entry = {
6
6
  kind: 'message';
7
7
  message: Message;
@@ -13,7 +13,9 @@ export declare class Engine {
13
13
  readonly store: Store;
14
14
  readonly outbox: Outbox;
15
15
  readonly me: string;
16
- constructor(me: string);
16
+ /** Its clock (ms): what says a deleted group may no longer be reported. */
17
+ readonly now: () => number;
18
+ constructor(me: string, now?: () => number);
17
19
  apply(ch: Changes): Touched;
18
20
  reset(ch: Changes): Touched;
19
21
  private settled;
@@ -34,6 +36,8 @@ export declare class Engine {
34
36
  /** A thread's answers, then what is on its way to it. */
35
37
  answers(conversationId: string, rootId: string): Entry[];
36
38
  private entries;
39
+ /** The groups a person deleted that may still be reported, the latest to stop first. */
40
+ deletedGroups(): DeletedGroup[];
37
41
  kept(): Kept;
38
42
  load(k: Kept): void;
39
43
  }
@@ -4,6 +4,19 @@ export type Member = api.Member;
4
4
  export type Message = api.Message;
5
5
  export type ThreadState = api.ThreadState;
6
6
  export type ScheduledMessage = api.ScheduledMessage;
7
+ /** A group a person deleted, as the device keeps it while those who were in it may still report it. */
8
+ export interface DeletedGroup {
9
+ id: string;
10
+ /**
11
+ * Its title as the device had it: null when the device no longer had the group as the word came — one it never had,
12
+ * or, on the deleter's own device, one its app took from the list before the server's word with its days arrived.
13
+ */
14
+ title: string | null;
15
+ /** Who deleted it: null when no one is known any more. */
16
+ deletedBy: string | null;
17
+ /** Until when it may be reported (POST /messaging/reports naming it, no message), ISO 8601. */
18
+ reportableUntil: string;
19
+ }
7
20
  /** What changed for the reader: a sync page's, or a live `changes` event's. */
8
21
  export interface Changes {
9
22
  conversations?: Conversation[];
@@ -22,10 +35,11 @@ export interface Snapshot {
22
35
  messages: Message[];
23
36
  threads: ThreadState[];
24
37
  scheduled: ScheduledMessage[];
38
+ deleted: DeletedGroup[];
25
39
  }
26
40
  /** What changed in the store by one apply: what its views read again. */
27
41
  export interface Touched {
28
- /** The list of conversations (an order, an unread count, a last message). */
42
+ /** The list of conversations (an order, an unread count, a last message), and the groups deleted from it. */
29
43
  list: boolean;
30
44
  /** Conversations whose messages, members or details changed. */
31
45
  conversations: Set<string>;
@@ -45,11 +59,14 @@ export declare class Store {
45
59
  /** By the thread's root. */
46
60
  readonly threads: Map<string, api.ThreadState>;
47
61
  readonly scheduled: Map<string, api.ScheduledMessage>;
62
+ /** Groups a person deleted, by id: kept while they may be reported. */
63
+ readonly deleted: Map<string, DeletedGroup>;
48
64
  constructor(reader: string);
49
65
  /** Applies what changed; answers what of the store it touched. */
50
66
  apply(ch: Changes): Touched;
51
- /** A sync that starts again (reset): what the store kept goes, then the page is applied. */
67
+ /** A sync that starts again (reset): what the store kept goes — but the groups deleted, which no page carries again — then the page is applied. */
52
68
  reset(ch: Changes): Touched;
69
+ private removed;
53
70
  private drop;
54
71
  private putConversation;
55
72
  private putMember;
@@ -74,6 +91,8 @@ export declare class Store {
74
91
  timeline(conversationId: string): Message[];
75
92
  /** A thread's answers, the oldest first. */
76
93
  answers(conversationId: string, rootId: string): Message[];
94
+ /** The groups a person deleted that may still be reported at now (ms), the latest to stop first, then by id: those past it go. */
95
+ deletedGroups(now: number): DeletedGroup[];
77
96
  membersOf(conversationId: string): Member[];
78
97
  snapshot(): Snapshot;
79
98
  load(s: Snapshot): void;
@@ -3193,14 +3193,21 @@ export type StatusVerified = {
3193
3193
  status: "verified";
3194
3194
  };
3195
3195
  /**
3196
- * A TOTP step-up sends its `code`; a WebAuthn step-up sends the assertion of `POST /auth/step-up/webauthn/begin`'s ceremony at the top level of the same body.
3196
+ * A TOTP step-up sends its `code`; an SMS step-up the code `POST /auth/step-up/sms/send` texted; a WebAuthn step-up sends the assertion of `POST /auth/step-up/webauthn/begin`'s ceremony at the top level of the same body. An email code is not a step-up method: it is no second factor (NIST SP 800-63B-4 §3.1.3.1).
3197
3197
  *
3198
3198
  */
3199
- export type StepUpRequest = StepUpTOTPRequest | StepUpWebAuthnRequest;
3199
+ export type StepUpRequest = StepUpTOTPRequest | StepUpSMSRequest | StepUpWebAuthnRequest;
3200
3200
  export type StepUpTOTPRequest = {
3201
3201
  code: string;
3202
3202
  method: "totp";
3203
3203
  };
3204
+ /**
3205
+ * The code `POST /auth/step-up/sms/send` texted to the user's SMS factor.
3206
+ */
3207
+ export type StepUpSMSRequest = {
3208
+ code: string;
3209
+ method: "sms";
3210
+ };
3204
3211
  /**
3205
3212
  * `method` beside the PublicKeyCredential JSON a browser makes in `navigator.credentials.get()` (as `WebAuthnAssertionResponse`); all binary fields are base64url-encoded.
3206
3213
  *
@@ -5478,8 +5485,12 @@ export declare function client(t: Transport): {
5478
5485
  * Raise session ACR via step-up
5479
5486
  *
5480
5487
  * Raise the session ACR (authentication context reference) by
5481
- * re-verifying with TOTP or WebAuthn. Required before sensitive
5482
- * operations. Subject to rate limiting (5 per 5 min per account).
5488
+ * re-verifying with an authenticator app's code (TOTP, aal2), a code texted
5489
+ * to the user's SMS factor (aal2), or a passkey (WebAuthn: aal2, aal3 for a
5490
+ * device-bound key). The new access token's amr names the method (otp,
5491
+ * sms, swk, hwk) and its auth_time is now; tokens refreshed from the session
5492
+ * keep both. Required before sensitive operations. Subject to rate limiting
5493
+ * (5 per 5 min per account).
5483
5494
  *
5484
5495
  */
5485
5496
  stepUp(input: {
@@ -5508,6 +5519,17 @@ export declare function client(t: Transport): {
5508
5519
  stepUpWebAuthnBegin(input?: {
5509
5520
  signal?: AbortSignal;
5510
5521
  }): Promise<Reply<200, WebAuthnCredentialRequestOptions>>;
5522
+ /**
5523
+ * Text a step-up code
5524
+ *
5525
+ * Text the signed-in user's SMS factor a code for a step-up; `POST /auth/step-up`
5526
+ * with method `sms` checks it. The project's SMS second-factor policy and its
5527
+ * per-phone rate limit apply; a test fixture's fixed code is never texted.
5528
+ *
5529
+ */
5530
+ stepUpSmsSend(input?: {
5531
+ signal?: AbortSignal;
5532
+ }): Promise<Reply<200, StatusSent>>;
5511
5533
  /**
5512
5534
  * Exchange custom token for session
5513
5535
  *
@@ -391,6 +391,19 @@ export type DirectRequest = {
391
391
  */
392
392
  user_id: string;
393
393
  };
394
+ /**
395
+ * What an edited message said before a change.
396
+ */
397
+ export type EarlierVersion = {
398
+ /**
399
+ * When it was changed.
400
+ */
401
+ replaced_at: string;
402
+ /**
403
+ * What it said.
404
+ */
405
+ text: string;
406
+ };
394
407
  /**
395
408
  * A message's new words.
396
409
  */
@@ -964,15 +977,31 @@ export type RemovedConversation = {
964
977
  * The conversation.
965
978
  */
966
979
  conversation_id: string;
980
+ /**
981
+ * The person who deleted the group (absent: the project's server, or no one known any more).
982
+ */
983
+ deleted_by?: string | null;
967
984
  /**
968
985
  * Why: deleted.
969
986
  */
970
987
  reason: string;
988
+ /**
989
+ * For a group a person deleted: until when those who were in it still report it (POST /messaging/reports, naming the conversation), 14 days after it was deleted. Absent once that is past, or when the project's server deleted it.
990
+ */
991
+ reportable_until?: string | null;
971
992
  };
972
993
  /**
973
994
  * A report as the project's server reads it.
974
995
  */
975
996
  export type Report = {
997
+ /**
998
+ * For a report of a group a person had deleted: when they deleted it.
999
+ */
1000
+ conversation_deleted_at: string | null;
1001
+ /**
1002
+ * Who deleted it (null when not deleted, or no one known any more).
1003
+ */
1004
+ conversation_deleted_by: string | null;
976
1005
  /**
977
1006
  * The conversation.
978
1007
  */
@@ -1087,7 +1116,7 @@ export type ReportRequest = {
1087
1116
  */
1088
1117
  conversation_id: string;
1089
1118
  /**
1090
- * Messages the reader sees in it (at most 50).
1119
+ * Messages the reader sees in it (at most 50). Naming none for a group a person deleted, the last 30 messages the reader saw go with the report.
1091
1120
  */
1092
1121
  message_ids?: string[];
1093
1122
  /**
@@ -1115,6 +1144,10 @@ export type ReportedMessage = {
1115
1144
  * When it was sent.
1116
1145
  */
1117
1146
  created_at: string;
1147
+ /**
1148
+ * What it said before its edits, the oldest first: the versions changed while the reporter was in the conversation, kept 14 days after each change.
1149
+ */
1150
+ earlier_versions: EarlierVersion[];
1118
1151
  /**
1119
1152
  * The message.
1120
1153
  */
@@ -1693,7 +1726,7 @@ export declare function client(t: Transport): {
1693
1726
  /**
1694
1727
  * Delete a conversation
1695
1728
  *
1696
- * The conversation goes for everyone, its messages, files and keys with it. In the access log.
1729
+ * The conversation goes for everyone, its messages, files and keys with it, at once — a group a person deleted, still sealed for reports, too. In the access log.
1697
1730
  */
1698
1731
  adminDeleteConversation(input: {
1699
1732
  path: {
@@ -1805,7 +1838,7 @@ export declare function client(t: Transport): {
1805
1838
  /**
1806
1839
  * One report, with what it carries
1807
1840
  *
1808
- * A report with its reporter's note and what the messages it names said when reported (their files with the keys that open them; a message already gone from its reader's screen — seen once, its time up, vanish mode, taken back — as it was kept for reports, 14 days). In the access log. An owner's or an admin's read from Studio or with a token: a member sees the conversations and the reports, not what was said. A report is kept 180 days once resolved, two years never resolved.
1841
+ * A report with its reporter's note and what the messages it names said when reported (their files with the keys that open them; a message already gone from its reader's screen — seen once, its time up, vanish mode, taken back — as it was kept for reports, 14 days). In the access log. An owner's or an admin's read from Studio or with a token: a member sees the conversations and the reports, not what was said. A report is kept 190 days once resolved, two years never resolved.
1809
1842
  */
1810
1843
  adminGetReport(input: {
1811
1844
  path: {
@@ -1918,7 +1951,7 @@ export declare function client(t: Transport): {
1918
1951
  /**
1919
1952
  * Delete a group for everyone
1920
1953
  *
1921
- * A group's owner or admin deletes it for everyone: its messages, its files and its keys go. A direct conversation is cleared, not deleted (…/clear).
1954
+ * A group's owner or admin deletes it for everyone: it goes from their lists at once (`removed`, with `reportable_until`), and what it said, its files and its keys stay sealed 14 days for those who were in it to report it, then go. A direct conversation is cleared, not deleted (…/clear).
1922
1955
  */
1923
1956
  deleteConversation(input: {
1924
1957
  path: {
@@ -2069,7 +2102,7 @@ export declare function client(t: Transport): {
2069
2102
  /**
2070
2103
  * Change a message
2071
2104
  *
2072
- * Its writer changes what a message says, within 15 minutes of sending it; its files stay.
2105
+ * Its writer changes what a message says, within 15 minutes of sending it; its files stay. What it said before is kept 14 days, sealed, for a report alone.
2073
2106
  */
2074
2107
  editMessage(input: {
2075
2108
  path: {
@@ -2254,7 +2287,7 @@ export declare function client(t: Transport): {
2254
2287
  /**
2255
2288
  * Report a conversation, a person or messages
2256
2289
  *
2257
- * The reader reports a conversation, someone in it or messages they see in it, saying why. What the messages say is kept with the report, sealed — it outlives them — and the project's backend is told (`messaging.report.created`) to read it with its secret key.
2290
+ * The reader reports a conversation, someone in it or messages they see in it, saying why. What the messages say is kept with the report, sealed — it outlives them — with what they said before an edit, and the project's backend is told (`messaging.report.created`) to read it with its secret key. A group a person deleted is reported, for 14 days, by those who were in it: naming no message, its last 30 the reader saw go with the report.
2258
2291
  */
2259
2292
  report(input: {
2260
2293
  body: ReportRequest; /** Stops the call: the request in flight, a wait before a retry, a proof-of-work being solved. */
@@ -69,6 +69,14 @@ export declare class Auth {
69
69
  * here on; its refreshes stay at aal2.
70
70
  */
71
71
  stepUp: (code: string) => Promise<Session>;
72
+ /** Texts the signed-in user's SMS factor a code for stepUpWithSms. */
73
+ sendStepUpSmsCode: () => Promise<void>;
74
+ /**
75
+ * Raises the signed-in session to aal2 with the code sendStepUpSmsCode texted,
76
+ * as stepUp does with an authenticator's. The token says it was a text
77
+ * (amr "sms"). An email code is no way up: it is not a second factor.
78
+ */
79
+ stepUpWithSms: (code: string) => Promise<Session>;
72
80
  };
73
81
  readonly passkey: {
74
82
  /** Adds a passkey to the signed-in user. */
@@ -10,7 +10,7 @@ export { connectVoice, type StartedVoice, type VoiceConnection, type VoiceOption
10
10
  export { Purchases, redemptionToken, type CheckoutSource, type CustomerInfo, type CustomerInfoListener, type GrantInfo, type MergeGrant, type OfferView, type Offerings, type Redeemed, type RedemptionLink, } from './purchases.js';
11
11
  export { Notify, WebPush, type PushPermission, type PushSubscribeOptions } from './notify.js';
12
12
  export { Flags, type FlagSource, type FlagsListener } from './flags.js';
13
- export { ConversationList, ConversationView, indexedDBKeyValue, Messaging, ScheduledList, ThreadView, type Conversation, type ConversationViewState, type ConversationListState, type Entry, type Member, type Message, type MessagingOptions, type MyProfile, type Observed, type OpenedFile, type OutboxItem, type OutgoingFile, type Profile, type ScheduledMessage, type SendOptions, type ThreadState, type ThreadViewState, } from './messaging.js';
13
+ export { ConversationList, ConversationView, DeletedGroupList, indexedDBKeyValue, Messaging, ScheduledList, ThreadView, type Conversation, type ConversationViewState, type ConversationListState, type DeletedGroup, type DeletedGroupListState, type Entry, type Member, type Message, type MessagingOptions, type MyProfile, type Observed, type OpenedFile, type OutboxItem, type OutgoingFile, type Profile, type ScheduledMessage, type SendOptions, type ThreadState, type ThreadViewState, } from './messaging.js';
14
14
  export { Inbox, type InboxItem, type InboxListOptions, type InboxPage, type InboxView, type InboxViewOptions } from './inbox.js';
15
15
  export { InApp, SESSION_START, type InAppOptions } from './inapp.js';
16
16
  export type { Paywall, PaywallRenderOptions } from './paywall/placement.js';
@@ -1,5 +1,5 @@
1
1
  import { messaging as api } from '../../internal/src/modules/index.js';
2
- import { Engine, type Entry, type KeyValue, type OutboxItem, type Touched } from '../../internal/src/messaging/index.js';
2
+ import { Engine, type DeletedGroup, type Entry, type KeyValue, type OutboxItem, type Touched } from '../../internal/src/messaging/index.js';
3
3
  import { type Fetch, type Transport } from '../../internal/src/transport.js';
4
4
  import { type SessionManager } from './session.js';
5
5
  import type { RealtimeSocket } from './socket.js';
@@ -10,7 +10,7 @@ export type MyProfile = api.MyProfile;
10
10
  export type Profile = api.Profile;
11
11
  export type ScheduledMessage = api.ScheduledMessage;
12
12
  export type ThreadState = api.ThreadState;
13
- export type { Entry, OutboxItem } from '../../internal/src/messaging/index.js';
13
+ export type { DeletedGroup, Entry, OutboxItem } from '../../internal/src/messaging/index.js';
14
14
  export interface MessagingOptions {
15
15
  /**
16
16
  * What the device keeps of a person's conversations when they sign out:
@@ -74,6 +74,10 @@ export interface ConversationListState {
74
74
  /** The device's copy was drawn and the sync has caught up. */
75
75
  synced: boolean;
76
76
  }
77
+ export interface DeletedGroupListState {
78
+ /** The groups deleted that the person may still report, the latest to stop first. */
79
+ items: DeletedGroup[];
80
+ }
77
81
  export interface ConversationViewState {
78
82
  conversation: Conversation | null;
79
83
  /** Its timeline: its messages, the oldest first, then what is on its way. */
@@ -154,6 +158,8 @@ export declare class Messaging {
154
158
  private after;
155
159
  /** A message whose time is up goes from the device at once: the server says so too, a moment after. */
156
160
  private expireAt;
161
+ /** A group deleted goes from deletedGroups() once it may no longer be reported: the views hear it then. */
162
+ private expireDeleted;
157
163
  private deliver;
158
164
  private save;
159
165
  /** Sends what waits, in each conversation's order; tries again later while the network or the server is away. */
@@ -168,6 +174,13 @@ export declare class Messaging {
168
174
  private tell;
169
175
  /** The person's conversations, the latest first, kept up to date. */
170
176
  conversations(): ConversationList;
177
+ /**
178
+ * The groups the person was in that someone deleted, kept up to date while the person may still report them
179
+ * (reportableUntil, 14 days after), the latest to stop first: report() names one by its id, no message needed. A
180
+ * group the project's server deleted is not among them. A title may be null: the device did not have the group as
181
+ * the word came (on the deleter's own device, now and then, the group the person deleted).
182
+ */
183
+ deletedGroups(): DeletedGroupList;
171
184
  /** A conversation of the person's, kept up to date: its timeline, its members, who is typing. */
172
185
  conversation(conversationId: string): ConversationView;
173
186
  /** The direct conversation with someone — the one there is, or a new one. */
@@ -227,6 +240,11 @@ export declare class Messaging {
227
240
  profiles(userIds: string[]): Promise<Profile[]>;
228
241
  block(userId: string): Promise<void>;
229
242
  unblock(userId: string): Promise<void>;
243
+ /**
244
+ * Reports a conversation, someone in it (user_id) or messages they see in it (message_ids), saying why: what the
245
+ * messages say is kept with the report, sealed. A group from deletedGroups() is reported by its id until its
246
+ * reportableUntil, naming no message: the last 30 messages the person saw in it go with the report.
247
+ */
230
248
  report(input: api.ReportRequest): Promise<api.ReportCreated>;
231
249
  }
232
250
  declare abstract class View<S> implements Observed<S> {
@@ -247,6 +265,10 @@ export declare class ConversationList extends View<ConversationListState> {
247
265
  protected touches(t: Touched): boolean;
248
266
  protected read(): ConversationListState;
249
267
  }
268
+ export declare class DeletedGroupList extends View<DeletedGroupListState> {
269
+ protected touches(t: Touched): boolean;
270
+ protected read(): DeletedGroupListState;
271
+ }
250
272
  export declare class ConversationView extends View<ConversationViewState> {
251
273
  readonly id: string;
252
274
  constructor(m: Messaging, id: string);