palbase 0.3.1 → 0.3.3

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 (38) hide show
  1. package/LICENSE +11 -5
  2. package/dist/ai/index.js +2 -2
  3. package/dist/backend/engine.js +2 -2
  4. package/dist/backend/env.js +1 -1
  5. package/dist/backend/index.js +3 -3
  6. package/dist/backend/stack.js +1 -1
  7. package/dist/backend/test.js +2 -2
  8. package/dist/chunks/{NTMO2LFH.js → 47V66C2X.js} +2 -2
  9. package/dist/chunks/{L6GKX3XI.js → 4AQYBTIN.js} +2 -2
  10. package/dist/chunks/{XNRYSI7A.js → 4YD2XCGF.js} +1 -1
  11. package/dist/chunks/{XOGEEZNP.js → CJCMQ73A.js} +2 -2
  12. package/dist/chunks/{INXQWVHU.js → CZQ7KIRM.js} +2 -2
  13. package/dist/chunks/{TV7W53F2.js → IXHR57QC.js} +2 -2
  14. package/dist/chunks/{4UPL27ED.js → M5B52IE6.js} +1 -1
  15. package/dist/chunks/{6FQGUDBD.js → NK54UVDI.js} +2 -2
  16. package/dist/chunks/{4MOCDBZP.js → OKZJIY6F.js} +1 -1
  17. package/dist/chunks/{JF7KZUPL.js → P5JIZEPB.js} +2 -2
  18. package/dist/chunks/PB7UKHCY.js +2 -0
  19. package/dist/chunks/{VTNEPJRV.js → PRM2UXWG.js} +1 -1
  20. package/dist/chunks/TJ5SQTW5.js +92 -0
  21. package/dist/chunks/{MJPUCGXY.js → UXRIXHHY.js} +2 -2
  22. package/dist/chunks/{4K4MKD2J.js → YWOS5WH2.js} +2 -2
  23. package/dist/cli.js +153 -132
  24. package/dist/refuse/ai.js +1 -1
  25. package/dist/refuse/backend.js +1 -1
  26. package/dist/refuse/server.js +1 -1
  27. package/dist/server/index.js +2 -2
  28. package/dist/server/testing.js +2 -2
  29. package/dist/web/index.js +2 -2
  30. package/dist/web/palbe.js +2 -2
  31. package/dist/web/paywall.js +2 -2
  32. package/dist/web/vite.js +2 -2
  33. package/package.json +6 -6
  34. package/types/internal/src/modules/purchases.d.ts +77 -4
  35. package/types/internal/src/modules/storage.d.ts +3 -2
  36. package/types/server/src/auth/jwt.d.ts +4 -1
  37. package/dist/chunks/2YUVLZLK.js +0 -87
  38. package/dist/chunks/FVIHTHHV.js +0 -2
package/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  Palbase SDK License
2
2
 
3
- Copyright (c) 2024-present Palbase. All rights reserved.
3
+ Copyright (c) 2024-present Pallasite OÜ (Estonian registry code 17348411), Tallinn, Estonia ("Pallasite",
4
+ "we"), the maker of Palbase. All rights reserved.
4
5
 
5
6
  The Palbase SDK — the compiled libraries, their interface files and the documentation distributed with them
6
7
  ("the SDK") — is licensed, not sold. Its source code is not part of this distribution.
@@ -17,14 +18,19 @@ The Palbase SDK — the compiled libraries, their interface files and the docume
17
18
  code, except to the extent applicable law expressly permits it notwithstanding this restriction;
18
19
  c. remove or alter any notice in the SDK.
19
20
 
20
- 3. Ownership. Palbase keeps all rights in the SDK that this license does not expressly grant.
21
+ 3. Ownership. Pallasite keeps all rights in the SDK that this license does not expressly grant.
21
22
 
22
23
  4. No warranty. The SDK is provided "as is", without warranty of any kind, express or implied, including the
23
24
  warranties of merchantability, fitness for a particular purpose and non-infringement.
24
25
 
25
- 5. Limitation of liability. In no event shall Palbase be liable for any claim, damages or other liability,
26
- whether in an action of contract, tort or otherwise, arising from, out of or in connection with the SDK or
27
- its use.
26
+ 5. Limitation of liability. To the extent permitted by applicable law, in no event shall Pallasite be liable
27
+ for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising
28
+ from, out of or in connection with the SDK or its use.
28
29
 
29
30
  6. Termination. This license ends automatically if you break its terms; you must then stop using and
30
31
  distributing the SDK.
32
+
33
+ 7. Governing law and venue. This license, and any dispute arising out of or in connection with it, is governed
34
+ by the laws of the Republic of Estonia, excluding their conflict-of-laws rules. The courts of Estonia have
35
+ exclusive jurisdiction, with Harju County Court (Harju Maakohus) in Tallinn as the court of first instance,
36
+ except where mandatory law gives you the right to bring a claim elsewhere.
package/dist/ai/index.js CHANGED
@@ -1,5 +1,5 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{a as V}from"../chunks/XNRYSI7A.js";import{a as W}from"../chunks/6FQGUDBD.js";import{a as q,b as Y}from"../chunks/TV7W53F2.js";import{b as U,d as z}from"../chunks/MJPUCGXY.js";import"../chunks/4MOCDBZP.js";import"../chunks/VTNEPJRV.js";async function*Z(e){let t=e.getReader(),a=new TextDecoder,r="",o="",l="";try{for(;;){let{done:d,value:g}=await t.read();if(d)return;r+=a.decode(g,{stream:!0}).replace(/\r\n/g,`
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{a as V}from"../chunks/4YD2XCGF.js";import{a as W}from"../chunks/NK54UVDI.js";import{a as q,b as Y}from"../chunks/IXHR57QC.js";import{b as U,d as z}from"../chunks/UXRIXHHY.js";import"../chunks/OKZJIY6F.js";import"../chunks/PRM2UXWG.js";async function*Z(e){let t=e.getReader(),a=new TextDecoder,r="",o="",l="";try{for(;;){let{done:d,value:g}=await t.read();if(d)return;r+=a.decode(g,{stream:!0}).replace(/\r\n/g,`
3
3
  `);for(let b=r.indexOf(`
4
4
  `);b>=0;b=r.indexOf(`
5
5
  `)){let v=r.slice(0,b);r=r.slice(b+1),v===""?(o!==""&&(yield{event:o,data:l}),o="",l=""):v.startsWith("event: ")?o=v.slice(7):v.startsWith("data: ")&&(l=v.slice(6))}}}finally{try{await t.cancel()}catch{}}}var se=/\s/;function M(e,t){for(;t<e.length&&se.test(e[t]);)t++;return t}function H(e,t){let a="";for(let r=t+1;r<e.length;r++){let o=e[r];if(o==='"')return{value:a,complete:!0,empty:!1,at:r+1};if(o!=="\\"){a+=o;continue}let l=e[r+1];if(l===void 0)break;if(l==="u"){let d=e.slice(r+2,r+6);if(d.length<4)break;a+=String.fromCharCode(Number.parseInt(d,16)),r+=5;continue}a+={n:`
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{ba as h,ea as d}from"../chunks/XOGEEZNP.js";import"../chunks/4UPL27ED.js";import"../chunks/FVIHTHHV.js";import"../chunks/XNRYSI7A.js";import"../chunks/6FQGUDBD.js";import"../chunks/TV7W53F2.js";import"../chunks/MJPUCGXY.js";import"../chunks/4MOCDBZP.js";import"../chunks/VTNEPJRV.js";import{binding as R,createDatabase as v}from"palgres";var b=new WeakMap;function q(l,e,n){if(!n?.schemas?.length)throw new TypeError("createRequestDatabase(sql, identity, { schemas }): the engine compiles each call against the app's schemas \u2014 pass the schema files' default exports");let u=n.schemas,s=b.get(l);s||b.set(l,s=new Map);let r=s.get(u);r||s.set(u,r=new Map);let o=e.role===e.serviceRole?"service":e.role==="anon"?"anon":"authenticated",f=o==="service"?{service:e.serviceRole}:{[o]:e.role,service:e.serviceRole},g=`${o}\0${e.role}\0${e.serviceRole}`,i=r.get(g);i||(i=v({sql:l,schemas:u,binding:R(0,!0),roles:f}),r.set(g,i));let w=JSON.parse(e.claimsJson),m=i.then(a=>a.request({role:o,claims:w},{diagnostics:n.diagnostics,signal:n.signal})),y=a=>new Proxy(()=>{},{apply:async(t,D,c)=>{let p=(await m).client;return a(p).apply(p,c)}});return{client:new Proxy({},{get(a,t){if(t!=="then")return t==="diagnostics"?()=>null:t==="asService"?()=>new Proxy({},{get:(D,c)=>c==="then"?void 0:y(p=>p.asService()[c])}):y(D=>D[t])}}),commit:async()=>(await m).commit(),rollback:async a=>(await m).rollback(a)}}export{h as createApp,q as createRequestDatabase,d as makeMemoryCache};
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{ba as h,ea as d}from"../chunks/CJCMQ73A.js";import"../chunks/M5B52IE6.js";import"../chunks/PB7UKHCY.js";import"../chunks/4YD2XCGF.js";import"../chunks/NK54UVDI.js";import"../chunks/IXHR57QC.js";import"../chunks/UXRIXHHY.js";import"../chunks/OKZJIY6F.js";import"../chunks/PRM2UXWG.js";import{binding as R,createDatabase as v}from"palgres";var b=new WeakMap;function q(l,e,n){if(!n?.schemas?.length)throw new TypeError("createRequestDatabase(sql, identity, { schemas }): the engine compiles each call against the app's schemas \u2014 pass the schema files' default exports");let u=n.schemas,s=b.get(l);s||b.set(l,s=new Map);let r=s.get(u);r||s.set(u,r=new Map);let o=e.role===e.serviceRole?"service":e.role==="anon"?"anon":"authenticated",f=o==="service"?{service:e.serviceRole}:{[o]:e.role,service:e.serviceRole},g=`${o}\0${e.role}\0${e.serviceRole}`,i=r.get(g);i||(i=v({sql:l,schemas:u,binding:R(0,!0),roles:f}),r.set(g,i));let w=JSON.parse(e.claimsJson),m=i.then(a=>a.request({role:o,claims:w},{diagnostics:n.diagnostics,signal:n.signal})),y=a=>new Proxy(()=>{},{apply:async(t,D,c)=>{let p=(await m).client;return a(p).apply(p,c)}});return{client:new Proxy({},{get(a,t){if(t!=="then")return t==="diagnostics"?()=>null:t==="asService"?()=>new Proxy({},{get:(D,c)=>c==="then"?void 0:y(p=>p.asService()[c])}):y(D=>D[t])}}),commit:async()=>(await m).commit(),rollback:async a=>(await m).rollback(a)}}export{h as createApp,q as createRequestDatabase,d as makeMemoryCache};
@@ -1 +1 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
@@ -1,5 +1,5 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{$ as C,A as T,B as Qe,C as Xe,D as Ze,E as et,F as rt,G as st,H as nt,I as at,J as ot,K as it,L as lt,M as ct,N as dt,O as ut,P as pt,Q as ht,R as Y,S as bt,T as mt,U as gt,V as ft,W as yt,X as wt,Y as Pt,Z as St,_ as vt,a as K,aa as kt,b as z,ba as B,c as G,ca as At,d as _e,da as Rt,e as Oe,f as Te,g as Ce,h as Be,i as Fe,j as Me,k as Ie,l as Le,m as $e,n as Ue,o as De,p as je,q as Ne,r as qe,s as Ve,t as We,u as Ke,v as ze,w as Ge,x as He,y as Je,z as Ye}from"../chunks/XOGEEZNP.js";import{b as Et}from"../chunks/INXQWVHU.js";import{a as E,b as H,c as J,e as h,f as tt,g as d}from"../chunks/4UPL27ED.js";import{a as j,g as Ee,h as xe,i as q,j as O,q as V,r as W}from"../chunks/FVIHTHHV.js";import"../chunks/XNRYSI7A.js";import{m as Re}from"../chunks/6FQGUDBD.js";import"../chunks/TV7W53F2.js";import{b as _}from"../chunks/MJPUCGXY.js";import"../chunks/4MOCDBZP.js";import"../chunks/VTNEPJRV.js";import"reflect-metadata";import{existsSync as er,writeFileSync as tr,writeSync as he}from"node:fs";import{createServer as rr}from"node:http";import{dirname as N,join as sr,resolve as nr}from"node:path";import{Readable as ar}from"node:stream";var xt=2e3,_t=1e4,Ot=/^[A-Za-z0-9_-]{1,64}$/,Tt=512,F=class{linesPerSecond;batchSize;flushMs;maxPending;sendMs;shutdownMs;now;tokens;refilled;unlogged=0;unloggedSince;pending=[];timer;sending;inFlight;pausedUntil=0;lastSendWarning=0;sink;constructor(e,r={}){this.sink=e,this.linesPerSecond=r.linesPerSecond??10,this.batchSize=Math.min(100,r.batchSize??100),this.flushMs=r.flushMs??2e3,this.maxPending=r.maxPending??2e3,this.sendMs=r.sendMs??_t,this.shutdownMs=r.shutdownMs??xt,this.now=r.now??Date.now,this.tokens=this.linesPerSecond,this.refilled=this.now(),this.unloggedSince=this.refilled}record(e){this.log(e),this.sink&&this.trace(e)}async flush(){this.timer&&clearTimeout(this.timer),this.timer=void 0;let e=!1,r,s=new Promise(a=>r=a),n=setTimeout(()=>{e=!0,r()},this.shutdownMs);try{for(;!e&&(this.pending.length>0||this.sending)&&(await Promise.race([this.sending??this.send(),s]),!(this.now()<this.pausedUntil)););}finally{clearTimeout(n)}e&&this.letGo()}letGo(){let e=this.inFlight,r=(e?.traces??0)+this.pending.length;this.pending=[],e&&(e.letGo=!0,e.call.abort(new Error(`analytics did not answer within the ${this.shutdownMs} ms a flush waits`))),r>0&&d.warn(`[palbase] request traces were not sent to analytics within the ${this.shutdownMs} ms a flush waits; ${r} dropped`)}log(e){let r=this.now();if(this.tokens=Math.min(this.linesPerSecond,this.tokens+(r-this.refilled)/1e3*this.linesPerSecond),this.refilled=r,this.unlogged>0&&r-this.unloggedSince>=6e4&&(d.info(`[palbase] ${this.unlogged} more requests answered in the last minute than the log keeps a line for (Analytics \u203A Network has every one)`),this.unlogged=0,this.unloggedSince=r),this.tokens<1){this.unlogged===0&&(this.unloggedSince=r),this.unlogged++;return}this.tokens-=1;let s=e.status>=500?"error":e.status>=400&&e.status!==499?"warn":"info",n=Math.round(e.durationMs*10)/10;d[s](`${e.method} ${e.path} ${e.status} ${n}ms`,{route:e.endpoint,status:e.status,duration_ms:n,...e.userId?{user_id:e.userId}:{}})}trace(e){this.pending.length>=this.maxPending&&this.pending.shift(),this.pending.push({request_id:Ot.test(e.requestId)?e.requestId:e.requestId.replace(/[^A-Za-z0-9_-]/g,"_").slice(0,64)||"unnamed",source:"backend",endpoint:e.endpoint.slice(0,Tt),method:e.method,status:e.status,duration_ms:Math.max(0,Math.round(e.durationMs)),timestamp:this.now(),...e.userId?{distinct_id:e.userId}:{}}),this.pending.length>=this.batchSize&&!this.sending?this.send():!this.timer&&!this.sending&&this.schedule(this.flushMs)}schedule(e){this.timer=setTimeout(()=>{this.send()},e),this.timer.unref?.()}send(){if(this.timer&&clearTimeout(this.timer),this.timer=void 0,this.sending||this.pending.length===0||this.now()<this.pausedUntil||!this.sink)return this.sending??Promise.resolve();let e=this.pending.splice(0,this.batchSize),r=this.sink,s={call:new AbortController,traces:e.length,letGo:!1};this.inFlight=s;let n=setTimeout(()=>s.call.abort(new Error(`analytics did not answer in ${this.sendMs} ms`)),this.sendMs);return n.unref?.(),this.sending=(async()=>{try{await r.sendTraceBatch({body:{traces:e},signal:s.call.signal})}catch(a){if(s.letGo)return;let l=a.status,o=l??(s.call.signal.aborted?`no answer in ${this.sendMs} ms`:"unreachable"),c=a.retryAfter;this.pausedUntil=this.now()+(typeof c=="number"&&c>0?c*1e3:l===429?1e3:5e3),this.now()-this.lastSendWarning>6e4&&(this.lastSendWarning=this.now(),d.warn(`[palbase] request traces were not sent to analytics (${o}); ${e.length} dropped`,{error:a}))}finally{if(clearTimeout(n),this.sending=void 0,this.inFlight=void 0,this.pending.length>0){let a=Math.max(0,this.pausedUntil-this.now());this.schedule(this.pending.length>=this.batchSize?a:Math.max(a,this.flushMs))}}})(),this.sending}};import{createHmac as Ct}from"node:crypto";import{bind as Bt,bunDriver as Ft,createDatabase as Mt,createSearchWorker as It,cutOff as Lt,forgetUser as $t,MigrationOpen as Ut,MigrationRefused as Dt,Migrator as ee,renewingBunPool as Q,VersionNotMigrated as jt}from"palgres";import{toModel as te}from"palgres/dsl";var Nt=["start","complete","rollback","plan","status"],qt=/^(deploy|cli:[^\u0000-\u001f\u007f]{1,200})$/u;function re(t){let e=t.PALBASE_DB_MIGRATE;if(!(e===void 0||e==="")){if(!Nt.includes(e))throw new Error(`[palbase] PALBASE_DB_MIGRATE is start, complete, rollback, plan or status, not ${e}`);return e}}function se(t){let e=Array.isArray(t.schemas)?t.schemas:[t.schemas];for(let r of e)if(r.name===C.name)throw new Error(`[palbase] db.schemas: the ${C.name} schema is the framework's own (its tables are migrated with the app's) \u2014 name the app's schema otherwise`);return[...e,C]}function L(t){return te(se(t))}function Vt(t){return t.tables.some(e=>e.search!==void 0)}function $(t){return t.tables.some(e=>!e.ignored&&e.columns.some(r=>r.user!==void 0&&!r.ignored))}function ne(t){let e=t.PALBASE_DB_CONNECTIONS;if(e===void 0||e==="")return 31;let r=Number(e);if(!Number.isSafeInteger(r)||r<4)throw new Error(`[palbase] PALBASE_DB_CONNECTIONS is how many connections the app may hold to its database, 4 at least (a request's transaction, the two further ones it may hold, one to cancel with) \u2014 not ${e}`);return r}function Wt(t){if(!Number.isSafeInteger(t)||t<3)throw new Error(`[palbase] db.driver: a pool of ${t} connection(s) \u2014 the engine needs at least 3: one request's transaction and the two further ones it may hold`);let e=Math.floor(t/3);return{concurrency:e,nestedConcurrency:e*2}}var X=5;function ae(t,e){if(t.driver)return t.driver;let r=globalThis.Bun;if(!r)throw new Error("[palbase] db.driver: off Bun there is no SQL client built in \u2014 give one: postgres.js with { types: POSTGRES_JS_TYPES }, its engine postgresJsDriver(pool, control)");let s=e-1;return n=>{let a=Q(()=>new r.SQL({url:n,prepare:!1,max:s})),l=Q(()=>new r.SQL({url:n,prepare:!1,max:1}));return{pool:{reserve:()=>a.reserve(),unsafe:(o,c)=>a.unsafe(o,c),begin:o=>a.current.begin(o)},engine:Ft(a,l),poolSize:s,close:async()=>{await a.close({timeout:X}),await l.close({timeout:X})}}}}function oe(t){return t==="rollback"?(d.info("[palbase] migrate rollback: this app declares no database; nothing of it to take back"),M(t,{state:"none"}),0):(d.error(`[palbase] migrate ${t}: this app declares no database \u2014 PalbaseFactory.create(\u2026, { db: { schemas } })`),1)}async function ie(t,e,r){let s=e.PALBASE_DB_OWNER_URL;if(!s)return d.error("[palbase] PALBASE_DB_MIGRATE without PALBASE_DB_OWNER_URL: a migration runs as the tables' owner"),1;let n=e.PALBASE_DB_MIGRATION_BY||"deploy";if(!qt.test(n))return d.error("[palbase] PALBASE_DB_MIGRATION_BY is deploy, or cli:<who>"),1;let a=ae(t,ne(e)),l=a(s),o,c=i=>d.error(`[palbase] migrate ${r}: ${i}`);try{let i=L(t),u=new ee(l.pool,{log:p=>{/ is held by others | held by writers/.test(p)&&(o=p.trim()),d.info(p)},shadow:p=>{let g=new URL(s);g.pathname=`/${p}`;let P=a(g.toString());return{reserve:()=>P.pool.reserve(),end:()=>P.close()}},openedBy:n});if(r==="plan"){let p=await u.plan(i);return M(r,p),p.refusals.length>0?1:0}if(r==="status")return M(r,await u.status()),0;let m=r==="start"?await Kt(u,i,n):r==="complete"?await u.complete():await u.rollback();return d.info(`[palbase] migrate ${r}: done`,{result:m}),M(r,m),0}catch(i){return i instanceof Dt?(d.error(`[palbase] migrate ${r}: refused`,{refusals:i.refusals}),c(`refused \u2014 ${i.refusals.join("; ")}`),1):Lt(i)?(d.error(`[palbase] migrate ${r}: cut off; run again, it goes on from where it stopped`,{error:i}),c(`cut off \u2014 ${o??Z(i)}`),75):(d.error(`[palbase] migrate ${r}: failed`,{error:i}),c(`failed \u2014 ${Z(i)}`),1)}finally{await l.close().catch(()=>{})}}async function Kt(t,e,r){try{return await t.start(e)}catch(s){if(!(s instanceof Ut)||r!=="deploy"||!s.openedBy?.startsWith("cli:"))throw s;return d.warn(`[palbase] migrate start: the migration ${s.openedBy} opened (version ${s.to}) gives way to this release \u2014 rolled back first`),await t.rollback(),await t.start(e)}}function M(t,e){process.stdout.write(`${JSON.stringify({palbase_migrate:t,result:e})}
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{$ as C,A as T,B as Qe,C as Xe,D as Ze,E as et,F as rt,G as st,H as nt,I as at,J as ot,K as it,L as lt,M as ct,N as dt,O as ut,P as pt,Q as ht,R as Y,S as bt,T as mt,U as gt,V as ft,W as yt,X as wt,Y as Pt,Z as St,_ as vt,a as K,aa as kt,b as z,ba as B,c as G,ca as At,d as _e,da as Rt,e as Oe,f as Te,g as Ce,h as Be,i as Fe,j as Me,k as Ie,l as Le,m as $e,n as Ue,o as De,p as je,q as Ne,r as qe,s as Ve,t as We,u as Ke,v as ze,w as Ge,x as He,y as Je,z as Ye}from"../chunks/CJCMQ73A.js";import{b as Et}from"../chunks/CZQ7KIRM.js";import{a as E,b as H,c as J,e as h,f as tt,g as d}from"../chunks/M5B52IE6.js";import{a as j,g as Ee,h as xe,i as q,j as O,q as V,r as W}from"../chunks/PB7UKHCY.js";import"../chunks/4YD2XCGF.js";import{m as Re}from"../chunks/NK54UVDI.js";import"../chunks/IXHR57QC.js";import{b as _}from"../chunks/UXRIXHHY.js";import"../chunks/OKZJIY6F.js";import"../chunks/PRM2UXWG.js";import"reflect-metadata";import{existsSync as er,writeFileSync as tr,writeSync as he}from"node:fs";import{createServer as rr}from"node:http";import{dirname as N,join as sr,resolve as nr}from"node:path";import{Readable as ar}from"node:stream";var xt=2e3,_t=1e4,Ot=/^[A-Za-z0-9_-]{1,64}$/,Tt=512,F=class{linesPerSecond;batchSize;flushMs;maxPending;sendMs;shutdownMs;now;tokens;refilled;unlogged=0;unloggedSince;pending=[];timer;sending;inFlight;pausedUntil=0;lastSendWarning=0;sink;constructor(e,r={}){this.sink=e,this.linesPerSecond=r.linesPerSecond??10,this.batchSize=Math.min(100,r.batchSize??100),this.flushMs=r.flushMs??2e3,this.maxPending=r.maxPending??2e3,this.sendMs=r.sendMs??_t,this.shutdownMs=r.shutdownMs??xt,this.now=r.now??Date.now,this.tokens=this.linesPerSecond,this.refilled=this.now(),this.unloggedSince=this.refilled}record(e){this.log(e),this.sink&&this.trace(e)}async flush(){this.timer&&clearTimeout(this.timer),this.timer=void 0;let e=!1,r,s=new Promise(a=>r=a),n=setTimeout(()=>{e=!0,r()},this.shutdownMs);try{for(;!e&&(this.pending.length>0||this.sending)&&(await Promise.race([this.sending??this.send(),s]),!(this.now()<this.pausedUntil)););}finally{clearTimeout(n)}e&&this.letGo()}letGo(){let e=this.inFlight,r=(e?.traces??0)+this.pending.length;this.pending=[],e&&(e.letGo=!0,e.call.abort(new Error(`analytics did not answer within the ${this.shutdownMs} ms a flush waits`))),r>0&&d.warn(`[palbase] request traces were not sent to analytics within the ${this.shutdownMs} ms a flush waits; ${r} dropped`)}log(e){let r=this.now();if(this.tokens=Math.min(this.linesPerSecond,this.tokens+(r-this.refilled)/1e3*this.linesPerSecond),this.refilled=r,this.unlogged>0&&r-this.unloggedSince>=6e4&&(d.info(`[palbase] ${this.unlogged} more requests answered in the last minute than the log keeps a line for (Analytics \u203A Network has every one)`),this.unlogged=0,this.unloggedSince=r),this.tokens<1){this.unlogged===0&&(this.unloggedSince=r),this.unlogged++;return}this.tokens-=1;let s=e.status>=500?"error":e.status>=400&&e.status!==499?"warn":"info",n=Math.round(e.durationMs*10)/10;d[s](`${e.method} ${e.path} ${e.status} ${n}ms`,{route:e.endpoint,status:e.status,duration_ms:n,...e.userId?{user_id:e.userId}:{}})}trace(e){this.pending.length>=this.maxPending&&this.pending.shift(),this.pending.push({request_id:Ot.test(e.requestId)?e.requestId:e.requestId.replace(/[^A-Za-z0-9_-]/g,"_").slice(0,64)||"unnamed",source:"backend",endpoint:e.endpoint.slice(0,Tt),method:e.method,status:e.status,duration_ms:Math.max(0,Math.round(e.durationMs)),timestamp:this.now(),...e.userId?{distinct_id:e.userId}:{}}),this.pending.length>=this.batchSize&&!this.sending?this.send():!this.timer&&!this.sending&&this.schedule(this.flushMs)}schedule(e){this.timer=setTimeout(()=>{this.send()},e),this.timer.unref?.()}send(){if(this.timer&&clearTimeout(this.timer),this.timer=void 0,this.sending||this.pending.length===0||this.now()<this.pausedUntil||!this.sink)return this.sending??Promise.resolve();let e=this.pending.splice(0,this.batchSize),r=this.sink,s={call:new AbortController,traces:e.length,letGo:!1};this.inFlight=s;let n=setTimeout(()=>s.call.abort(new Error(`analytics did not answer in ${this.sendMs} ms`)),this.sendMs);return n.unref?.(),this.sending=(async()=>{try{await r.sendTraceBatch({body:{traces:e},signal:s.call.signal})}catch(a){if(s.letGo)return;let l=a.status,o=l??(s.call.signal.aborted?`no answer in ${this.sendMs} ms`:"unreachable"),c=a.retryAfter;this.pausedUntil=this.now()+(typeof c=="number"&&c>0?c*1e3:l===429?1e3:5e3),this.now()-this.lastSendWarning>6e4&&(this.lastSendWarning=this.now(),d.warn(`[palbase] request traces were not sent to analytics (${o}); ${e.length} dropped`,{error:a}))}finally{if(clearTimeout(n),this.sending=void 0,this.inFlight=void 0,this.pending.length>0){let a=Math.max(0,this.pausedUntil-this.now());this.schedule(this.pending.length>=this.batchSize?a:Math.max(a,this.flushMs))}}})(),this.sending}};import{createHmac as Ct}from"node:crypto";import{bind as Bt,bunDriver as Ft,createDatabase as Mt,createSearchWorker as It,cutOff as Lt,forgetUser as $t,MigrationOpen as Ut,MigrationRefused as Dt,Migrator as ee,renewingBunPool as Q,VersionNotMigrated as jt}from"palgres";import{toModel as te}from"palgres/dsl";var Nt=["start","complete","rollback","plan","status"],qt=/^(deploy|cli:[^\u0000-\u001f\u007f]{1,200})$/u;function re(t){let e=t.PALBASE_DB_MIGRATE;if(!(e===void 0||e==="")){if(!Nt.includes(e))throw new Error(`[palbase] PALBASE_DB_MIGRATE is start, complete, rollback, plan or status, not ${e}`);return e}}function se(t){let e=Array.isArray(t.schemas)?t.schemas:[t.schemas];for(let r of e)if(r.name===C.name)throw new Error(`[palbase] db.schemas: the ${C.name} schema is the framework's own (its tables are migrated with the app's) \u2014 name the app's schema otherwise`);return[...e,C]}function L(t){return te(se(t))}function Vt(t){return t.tables.some(e=>e.search!==void 0)}function $(t){return t.tables.some(e=>!e.ignored&&e.columns.some(r=>r.user!==void 0&&!r.ignored))}function ne(t){let e=t.PALBASE_DB_CONNECTIONS;if(e===void 0||e==="")return 31;let r=Number(e);if(!Number.isSafeInteger(r)||r<4)throw new Error(`[palbase] PALBASE_DB_CONNECTIONS is how many connections the app may hold to its database, 4 at least (a request's transaction, the two further ones it may hold, one to cancel with) \u2014 not ${e}`);return r}function Wt(t){if(!Number.isSafeInteger(t)||t<3)throw new Error(`[palbase] db.driver: a pool of ${t} connection(s) \u2014 the engine needs at least 3: one request's transaction and the two further ones it may hold`);let e=Math.floor(t/3);return{concurrency:e,nestedConcurrency:e*2}}var X=5;function ae(t,e){if(t.driver)return t.driver;let r=globalThis.Bun;if(!r)throw new Error("[palbase] db.driver: off Bun there is no SQL client built in \u2014 give one: postgres.js with { types: POSTGRES_JS_TYPES }, its engine postgresJsDriver(pool, control)");let s=e-1;return n=>{let a=Q(()=>new r.SQL({url:n,prepare:!1,max:s})),l=Q(()=>new r.SQL({url:n,prepare:!1,max:1}));return{pool:{reserve:()=>a.reserve(),unsafe:(o,c)=>a.unsafe(o,c),begin:o=>a.current.begin(o)},engine:Ft(a,l),poolSize:s,close:async()=>{await a.close({timeout:X}),await l.close({timeout:X})}}}}function oe(t){return t==="rollback"?(d.info("[palbase] migrate rollback: this app declares no database; nothing of it to take back"),M(t,{state:"none"}),0):(d.error(`[palbase] migrate ${t}: this app declares no database \u2014 PalbaseFactory.create(\u2026, { db: { schemas } })`),1)}async function ie(t,e,r){let s=e.PALBASE_DB_OWNER_URL;if(!s)return d.error("[palbase] PALBASE_DB_MIGRATE without PALBASE_DB_OWNER_URL: a migration runs as the tables' owner"),1;let n=e.PALBASE_DB_MIGRATION_BY||"deploy";if(!qt.test(n))return d.error("[palbase] PALBASE_DB_MIGRATION_BY is deploy, or cli:<who>"),1;let a=ae(t,ne(e)),l=a(s),o,c=i=>d.error(`[palbase] migrate ${r}: ${i}`);try{let i=L(t),u=new ee(l.pool,{log:p=>{/ is held by others | held by writers/.test(p)&&(o=p.trim()),d.info(p)},shadow:p=>{let g=new URL(s);g.pathname=`/${p}`;let P=a(g.toString());return{reserve:()=>P.pool.reserve(),end:()=>P.close()}},openedBy:n});if(r==="plan"){let p=await u.plan(i);return M(r,p),p.refusals.length>0?1:0}if(r==="status")return M(r,await u.status()),0;let m=r==="start"?await Kt(u,i,n):r==="complete"?await u.complete():await u.rollback();return d.info(`[palbase] migrate ${r}: done`,{result:m}),M(r,m),0}catch(i){return i instanceof Dt?(d.error(`[palbase] migrate ${r}: refused`,{refusals:i.refusals}),c(`refused \u2014 ${i.refusals.join("; ")}`),1):Lt(i)?(d.error(`[palbase] migrate ${r}: cut off; run again, it goes on from where it stopped`,{error:i}),c(`cut off \u2014 ${o??Z(i)}`),75):(d.error(`[palbase] migrate ${r}: failed`,{error:i}),c(`failed \u2014 ${Z(i)}`),1)}finally{await l.close().catch(()=>{})}}async function Kt(t,e,r){try{return await t.start(e)}catch(s){if(!(s instanceof Ut)||r!=="deploy"||!s.openedBy?.startsWith("cli:"))throw s;return d.warn(`[palbase] migrate start: the migration ${s.openedBy} opened (version ${s.to}) gives way to this release \u2014 rolled back first`),await t.rollback(),await t.start(e)}}function M(t,e){process.stdout.write(`${JSON.stringify({palbase_migrate:t,result:e})}
3
3
  `)}function Z(t){return(t instanceof Error?t.message:String(t)).split(`
4
4
  `)[0].slice(0,300)||(t instanceof Error?t.name:"unknown")}async function zt(t,e){try{return await new ee(t).plan(e)}catch{return}}var I=class extends Error{digest;plan;constructor(e,r){super([`[palbase] this schema (${e}) has no version in the database yet: palbase db:push tries it there (a database of your own: palbase db:push --url <its address>)`,...r?Gt(r):[" palbase db:plan says what it would change"]].join(`
5
5
  `)),this.name="SchemaNotPushed",this.digest=e,this.plan=r}};function Gt(t){let e=[t.adoption?` takes the database over as version 1${t.to>1?`, then version 1 \u2192 ${t.to}`:""}`:` version ${t.from??"none"} \u2192 ${t.to}`];t.changes.length===0&&t.refusals.length===0&&e.push(" nothing to change");for(let r of t.changes)e.push(` + ${r}`);for(let r of t.refusals)e.push(` \u2717 ${r}`);return e}async function le(t,e,r,s){let n=t.url??e.PALBASE_DB_URL;if(!n)throw new Error("[palbase] db.url / PALBASE_DB_URL is the database the app connects to");let a=se(t),l=te(a),o=ae(t,ne(e))(n);try{let c=await Bt(o.engine,l,{waitMs:s.onPlatform?6e4:0}).catch(async g=>{throw s.onPlatform||!(g instanceof jt)?g:new I(g.digest,await zt(o.pool,l))}),i=Ct("sha256",r).update("palgres page cursor").digest("hex"),u=t.embed??s.embed,m=await Mt({sql:o.engine,schemas:a,binding:c,cursorSecret:i,admission:Wt(o.poolSize),embed:u,log:g=>d.warn(`[palbase] ${g}`)}),p=Vt(l)?It({sql:o.engine,embed:u,log:g=>d.info(`[palbase] ${g}`)}):void 0;return{model:l,binding:c,app:m,requests:t.requests??"caller",forget:g=>$t(o.engine,c,l,g),...p?{search:p}:{},close:()=>o.close()}}catch(c){throw await o.close(),c}}function Ht(t){let e=Buffer.from(t,"base64"),r=new Array(e.byteLength/4);for(let s=0;s<r.length;s++)r[s]=e.readFloatLE(s*4);return r}function ce(t){return async({texts:e,model:r,dimensions:s})=>{let{data:n}=await t.ai.createEmbeddings({body:{input:e,model:r,dimensions:s}});return{model:n.model,vectors:n.vectors.map(Ht)}}}var Jt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function de(t,e,r){let s=[],n=t.url??e.PALBASE_URL??"",a="";try{let u=new URL(n);a=u.origin,u.protocol!=="https:"&&u.hostname!=="localhost"&&u.hostname!=="127.0.0.1"&&s.push("palbase.url / PALBASE_URL is https://<ref>.<domain>"),(u.pathname!=="/"||u.search||u.hash)&&s.push("palbase.url / PALBASE_URL is the project origin alone")}catch{s.push("palbase.url / PALBASE_URL is the project address, https://<ref>.<domain>")}let l=t.projectId??e.PALBASE_PROJECT_ID??"";Jt.test(l)||s.push("palbase.projectId / PALBASE_PROJECT_ID is the project id (a UUID)");let o=t.secretKey??e.PALBASE_SECRET_KEY??"";/^pb_[a-z0-9]+_s/.test(o)||s.push("palbase.secretKey / PALBASE_SECRET_KEY is the project secret key (pb_<ref>_s\u2026), kept in the project's Secrets");let c=(t.platformSecret??e.PALBASE_PLATFORM_SECRET)||void 0;c!==void 0&&!/^[0-9a-f]{64}$/.test(c)&&s.push("palbase.platformSecret / PALBASE_PLATFORM_SECRET is the key the platform signs its calls to this machine with (64 hex characters): the platform sets it, unset off the platform");let i=(t.webhookSecret??e.PALBASE_WEBHOOK_SECRET)||void 0;if(r.needsWebhookSecret&&(c!==void 0||i!==void 0)&&!/^whsec_[0-9a-f]{64}$/.test(i??"")&&s.push("palbase.webhookSecret / PALBASE_WEBHOOK_SECRET is the project's webhook endpoint secret (whsec_\u2026): the platform delivers this app events \u2014 its @On handlers', or user.deleted for the users its tables keep"),s.length>0)throw new Error(`[palbase] the app cannot start:
@@ -9,4 +9,4 @@ ${s.join(`
9
9
  `)}
10
10
  `}var be=2e4,me=5e3,or=15e3,ir="/_palbase/health";function lr(t){let e=new Set,r=s=>{if(e.has(s))return!1;e.add(s);let n=T(s,K);return n?n.providers.some(a=>T(a,z)!==void 0&&T(a,G)===void 0)||n.imports.some(r):!1};return t.some(r)}var cr={async create(t,e={}){let r=Array.isArray(t)?t:[t],s=e.env??process.env,n=re(s);if(n!==void 0){let y=e.db?await ie(e.db,s,n):oe(n);throw process.exit(y),new U(y)}let a=s.PALBASE_CONTRACT_OUT;if(a){let y;try{y=await dr(r,e,s)}catch(S){throw he(2,`[palbase] the contract: ${S instanceof Error?S.message:String(S)}
11
11
  `),process.exit(1),new x}throw a==="/dev/stdout"?he(1,pe(y)):tr(a,`${y}
12
- `),process.exit(0),new x}let l=e.db?L(e.db):void 0,o=await W({env:s,url:e.palbase?.url,secretKey:e.palbase?.secretKey});o&&d.info(`[palbase] secrets: ${o.loaded.length} from the project's ${o.set} set${o.kept.length>0?`; ${o.kept.join(", ")} kept as the environment gives them`:""}`),o&&o.refused.length>0&&d.warn(`[palbase] secrets not set \u2014 names a process reads as its own, not the app's: ${o.refused.map(y=>JSON.stringify(y)).join(", ")}`);let c=lr(r)||l!==void 0&&$(l),i=de(e.palbase??{},s,{needsWebhookSecret:c});c&&i.webhookSecret===void 0&&d.warn("[palbase] events: none is delivered here \u2014 the platform delivers them to the app's machine, not to this computer; its @On handlers (and forgetting a deleted user's rows) run there. Set PALBASE_WEBHOOK_SECRET to take a delivery forwarded here");let u=j({url:i.url,secretKey:i.secretKey}),m=e.port??Number(s.PORT??"8080");if(!Number.isInteger(m)||m<0||m>65535)throw new Error(`[palbase] PORT is a port number, not ${String(e.port??s.PORT)}`);let p=e.db?await le(e.db,s,i.secretKey,{onPlatform:i.platformSecret!==void 0,embed:ce(u)}):void 0;p&&d.info(`[palbase] database: version ${p.binding.version}`);let g=p&&$(p.model)?{"user.deleted":[y=>ur(p,y)]}:void 0,P=i.platformSecret===void 0?void 0:{secret:i.platformSecret},v=e.requestTelemetry===!1?void 0:new F(u.analytics),b=()=>B({modules:r,verifier:new O({issuer:i.url,projectId:i.projectId,standing:q({url:i.url,secretKey:i.secretKey})}),server:u,webhookSecret:i.webhookSecret,env:s,projectId:i.projectId,telemetry:v,auth:e.auth,tokens:e.tokens,rateLimit:e.rateLimit,maxBodyBytes:e.bodyLimit,cors:e.cors,platform:P,events:g,database:p&&{app:p.app,requests:p.requests}}),f=b(),A=e.boot?.attempts??5,R=e.boot?.backoffMs??1e3;for(let y=1;;y++)try{await f.start();break}catch(S){if(y>=A)throw d.error(`[palbase] the app did not start after ${A} attempts`,{error:S}),S;d.warn(`[palbase] the app did not start (attempt ${y} of ${A}); trying again in ${R} ms`,{error:S}),await new Promise(Ae=>setTimeout(Ae,R)),R*=2,f=b()}return pr(f,u,m,e.host??"0.0.0.0",e.exitOnFatal??!0,p)}};async function dr(t,e,r){let s=nr(r.PALBASE_CONTRACT_ENTRY??process.argv[1]??"");if(!/\.[cm]?tsx?$/.test(s))throw new Error(`the contract is read from the app's TypeScript source, and this run's entry is ${s||"none"}: start it from its source (bun run src/main.ts), or name the source's entry in PALBASE_CONTRACT_ENTRY`);let n=N(s);for(;!er(sr(n,"package.json"))&&N(n)!==n;)n=N(n);let{analyzeProject:a}=await import("../chunks/JF7KZUPL.js"),{routeContracts:l}=await import("../chunks/NTMO2LFH.js"),o=a(n,s);for(let u of o.warnings)d.warn(`[palbase] the contract: ${u}`);let c="https://contract.palbase.invalid",i=B({modules:t,verifier:new O({issuer:c,projectId:"contract",standing:()=>Promise.reject(new Error("the contract run serves nothing"))}),server:j({url:c,secretKey:"pb_contract_s"}),env:r,projectId:"contract",auth:e.auth,tokens:e.tokens,rateLimit:e.rateLimit,maxBodyBytes:e.bodyLimit,cors:e.cors,contractOnly:{database:e.db!==void 0,routes:await l(o.routes),errors:Y()},events:e.db&&$(L(e.db))?{"user.deleted":[]}:void 0});return JSON.stringify(i.contract(),null,2)}var x=class extends Error{constructor(){super("[palbase] the contract run ended"),this.name="ContractRunEnded"}},U=class extends Error{code;constructor(e){super(`[palbase] the migration run ended with ${e}`),this.name="MigrationRunEnded",this.code=e}};async function ur(t,e){let r=e.data?.user_id;if(typeof r!="string"||r==="")throw new Error("[palbase] user.deleted without a user_id");let s=await t.forget(r);d.info(`[palbase] user ${r} deleted: ${s.deleted} row(s) gone, ${s.detached} forgot them`)}async function pr(t,e,r,s,n,a){let l,o={on:!1},c=(b,f)=>new URL(b.url).pathname===ir&&b.method==="GET"?Promise.resolve(o.on?Response.json({ok:!1,stopping:!0},{status:503}):Response.json({ok:!0})):t.handle(b,f),i=rr((b,f)=>{hr(c,b,f,o).finally(()=>{o.on&&i.closeIdleConnections()})});i.keepAliveTimeout=29e4,i.headersTimeout=3e5;try{await new Promise((b,f)=>{i.once("error",f),i.listen(r,s,()=>b())})}catch(b){throw await t.stop(),await a?.close(),b}let u=i.address().port;d.info(`[palbase] serving ${t.routes.length} route(s) on :${u}`,{routes:t.routes}),a?.search?.start();let m=b=>l??=(async()=>{d.info("[palbase] stopping: finishing the requests in flight"),o.on=!0;let f=new Promise(R=>i.close(()=>R()));i.closeIdleConnections();let A=setTimeout(()=>i.closeAllConnections(),b);await f,clearTimeout(A),process.off("SIGINT",P),process.off("uncaughtException",v),process.off("unhandledRejection",v);try{await t.stop(),await a?.search?.stop(),await a?.close()}finally{process.off("SIGTERM",P)}})(),p=()=>m(be),g=!1,P=()=>{if(g){d.info("[palbase] stopping: told to stop again; the requests in flight are still being finished");return}g=!0;let b=setTimeout(()=>{d.error("[palbase] stopping took longer than it is given; the process ends"),process.exit(1)},be+or);b.unref(),p().then(()=>{clearTimeout(b),process.exit(0)},f=>{clearTimeout(b),d.error("[palbase] stopping failed; the process ends",{error:f}),process.exit(1)})},v=b=>{d.error("[palbase] the app crashed; stopping so the machine starts it again",{error:b});let f=setTimeout(()=>process.exit(1),me+1e3);m(me).finally(()=>{clearTimeout(f),process.exit(1)})};return process.on("SIGTERM",P),process.once("SIGINT",P),n&&(process.on("uncaughtException",v),process.on("unhandledRejection",v)),{routes:t.routes,palbase:e,port:u,handle:c,close:p}}async function hr(t,e,r,s){try{let n=e.url??"/",a;try{if(!n.startsWith("/"))throw new TypeError("the request target is not a path");a=new URL(`http://localhost${n}`)}catch{r.statusCode=400,r.end();return}let l=new Headers;for(let[m,p]of Object.entries(e.headers))if(p!==void 0)if(Array.isArray(p))for(let g of p)l.append(m,g);else l.set(m,p);let o=e.method!=="GET"&&e.method!=="HEAD",c=new AbortController;r.on("close",()=>{r.writableFinished||c.abort(new Error("the client closed the connection"))});let i=new Request(a,{method:e.method,headers:l,body:o?ar.toWeb(e):void 0,duplex:"half",signal:c.signal}),u=await t(i,{remoteAddress:e.socket.remoteAddress});if(r.statusCode=u.status,u.headers.forEach((m,p)=>r.setHeader(p,m)),s.on&&r.setHeader("connection","close"),u.body)for await(let m of u.body)r.write(m);r.end()}catch(n){d.error("[palbase] the request could not be answered",{error:n}),r.headersSent||(r.statusCode=500),r.end()}}import{bigint as gs,boolean as fs,check as ys,date as ws,defineSchema as Ps,defineTable as Ss,enumType as vs,foreignKey as ks,index as As,integer as Rs,jsonb as Es,numeric as xs,ownedByUser as _s,policy as Os,raw as Ts,sqlType as Cs,text as Bs,timestamp as Fs,userRef as Ms,uuid as Is}from"palgres/dsl";import{increment as $s,now as Us}from"palgres";function k(t){if(t instanceof _)return{data:null,error:{code:t.code,message:t.message},status:t.status};throw t}async function w(t,e){try{let r=await t();return{data:await e(r.data),error:null,status:r.status}}catch(r){return k(r)}}var br=E("Secrets",{async get(t){if(V(t))return null;let e=process.env[t];return typeof e=="string"&&e!==""?e:null}}),mr=100,gr=1e3,fr=168*3600,yr={s:1,m:60,h:3600,d:86400};function wr(t){let e=String(t).trim();if(!/^(\d+(\.\d+)?[dhms])+$/.test(e))return;let r=0;for(let[,s,,n]of e.matchAll(/(\d+(\.\d+)?)([dhms])/g))r+=Math.round(Number(s)*yr[n]*1e3);return Math.ceil(r/1e3)}function ve(t,e,r){let s=`${h.url}/storage/public/${encodeURIComponent(t)}/${encodeURIComponent(e)}`;return r?`${s}?variant=${encodeURIComponent(r)}`:s}function ge(t){return{path:t.path,name:t.path,bucket:t.bucket,size:t.size,contentType:t.content_type,checksum:t.checksum_sha256,...t.width!==void 0?{width:t.width}:{},...t.height!==void 0?{height:t.height}:{},...t.thumbhash!==void 0?{thumbhash:t.thumbhash}:{},variants:Object.fromEntries(Object.keys(t.variants??{}).map(e=>[e,ve(t.bucket,t.path,e)]))}}function Pr(t){return{async upload(e,r,s){let n=s?.contentType??(r instanceof Blob&&r.type!==""?r.type:void 0);try{let a=await h.storage.putObject({path:{bucket:t,path:e},headers:s?.upsert?void 0:{"If-None-Match":"*"},body:r,contentType:n});return{data:ge(a.data),error:null,status:a.status}}catch(a){return a instanceof _&&a.status===412&&a.code==="object_exists"?{data:null,error:{code:"already_exists",message:"An object already exists at that path: upload with { upsert: true } to replace it"},status:409}:k(a)}},async download(e){try{let r=await h.storage.getObject({path:{bucket:t,path:e}});if(r.status===304)throw new Error("storage answered 304 to a read that sent no entity tag");let s=r.data;try{return{data:await s.blob(),error:null,status:r.status}}catch(n){return{data:null,error:{code:"network_error",message:`the object's bytes stopped arriving: ${n instanceof Error?n.message:String(n)}`},status:0}}}catch(r){return k(r)}},getPublicUrl(e,r){return ve(t,e,r?.variant)},async createSignedUrl(e,r){let s=wr(r?.expiresIn);return s===void 0||s<1||s>fr?{data:null,error:{code:"bad_request",message:`expiresIn is a duration from 1s to 7d, like "15m", "1h" or "7d" (got ${JSON.stringify(r?.expiresIn)})`},status:400}:w(()=>h.storage.createSignedUrl({path:{bucket:t},body:{path:e,expires_in:s}}),n=>({signedUrl:n.url,expiresAt:n.expires_at}))},async list(e,r){let s=r?.limit??mr,n=r?.offset??0;if(!Number.isInteger(s)||s<0||!Number.isInteger(n)||n<0)return{data:null,error:{code:"bad_request",message:"limit and offset are whole numbers, 0 or more"},status:400};let a=[],l,o=200;try{for(;a.length<s;){let c=Math.max(1,Math.min(gr,n+s-a.length)),i=await h.storage.listObjects({path:{bucket:t},query:{...e?{prefix:e}:{},limit:c,...l?{cursor:l}:{}}});o=i.status;for(let u of i.data.objects)n>0?n--:a.length<s&&a.push(ge(u));if(l=i.data.next_cursor,!l)break}}catch(c){return k(c)}return{data:a,error:null,status:o}},async remove(e){let r=[];for(let s of e){try{await h.storage.deleteObject({path:{bucket:t,path:s}})}catch(n){return k(n)}r.push({path:s,name:s,bucket:t,size:0,contentType:"",checksum:"",variants:{}})}return{data:r,error:null,status:200}},move(e,r){return w(()=>h.storage.moveObject({path:{bucket:t},body:{from:e,to:r}}),()=>{})},copy(e,r){return w(()=>h.storage.copyObject({path:{bucket:t},body:{from:e,to:r}}),()=>{})}}}var Sr={bucket:Pr},fe=t=>H("Storage",t,Sr),vr={bucket:t=>fe("bucket").bucket(t),buckets:new Proxy({},{get:(t,e)=>typeof e=="string"?fe("buckets").bucket(e):void 0})},kr=E("Notifications",{push:{send(t){let{to:e,...r}=t,s=typeof e=="string"?{user_ids:[e]}:Array.isArray(e)?{user_ids:e}:{topic:e.topic};return w(()=>h.notify.sendPush({body:{...r,to:s}}),n=>({message_ids:n.message_ids,recipients:n.message_ids.length,skipped_user_ids:n.skipped_user_ids}))}},email:{async send(t){let{to:e,templateSlug:r,...s}=t,n={...s,...r!==void 0?{template:r}:{}};if(!Array.isArray(e))return w(()=>h.notify.sendEmail({body:{...n,to:e}}),o=>({...o.message_id!==void 0?{message_id:o.message_id}:{},...o.skipped?{skipped:!0}:{}}));let a=[],l=202;for(let o of e)try{let c=await h.notify.sendEmail({body:{...n,to:o}});l=c.status,a.push(c.data.message_id??null)}catch(c){return k(c)}return{data:{message_ids:a},error:null,status:l}}}}),ye=t=>typeof t=="boolean"?t:t!=null&&t!==0&&t!=="",we=t=>typeof t=="string"?{name:t}:null,Pe=t=>t==="override"?"user":"system",Ar=t=>t!==null&&typeof t=="object"&&!Array.isArray(t)&&("userId"in t||"properties"in t);function ke(){return J.getStore()?.userId}function D(t){let e=t&&"userId"in t?t.userId??void 0:ke();return w(()=>e?h.flags.getUserValues({path:{user_id:e}}):h.flags.getValues(),r=>r.values??{})}var Se={setOverrideForUser:(t,e,r)=>w(()=>h.flags.putUserValue({path:{user_id:t,key:e},body:{value:r}}),s=>({key:s.key,value:s.value,source:Pe(s.source)})),setOverridesForUser:(t,e)=>w(()=>h.flags.putUserValues({path:{user_id:t},body:{values:e}}),r=>({values:r.values??{}})),clearOverrideForUser:(t,e)=>w(()=>h.flags.deleteUserValue({path:{user_id:t,key:e}}),r=>({key:r.key,value:r.value,source:Pe(r.source)})),clearAllOverridesForUser:t=>w(()=>h.flags.deleteUserValues({path:{user_id:t}}),e=>({deleted:e.deleted})),batchSetOverrides:t=>w(()=>h.flags.batchUserValues({body:{operations:t.map(e=>({user_id:e.userId,values:e.values}))}}),e=>({applied:e.applied}))},Rr=E("Flags",{async isEnabled(t,e){let r=s=>(d.warn(`[palbase] flag "${t}" could not be read (${s}): treating it as off`),!1);try{let s=await D(e);return s.error?r(`${s.error.code}: ${s.error.message}`):ye(s.data[t])}catch(s){return r(s instanceof Error?s.message:String(s))}},async getVariant(t,e){let r=await D(e);return r.error?{data:null,error:r.error,status:r.status}:{data:we(r.data[t]),error:null,status:r.status}},async getAll(t){let e=await D(t);return e.error?{data:null,error:e.error,status:e.status}:{data:Object.entries(e.data).map(([r,s])=>{let n=we(s);return{name:r,enabled:ye(s),...n?{variant:n}:{}}}),error:null,status:e.status}},async get(t,e,r){let s,n=!1,a;r!==void 0?(s=e,n=!0,a=r):Ar(e)?a=e:e!==void 0&&(s=e,n=!0);let l=await D(a);if(l.error)return n?{data:s??null,error:null,status:l.status}:{data:null,error:l.error,status:l.status};let o=l.data[t];return{data:o===void 0?s??null:o,error:null,status:l.status}},async setOverride(t,e){let r=ke();return r?Se.setOverrideForUser(r,t,e):{data:null,error:{code:"no_user",message:"Flags.setOverride writes the signed-in user's value: this request has none \u2014 Flags.$asService().setOverrideForUser(userId, key, value) writes anyone's"},status:400}},$asService(){return Se}}),Er=E("Realtime",{broadcast(t,e,r){return w(()=>h.realtime.broadcast({body:{messages:[{topic:t,event:e,payload:r??{}}]}}),()=>{})},state:{set(t,e,r){return w(()=>h.realtime.writeState({body:{ops:[{topic:t,key:e,value:r}]}}),()=>{})},clear(t,e){return w(()=>h.realtime.writeState({body:{ops:[{topic:t,key:e,delete:!0}]}}),()=>{})}}});import{z as zs}from"zod";export{xe as AuthUnavailable,mt as BadRequest,Ie as Body,At as CACHE_MAX_TTL,Rt as Cache,We as Client,gt as Conflict,x as ContractRunEnded,_e as Controller,tt as Database,ft as DeadlockDetected,Fe as Delete,dt as DiError,Re as EVENT_TYPES,Rr as Flags,ht as Forbidden,Oe as Get,$e as Headers,yt as HttpError,ze as Injectable,Je as Job,d as Log,kt as MAX_BODY_BYTES,U as MigrationRunEnded,Ge as Module,wt as NotFound,kr as Notifications,He as On,st as OnAuthorize,it as OnEmpty,nt as OnFirst,at as OnJoin,ot as OnLeave,lt as OnMessage,je as OptionalUser,ut as PalError,h as Palbase,_ as PalbaseError,cr as PalbaseFactory,Ue as Param,Be as Patch,Te as Post,Ce as Put,Me as Query,Le as QueryParams,Er as Realtime,Ne as Req,qe as RequestId,Ke as Resolve,rt as Room,I as SchemaNotPushed,br as Secrets,Pt as SerializationFailure,vr as Storage,Ee as TokenError,O as TokenVerifier,St as TooManyRequests,Ve as TraceId,pt as Unauthorized,vt as UniqueViolation,Ze as Upload,et as UploadedObject,De as User,Ye as Webhook,gs as bigint,fs as boolean,ys as check,B as createApp,ws as date,bt as defineError,Ps as defineSchema,Ss as defineTable,vs as enumType,ks as foreignKey,Qe as getRegisteredControllers,Xe as getRoutes,ct as getWebhookManifest,$s as increment,As as index,Rs as integer,Es as jsonb,Us as now,xs as numeric,_s as ownedByUser,Os as policy,Ts as raw,Cs as sqlType,Et as t,Bs as text,Fs as timestamp,Ms as userRef,Is as uuid,zs as z};
12
+ `),process.exit(0),new x}let l=e.db?L(e.db):void 0,o=await W({env:s,url:e.palbase?.url,secretKey:e.palbase?.secretKey});o&&d.info(`[palbase] secrets: ${o.loaded.length} from the project's ${o.set} set${o.kept.length>0?`; ${o.kept.join(", ")} kept as the environment gives them`:""}`),o&&o.refused.length>0&&d.warn(`[palbase] secrets not set \u2014 names a process reads as its own, not the app's: ${o.refused.map(y=>JSON.stringify(y)).join(", ")}`);let c=lr(r)||l!==void 0&&$(l),i=de(e.palbase??{},s,{needsWebhookSecret:c});c&&i.webhookSecret===void 0&&d.warn("[palbase] events: none is delivered here \u2014 the platform delivers them to the app's machine, not to this computer; its @On handlers (and forgetting a deleted user's rows) run there. Set PALBASE_WEBHOOK_SECRET to take a delivery forwarded here");let u=j({url:i.url,secretKey:i.secretKey}),m=e.port??Number(s.PORT??"8080");if(!Number.isInteger(m)||m<0||m>65535)throw new Error(`[palbase] PORT is a port number, not ${String(e.port??s.PORT)}`);let p=e.db?await le(e.db,s,i.secretKey,{onPlatform:i.platformSecret!==void 0,embed:ce(u)}):void 0;p&&d.info(`[palbase] database: version ${p.binding.version}`);let g=p&&$(p.model)?{"user.deleted":[y=>ur(p,y)]}:void 0,P=i.platformSecret===void 0?void 0:{secret:i.platformSecret},v=e.requestTelemetry===!1?void 0:new F(u.analytics),b=()=>B({modules:r,verifier:new O({issuer:i.url,projectId:i.projectId,standing:q({url:i.url,secretKey:i.secretKey})}),server:u,webhookSecret:i.webhookSecret,env:s,projectId:i.projectId,telemetry:v,auth:e.auth,tokens:e.tokens,rateLimit:e.rateLimit,maxBodyBytes:e.bodyLimit,cors:e.cors,platform:P,events:g,database:p&&{app:p.app,requests:p.requests}}),f=b(),A=e.boot?.attempts??5,R=e.boot?.backoffMs??1e3;for(let y=1;;y++)try{await f.start();break}catch(S){if(y>=A)throw d.error(`[palbase] the app did not start after ${A} attempts`,{error:S}),S;d.warn(`[palbase] the app did not start (attempt ${y} of ${A}); trying again in ${R} ms`,{error:S}),await new Promise(Ae=>setTimeout(Ae,R)),R*=2,f=b()}return pr(f,u,m,e.host??"0.0.0.0",e.exitOnFatal??!0,p)}};async function dr(t,e,r){let s=nr(r.PALBASE_CONTRACT_ENTRY??process.argv[1]??"");if(!/\.[cm]?tsx?$/.test(s))throw new Error(`the contract is read from the app's TypeScript source, and this run's entry is ${s||"none"}: start it from its source (bun run src/main.ts), or name the source's entry in PALBASE_CONTRACT_ENTRY`);let n=N(s);for(;!er(sr(n,"package.json"))&&N(n)!==n;)n=N(n);let{analyzeProject:a}=await import("../chunks/P5JIZEPB.js"),{routeContracts:l}=await import("../chunks/47V66C2X.js"),o=a(n,s);for(let u of o.warnings)d.warn(`[palbase] the contract: ${u}`);let c="https://contract.palbase.invalid",i=B({modules:t,verifier:new O({issuer:c,projectId:"contract",standing:()=>Promise.reject(new Error("the contract run serves nothing"))}),server:j({url:c,secretKey:"pb_contract_s"}),env:r,projectId:"contract",auth:e.auth,tokens:e.tokens,rateLimit:e.rateLimit,maxBodyBytes:e.bodyLimit,cors:e.cors,contractOnly:{database:e.db!==void 0,routes:await l(o.routes),errors:Y()},events:e.db&&$(L(e.db))?{"user.deleted":[]}:void 0});return JSON.stringify(i.contract(),null,2)}var x=class extends Error{constructor(){super("[palbase] the contract run ended"),this.name="ContractRunEnded"}},U=class extends Error{code;constructor(e){super(`[palbase] the migration run ended with ${e}`),this.name="MigrationRunEnded",this.code=e}};async function ur(t,e){let r=e.data?.user_id;if(typeof r!="string"||r==="")throw new Error("[palbase] user.deleted without a user_id");let s=await t.forget(r);d.info(`[palbase] user ${r} deleted: ${s.deleted} row(s) gone, ${s.detached} forgot them`)}async function pr(t,e,r,s,n,a){let l,o={on:!1},c=(b,f)=>new URL(b.url).pathname===ir&&b.method==="GET"?Promise.resolve(o.on?Response.json({ok:!1,stopping:!0},{status:503}):Response.json({ok:!0})):t.handle(b,f),i=rr((b,f)=>{hr(c,b,f,o).finally(()=>{o.on&&i.closeIdleConnections()})});i.keepAliveTimeout=29e4,i.headersTimeout=3e5;try{await new Promise((b,f)=>{i.once("error",f),i.listen(r,s,()=>b())})}catch(b){throw await t.stop(),await a?.close(),b}let u=i.address().port;d.info(`[palbase] serving ${t.routes.length} route(s) on :${u}`,{routes:t.routes}),a?.search?.start();let m=b=>l??=(async()=>{d.info("[palbase] stopping: finishing the requests in flight"),o.on=!0;let f=new Promise(R=>i.close(()=>R()));i.closeIdleConnections();let A=setTimeout(()=>i.closeAllConnections(),b);await f,clearTimeout(A),process.off("SIGINT",P),process.off("uncaughtException",v),process.off("unhandledRejection",v);try{await t.stop(),await a?.search?.stop(),await a?.close()}finally{process.off("SIGTERM",P)}})(),p=()=>m(be),g=!1,P=()=>{if(g){d.info("[palbase] stopping: told to stop again; the requests in flight are still being finished");return}g=!0;let b=setTimeout(()=>{d.error("[palbase] stopping took longer than it is given; the process ends"),process.exit(1)},be+or);b.unref(),p().then(()=>{clearTimeout(b),process.exit(0)},f=>{clearTimeout(b),d.error("[palbase] stopping failed; the process ends",{error:f}),process.exit(1)})},v=b=>{d.error("[palbase] the app crashed; stopping so the machine starts it again",{error:b});let f=setTimeout(()=>process.exit(1),me+1e3);m(me).finally(()=>{clearTimeout(f),process.exit(1)})};return process.on("SIGTERM",P),process.once("SIGINT",P),n&&(process.on("uncaughtException",v),process.on("unhandledRejection",v)),{routes:t.routes,palbase:e,port:u,handle:c,close:p}}async function hr(t,e,r,s){try{let n=e.url??"/",a;try{if(!n.startsWith("/"))throw new TypeError("the request target is not a path");a=new URL(`http://localhost${n}`)}catch{r.statusCode=400,r.end();return}let l=new Headers;for(let[m,p]of Object.entries(e.headers))if(p!==void 0)if(Array.isArray(p))for(let g of p)l.append(m,g);else l.set(m,p);let o=e.method!=="GET"&&e.method!=="HEAD",c=new AbortController;r.on("close",()=>{r.writableFinished||c.abort(new Error("the client closed the connection"))});let i=new Request(a,{method:e.method,headers:l,body:o?ar.toWeb(e):void 0,duplex:"half",signal:c.signal}),u=await t(i,{remoteAddress:e.socket.remoteAddress});if(r.statusCode=u.status,u.headers.forEach((m,p)=>r.setHeader(p,m)),s.on&&r.setHeader("connection","close"),u.body)for await(let m of u.body)r.write(m);r.end()}catch(n){d.error("[palbase] the request could not be answered",{error:n}),r.headersSent||(r.statusCode=500),r.end()}}import{bigint as gs,boolean as fs,check as ys,date as ws,defineSchema as Ps,defineTable as Ss,enumType as vs,foreignKey as ks,index as As,integer as Rs,jsonb as Es,numeric as xs,ownedByUser as _s,policy as Os,raw as Ts,sqlType as Cs,text as Bs,timestamp as Fs,userRef as Ms,uuid as Is}from"palgres/dsl";import{increment as $s,now as Us}from"palgres";function k(t){if(t instanceof _)return{data:null,error:{code:t.code,message:t.message},status:t.status};throw t}async function w(t,e){try{let r=await t();return{data:await e(r.data),error:null,status:r.status}}catch(r){return k(r)}}var br=E("Secrets",{async get(t){if(V(t))return null;let e=process.env[t];return typeof e=="string"&&e!==""?e:null}}),mr=100,gr=1e3,fr=168*3600,yr={s:1,m:60,h:3600,d:86400};function wr(t){let e=String(t).trim();if(!/^(\d+(\.\d+)?[dhms])+$/.test(e))return;let r=0;for(let[,s,,n]of e.matchAll(/(\d+(\.\d+)?)([dhms])/g))r+=Math.round(Number(s)*yr[n]*1e3);return Math.ceil(r/1e3)}function ve(t,e,r){let s=`${h.url}/storage/public/${encodeURIComponent(t)}/${encodeURIComponent(e)}`;return r?`${s}?variant=${encodeURIComponent(r)}`:s}function ge(t){return{path:t.path,name:t.path,bucket:t.bucket,size:t.size,contentType:t.content_type,checksum:t.checksum_sha256,...t.width!==void 0?{width:t.width}:{},...t.height!==void 0?{height:t.height}:{},...t.thumbhash!==void 0?{thumbhash:t.thumbhash}:{},variants:Object.fromEntries(Object.keys(t.variants??{}).map(e=>[e,ve(t.bucket,t.path,e)]))}}function Pr(t){return{async upload(e,r,s){let n=s?.contentType??(r instanceof Blob&&r.type!==""?r.type:void 0);try{let a=await h.storage.putObject({path:{bucket:t,path:e},headers:s?.upsert?void 0:{"If-None-Match":"*"},body:r,contentType:n});return{data:ge(a.data),error:null,status:a.status}}catch(a){return a instanceof _&&a.status===412&&a.code==="object_exists"?{data:null,error:{code:"already_exists",message:"An object already exists at that path: upload with { upsert: true } to replace it"},status:409}:k(a)}},async download(e){try{let r=await h.storage.getObject({path:{bucket:t,path:e}});if(r.status===304)throw new Error("storage answered 304 to a read that sent no entity tag");let s=r.data;try{return{data:await s.blob(),error:null,status:r.status}}catch(n){return{data:null,error:{code:"network_error",message:`the object's bytes stopped arriving: ${n instanceof Error?n.message:String(n)}`},status:0}}}catch(r){return k(r)}},getPublicUrl(e,r){return ve(t,e,r?.variant)},async createSignedUrl(e,r){let s=wr(r?.expiresIn);return s===void 0||s<1||s>fr?{data:null,error:{code:"bad_request",message:`expiresIn is a duration from 1s to 7d, like "15m", "1h" or "7d" (got ${JSON.stringify(r?.expiresIn)})`},status:400}:w(()=>h.storage.createSignedUrl({path:{bucket:t},body:{path:e,expires_in:s}}),n=>({signedUrl:n.url,expiresAt:n.expires_at}))},async list(e,r){let s=r?.limit??mr,n=r?.offset??0;if(!Number.isInteger(s)||s<0||!Number.isInteger(n)||n<0)return{data:null,error:{code:"bad_request",message:"limit and offset are whole numbers, 0 or more"},status:400};let a=[],l,o=200;try{for(;a.length<s;){let c=Math.max(1,Math.min(gr,n+s-a.length)),i=await h.storage.listObjects({path:{bucket:t},query:{...e?{prefix:e}:{},limit:c,...l?{cursor:l}:{}}});o=i.status;for(let u of i.data.objects)n>0?n--:a.length<s&&a.push(ge(u));if(l=i.data.next_cursor,!l)break}}catch(c){return k(c)}return{data:a,error:null,status:o}},async remove(e){let r=[];for(let s of e){try{await h.storage.deleteObject({path:{bucket:t,path:s}})}catch(n){return k(n)}r.push({path:s,name:s,bucket:t,size:0,contentType:"",checksum:"",variants:{}})}return{data:r,error:null,status:200}},move(e,r){return w(()=>h.storage.moveObject({path:{bucket:t},body:{from:e,to:r}}),()=>{})},copy(e,r){return w(()=>h.storage.copyObject({path:{bucket:t},body:{from:e,to:r}}),()=>{})}}}var Sr={bucket:Pr},fe=t=>H("Storage",t,Sr),vr={bucket:t=>fe("bucket").bucket(t),buckets:new Proxy({},{get:(t,e)=>typeof e=="string"?fe("buckets").bucket(e):void 0})},kr=E("Notifications",{push:{send(t){let{to:e,...r}=t,s=typeof e=="string"?{user_ids:[e]}:Array.isArray(e)?{user_ids:e}:{topic:e.topic};return w(()=>h.notify.sendPush({body:{...r,to:s}}),n=>({message_ids:n.message_ids,recipients:n.message_ids.length,skipped_user_ids:n.skipped_user_ids}))}},email:{async send(t){let{to:e,templateSlug:r,...s}=t,n={...s,...r!==void 0?{template:r}:{}};if(!Array.isArray(e))return w(()=>h.notify.sendEmail({body:{...n,to:e}}),o=>({...o.message_id!==void 0?{message_id:o.message_id}:{},...o.skipped?{skipped:!0}:{}}));let a=[],l=202;for(let o of e)try{let c=await h.notify.sendEmail({body:{...n,to:o}});l=c.status,a.push(c.data.message_id??null)}catch(c){return k(c)}return{data:{message_ids:a},error:null,status:l}}}}),ye=t=>typeof t=="boolean"?t:t!=null&&t!==0&&t!=="",we=t=>typeof t=="string"?{name:t}:null,Pe=t=>t==="override"?"user":"system",Ar=t=>t!==null&&typeof t=="object"&&!Array.isArray(t)&&("userId"in t||"properties"in t);function ke(){return J.getStore()?.userId}function D(t){let e=t&&"userId"in t?t.userId??void 0:ke();return w(()=>e?h.flags.getUserValues({path:{user_id:e}}):h.flags.getValues(),r=>r.values??{})}var Se={setOverrideForUser:(t,e,r)=>w(()=>h.flags.putUserValue({path:{user_id:t,key:e},body:{value:r}}),s=>({key:s.key,value:s.value,source:Pe(s.source)})),setOverridesForUser:(t,e)=>w(()=>h.flags.putUserValues({path:{user_id:t},body:{values:e}}),r=>({values:r.values??{}})),clearOverrideForUser:(t,e)=>w(()=>h.flags.deleteUserValue({path:{user_id:t,key:e}}),r=>({key:r.key,value:r.value,source:Pe(r.source)})),clearAllOverridesForUser:t=>w(()=>h.flags.deleteUserValues({path:{user_id:t}}),e=>({deleted:e.deleted})),batchSetOverrides:t=>w(()=>h.flags.batchUserValues({body:{operations:t.map(e=>({user_id:e.userId,values:e.values}))}}),e=>({applied:e.applied}))},Rr=E("Flags",{async isEnabled(t,e){let r=s=>(d.warn(`[palbase] flag "${t}" could not be read (${s}): treating it as off`),!1);try{let s=await D(e);return s.error?r(`${s.error.code}: ${s.error.message}`):ye(s.data[t])}catch(s){return r(s instanceof Error?s.message:String(s))}},async getVariant(t,e){let r=await D(e);return r.error?{data:null,error:r.error,status:r.status}:{data:we(r.data[t]),error:null,status:r.status}},async getAll(t){let e=await D(t);return e.error?{data:null,error:e.error,status:e.status}:{data:Object.entries(e.data).map(([r,s])=>{let n=we(s);return{name:r,enabled:ye(s),...n?{variant:n}:{}}}),error:null,status:e.status}},async get(t,e,r){let s,n=!1,a;r!==void 0?(s=e,n=!0,a=r):Ar(e)?a=e:e!==void 0&&(s=e,n=!0);let l=await D(a);if(l.error)return n?{data:s??null,error:null,status:l.status}:{data:null,error:l.error,status:l.status};let o=l.data[t];return{data:o===void 0?s??null:o,error:null,status:l.status}},async setOverride(t,e){let r=ke();return r?Se.setOverrideForUser(r,t,e):{data:null,error:{code:"no_user",message:"Flags.setOverride writes the signed-in user's value: this request has none \u2014 Flags.$asService().setOverrideForUser(userId, key, value) writes anyone's"},status:400}},$asService(){return Se}}),Er=E("Realtime",{broadcast(t,e,r){return w(()=>h.realtime.broadcast({body:{messages:[{topic:t,event:e,payload:r??{}}]}}),()=>{})},state:{set(t,e,r){return w(()=>h.realtime.writeState({body:{ops:[{topic:t,key:e,value:r}]}}),()=>{})},clear(t,e){return w(()=>h.realtime.writeState({body:{ops:[{topic:t,key:e,delete:!0}]}}),()=>{})}}});import{z as zs}from"zod";export{xe as AuthUnavailable,mt as BadRequest,Ie as Body,At as CACHE_MAX_TTL,Rt as Cache,We as Client,gt as Conflict,x as ContractRunEnded,_e as Controller,tt as Database,ft as DeadlockDetected,Fe as Delete,dt as DiError,Re as EVENT_TYPES,Rr as Flags,ht as Forbidden,Oe as Get,$e as Headers,yt as HttpError,ze as Injectable,Je as Job,d as Log,kt as MAX_BODY_BYTES,U as MigrationRunEnded,Ge as Module,wt as NotFound,kr as Notifications,He as On,st as OnAuthorize,it as OnEmpty,nt as OnFirst,at as OnJoin,ot as OnLeave,lt as OnMessage,je as OptionalUser,ut as PalError,h as Palbase,_ as PalbaseError,cr as PalbaseFactory,Ue as Param,Be as Patch,Te as Post,Ce as Put,Me as Query,Le as QueryParams,Er as Realtime,Ne as Req,qe as RequestId,Ke as Resolve,rt as Room,I as SchemaNotPushed,br as Secrets,Pt as SerializationFailure,vr as Storage,Ee as TokenError,O as TokenVerifier,St as TooManyRequests,Ve as TraceId,pt as Unauthorized,vt as UniqueViolation,Ze as Upload,et as UploadedObject,De as User,Ye as Webhook,gs as bigint,fs as boolean,ys as check,B as createApp,ws as date,bt as defineError,Ps as defineSchema,Ss as defineTable,vs as enumType,ks as foreignKey,Qe as getRegisteredControllers,Xe as getRoutes,ct as getWebhookManifest,$s as increment,As as index,Rs as integer,Es as jsonb,Us as now,xs as numeric,_s as ownedByUser,Os as policy,Ts as raw,Cs as sqlType,Et as t,Bs as text,Fs as timestamp,Ms as userRef,Is as uuid,zs as z};
@@ -1 +1 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{a as k,b as $,c as R,d as E}from"../chunks/4K4MKD2J.js";import{a as h}from"../chunks/INXQWVHU.js";import{c as m}from"../chunks/4UPL27ED.js";import"../chunks/4MOCDBZP.js";import"../chunks/VTNEPJRV.js";import"reflect-metadata";import{randomUUID as C}from"node:crypto";import{createFakeClient as O,typedDatabase as b}from"palgres/testing";function x(t,r,n){if(n?.acceptLanguage!==void 0&&n.strings===void 0)throw new TypeError("withServices: acceptLanguage chooses among the languages of a strings table, and none was given \u2014 { strings: await loadStringsTable(appRoot), acceptLanguage }");let{Database:o,...i}=t,e=n?.strings;return m.run({requestId:`test_${C()}`,database:o===void 0?void 0:b(o),services:i,...e!==void 0?{strings:e,locales:h(n?.acceptLanguage??null,e.source),usedLocales:[]}:{}},r)}function D(){let t=new Map,r=new Map,n=[],o=e=>{if(t.has(e))return t.get(e);if(r.has(e))return r.get(e);if(n.includes(e)){let a=[...n.slice(n.indexOf(e)),e].map(c=>c.name??String(c));throw new TypeError(`isolated(): ${a.join(" \u2192 ")} needs itself to be built \u2014 give one of them with .with(Token, value)`)}n.push(e);try{let a=Reflect.getMetadata("design:paramtypes",e)??[],c=new e(...a.map(o));return r.set(e,c),c}finally{n.pop()}},i={with(e,a){return t.set(e,a),i},get:e=>o(e)};return i}function F(){let t=O();return{db:b(t),raw:t,queries:t.queries,seed:(r,n)=>t.seed(r,n),inserted:r=>t.inserted(r),updated:r=>t.updated(r),deleted:r=>t.deleted(r)}}import{lstat as N,readdir as j,readFile as L}from"node:fs/promises";import{join as T}from"node:path";var l="palbase/strings",u="_meta.json",f=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function S(t){try{return Intl.getCanonicalLocales(t),!0}catch{return!1}}function v(t,r){try{return JSON.parse(t)}catch(n){throw new Error(`${r} is not JSON: ${n.message}`)}}async function I(t){let r=T(t,l);try{if(!(await N(r)).isDirectory())throw new Error(`${l} is not a directory: the strings live in a directory of their own`)}catch(s){if(s.code==="ENOENT")return;throw s}let n=new Map;for(let s of await j(r,{withFileTypes:!0}))if(!(s.name.startsWith(".")||!s.name.endsWith(".json"))){if(!s.isFile())throw new Error(`${l}/${s.name} is not a regular file`);n.set(s.name,await L(T(r,s.name),"utf8"))}if(n.size===0)return;let o=n.get(u);if(o===void 0)throw new Error(`${l}/${u} is missing: it names the source language, and without it the language files are not a table`);let i=v(o,`${l}/${u}`);if(!f(i)||i.version!==2)throw new Error(`${l}/${u}: version ${JSON.stringify(f(i)?i.version:i)} is not one this reads (2)`);let e=i.source;if(typeof e!="string"||e===""||!S(e))throw new Error(`${l}/${u}: source ${JSON.stringify(e)} is not a language tag`);let a={},c=[];Object.setPrototypeOf(a,null);for(let s of[...n.keys()].sort()){if(s===u)continue;let g=s.slice(0,-5),d=`${l}/${s}`;if(g===""||!S(g))throw new Error(`${d}: ${JSON.stringify(g)} is not a language tag`);if(g===e)throw new Error(`${d}: ${g} is the source language \u2014 its text is the key itself, and it has no file`);let w=v(n.get(s),d);if(!f(w))throw new Error(`${d}: not a JSON object`);for(let[y,p]of Object.entries(w)){if(!f(p)||typeof p.value!="string"||typeof p.state!="string")throw new Error(`${d}: key ${JSON.stringify(y)} is not {"value": string, "state": string}`);(a[y]??={})[g]={value:p.value,state:p.state}}c.push(g)}return{version:1,source:e,locales:[e,...c],strings:a}}export{k as TestApiError,E as api,$ as createTestApi,F as fakeDatabase,D as isolated,I as loadStringsTable,R as testRun,x as withServices};
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{a as k,b as $,c as R,d as E}from"../chunks/YWOS5WH2.js";import{a as h}from"../chunks/CZQ7KIRM.js";import{c as m}from"../chunks/M5B52IE6.js";import"../chunks/OKZJIY6F.js";import"../chunks/PRM2UXWG.js";import"reflect-metadata";import{randomUUID as C}from"node:crypto";import{createFakeClient as O,typedDatabase as b}from"palgres/testing";function x(t,r,n){if(n?.acceptLanguage!==void 0&&n.strings===void 0)throw new TypeError("withServices: acceptLanguage chooses among the languages of a strings table, and none was given \u2014 { strings: await loadStringsTable(appRoot), acceptLanguage }");let{Database:o,...i}=t,e=n?.strings;return m.run({requestId:`test_${C()}`,database:o===void 0?void 0:b(o),services:i,...e!==void 0?{strings:e,locales:h(n?.acceptLanguage??null,e.source),usedLocales:[]}:{}},r)}function D(){let t=new Map,r=new Map,n=[],o=e=>{if(t.has(e))return t.get(e);if(r.has(e))return r.get(e);if(n.includes(e)){let a=[...n.slice(n.indexOf(e)),e].map(c=>c.name??String(c));throw new TypeError(`isolated(): ${a.join(" \u2192 ")} needs itself to be built \u2014 give one of them with .with(Token, value)`)}n.push(e);try{let a=Reflect.getMetadata("design:paramtypes",e)??[],c=new e(...a.map(o));return r.set(e,c),c}finally{n.pop()}},i={with(e,a){return t.set(e,a),i},get:e=>o(e)};return i}function F(){let t=O();return{db:b(t),raw:t,queries:t.queries,seed:(r,n)=>t.seed(r,n),inserted:r=>t.inserted(r),updated:r=>t.updated(r),deleted:r=>t.deleted(r)}}import{lstat as N,readdir as j,readFile as L}from"node:fs/promises";import{join as T}from"node:path";var l="palbase/strings",u="_meta.json",f=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function S(t){try{return Intl.getCanonicalLocales(t),!0}catch{return!1}}function v(t,r){try{return JSON.parse(t)}catch(n){throw new Error(`${r} is not JSON: ${n.message}`)}}async function I(t){let r=T(t,l);try{if(!(await N(r)).isDirectory())throw new Error(`${l} is not a directory: the strings live in a directory of their own`)}catch(s){if(s.code==="ENOENT")return;throw s}let n=new Map;for(let s of await j(r,{withFileTypes:!0}))if(!(s.name.startsWith(".")||!s.name.endsWith(".json"))){if(!s.isFile())throw new Error(`${l}/${s.name} is not a regular file`);n.set(s.name,await L(T(r,s.name),"utf8"))}if(n.size===0)return;let o=n.get(u);if(o===void 0)throw new Error(`${l}/${u} is missing: it names the source language, and without it the language files are not a table`);let i=v(o,`${l}/${u}`);if(!f(i)||i.version!==2)throw new Error(`${l}/${u}: version ${JSON.stringify(f(i)?i.version:i)} is not one this reads (2)`);let e=i.source;if(typeof e!="string"||e===""||!S(e))throw new Error(`${l}/${u}: source ${JSON.stringify(e)} is not a language tag`);let a={},c=[];Object.setPrototypeOf(a,null);for(let s of[...n.keys()].sort()){if(s===u)continue;let g=s.slice(0,-5),d=`${l}/${s}`;if(g===""||!S(g))throw new Error(`${d}: ${JSON.stringify(g)} is not a language tag`);if(g===e)throw new Error(`${d}: ${g} is the source language \u2014 its text is the key itself, and it has no file`);let w=v(n.get(s),d);if(!f(w))throw new Error(`${d}: not a JSON object`);for(let[y,p]of Object.entries(w)){if(!f(p)||typeof p.value!="string"||typeof p.state!="string")throw new Error(`${d}: key ${JSON.stringify(y)} is not {"value": string, "state": string}`);(a[y]??={})[g]={value:p.value,state:p.state}}c.push(g)}return{version:1,source:e,locales:[e,...c],strings:a}}export{k as TestApiError,E as api,$ as createTestApi,F as fakeDatabase,D as isolated,I as loadStringsTable,R as testRun,x as withServices};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import"./VTNEPJRV.js";import{pathToFileURL as i}from"node:url";import{z as c}from"zod";async function f(e){let n=new Map,t=new Map;for(let r of e){let a=`${r.className}.${r.method}`,o=t.get(r.className);if(o!==void 0&&o!==r.file)throw new Error(`two controllers are named ${r.className} (${o}, ${r.file}): the contract tells routes apart by their class's name \u2014 rename one`);t.set(r.className,r.file),n.set(a,{returns:await u(r),throws:r.throws})}return r=>n.get(`${r.controller.name}.${r.fn}`)}async function u(e){let n=`${e.file} \u2014 ${e.className}.${e.method}`;switch(e.returns.kind){case"void":return{kind:"void"};case"raw":return{kind:"raw"};case"schema":{let r=(await import(i(e.returns.file).href))[e.returns.exportName];if(!s(r))throw new Error(`${n}: its return type names ${e.returns.exportName}, which ${e.returns.file} exports as no schema (a zod, valibot or arktype schema)`);return{kind:"json",schema:r,array:e.returns.array}}case"expression":{let t=new Function("z",`return (${e.returns.expression});`)(c);if(!s(t))throw new Error(`${n}: the schema made of its return type is not one`);return{kind:"json",schema:t,array:!1}}}}function s(e){return typeof e=="object"&&e!==null&&typeof e["~standard"]?.validate=="function"}export{f as routeContracts};
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import"./PRM2UXWG.js";import{pathToFileURL as i}from"node:url";import{z as c}from"zod";async function f(e){let n=new Map,t=new Map;for(let r of e){let a=`${r.className}.${r.method}`,o=t.get(r.className);if(o!==void 0&&o!==r.file)throw new Error(`two controllers are named ${r.className} (${o}, ${r.file}): the contract tells routes apart by their class's name \u2014 rename one`);t.set(r.className,r.file),n.set(a,{returns:await u(r),throws:r.throws})}return r=>n.get(`${r.controller.name}.${r.fn}`)}async function u(e){let n=`${e.file} \u2014 ${e.className}.${e.method}`;switch(e.returns.kind){case"void":return{kind:"void"};case"raw":return{kind:"raw"};case"schema":{let r=(await import(i(e.returns.file).href))[e.returns.exportName];if(!s(r))throw new Error(`${n}: its return type names ${e.returns.exportName}, which ${e.returns.file} exports as no schema (a zod, valibot or arktype schema)`);return{kind:"json",schema:r,array:e.returns.array}}case"expression":{let t=new Function("z",`return (${e.returns.expression});`)(c);if(!s(t))throw new Error(`${n}: the schema made of its return type is not one`);return{kind:"json",schema:t,array:!1}}}}function s(e){return typeof e=="object"&&e!==null&&typeof e["~standard"]?.validate=="function"}export{f as routeContracts};
@@ -1,5 +1,5 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{c as O}from"./TV7W53F2.js";import{a as E,b as T,e as _}from"./MJPUCGXY.js";var a=class extends Error{kind;code;status;requestId;fields;retryAfter;data;constructor(n,t){super(t.message,t.cause===void 0?void 0:{cause:t.cause}),this.name="BackendError",this.kind=n,this.code=t.code,this.status=t.status??0,this.requestId=t.requestId,this.fields=t.fields,this.retryAfter=t.retryAfter,this.data=t.data}};function D(e){return e instanceof a||typeof e=="object"&&e!==null&&e.name==="BackendError"&&typeof e.kind=="string"}function $(e){let n=e.body,t={code:e.code,message:e.message,status:e.status,requestId:e.requestId??se(n,"request_id"),data:b(n,"data"),cause:e};if(e.code==="network_error")return new a("network",t);if(e.status===401)return new a("unauthorized",t);if(e.status===429)return new a("rateLimited",{...t,retryAfter:oe(n)??e.retryAfter});let r=re(n);return e.status===400&&r?new a("validation",{...t,fields:r}):new a("server",t)}function P(e){return e instanceof T||e instanceof Error&&e.name==="PalbaseError"}function j(e){return Array.isArray(e)&&e.length>0&&e.every(n=>typeof n=="object"&&n!==null&&typeof n.field=="string"&&typeof n.message=="string")}function re(e){let n=b(b(e,"data"),"fields");if(j(n))return n;let t=b(e,"fields");return j(t)?t:void 0}function oe(e){return N(e,"retry_after")??N(b(e,"data"),"retryAfter")}function b(e,n){if(typeof e=="object"&&e!==null)return e[n]}function N(e,n){let t=b(e,n);return typeof t=="number"?t:void 0}function se(e,n){let t=b(e,n);return typeof t=="string"?t:void 0}var ie=/^[A-Za-z_$][A-Za-z0-9_$]*$/,ae=Object.freeze(["adoptSession","analytics","appContext","appVersion","auth","callOnSignOut","cancelCallOnSignOut","configuration","consent","currentSession","flags","installation","module","moduleDirectory","notify","onSessionChange","onSignOut","preferences","realtime","scope","send","socket","storage","storedUserId","telemetry","transport","version","palbe","data","stores","purchases","messaging","notifications","perf","debug","equals","hashCode","toString","self","Type","init","deinit","subscript","then","constructor","__proto__"]),ce=new Set(ae),de=new Set(["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]);function S(e){return e==="then"||e==="toJSON"||de.has(e)}function A(e){return e==="call"||e==="join"||S(e)}function C(e){return typeof e=="string"&&ie.test(e)&&!ce.has(e)&&!S(e)}function B(e){return typeof e=="string"&&/^[a-z][a-z0-9-]{0,62}$/.test(e)}function I(e){_(e)}function J(e){return _(e).origin}var R=class extends Error{reason;constructor(n,t){super(n),this.name="RoomError",this.reason=t}},q=new WeakMap;async function U(e,n,t){let{pattern:r,events:o,messages:s}=pe(n),i=ue(r,t),c=q.get(e);c||q.set(e,c=new Map);let p=c;p.set(i,(p.get(i)??0)+1);let u=e.channel(i),l=()=>{let d=(p.get(i)??1)-1;d>0?p.set(i,d):(p.delete(i),u.leave())};try{await u.join()}catch{let d=u.state==="refused"?K(u.refusal,"unavailable"):"socket closed";throw l(),new R(`room ${JSON.stringify(i)} was not joined: ${d}`,d)}let m=!1,w=new Set,k=()=>{if(!m){m=!0,h();for(let d of[...w])d();l()}},h=u.onClosed(k),y=d=>{if(m)return()=>{};let v=u.on("broadcast",f=>{typeof f.event=="string"&&o.has(f.event)&&d(f.event,E(f.payload))}),g=()=>{w.delete(g),v()};return w.add(g),g};return{topic:i,on(d,v){if(typeof d=="function")return y((g,f)=>d({event:g,payload:f}));if(!o.has(d))throw new TypeError(`room ${JSON.stringify(r)} declares no event ${JSON.stringify(String(d))}`);if(typeof v!="function")throw new TypeError(`room ${JSON.stringify(r)}: on(${JSON.stringify(d)}, \u2026) takes the function the event is handed to`);return y((g,f)=>{g===d&&v(f)})},off(d){w.has(d)&&d()},async send(d,v){if(!s.has(d))throw new TypeError(`room ${JSON.stringify(r)} declares no message ${JSON.stringify(String(d))}`);let g=m?{status:"error",response:{reason:"not joined"}}:await u.push("broadcast",{type:"broadcast",event:d,payload:v});if(g.status==="ok")return;let f=K(g.response,"unavailable");throw new R(`room ${JSON.stringify(i)} did not take ${JSON.stringify(d)}: ${f}`,f)},leave:k}}function pe(e){let n=typeof e=="object"&&e!==null?e:{},t=r=>Array.isArray(r)&&r.every(o=>typeof o=="string");if(typeof n.pattern!="string"||n.pattern===""||!t(n.events)||!t(n.messages))throw new TypeError("join takes a room of the backend's generated module: its pattern, its events and its messages");return{pattern:n.pattern,events:new Set(n.events),messages:new Set(n.messages)}}function ue(e,n){let t=typeof n=="object"&&n!==null?n:{};return e.split(":").map(r=>{if(!(r.startsWith("{")&&r.endsWith("}")&&r.length>2))return r;let o=r.slice(1,-1),s=Object.hasOwn(t,o)?t[o]:void 0;if(typeof s!="string"||s==="")throw new TypeError(`room ${JSON.stringify(e)} needs a value for ${JSON.stringify(o)}`);if(s.includes(":"))throw new TypeError(`room ${JSON.stringify(e)}: the value of ${JSON.stringify(o)} is one segment of the channel's name and cannot hold ":"`);return s}).join(":")}function K(e,n){let t=e?.reason;return typeof t=="string"&&t!==""?t:n}var x=class{pending="";dataLines=[];eventName;consume(n){this.pending+=n.replace(/\r\n/g,`
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{c as O}from"./IXHR57QC.js";import{a as E,b as T,e as _}from"./UXRIXHHY.js";var a=class extends Error{kind;code;status;requestId;fields;retryAfter;data;constructor(n,t){super(t.message,t.cause===void 0?void 0:{cause:t.cause}),this.name="BackendError",this.kind=n,this.code=t.code,this.status=t.status??0,this.requestId=t.requestId,this.fields=t.fields,this.retryAfter=t.retryAfter,this.data=t.data}};function D(e){return e instanceof a||typeof e=="object"&&e!==null&&e.name==="BackendError"&&typeof e.kind=="string"}function $(e){let n=e.body,t={code:e.code,message:e.message,status:e.status,requestId:e.requestId??se(n,"request_id"),data:b(n,"data"),cause:e};if(e.code==="network_error")return new a("network",t);if(e.status===401)return new a("unauthorized",t);if(e.status===429)return new a("rateLimited",{...t,retryAfter:oe(n)??e.retryAfter});let r=re(n);return e.status===400&&r?new a("validation",{...t,fields:r}):new a("server",t)}function P(e){return e instanceof T||e instanceof Error&&e.name==="PalbaseError"}function j(e){return Array.isArray(e)&&e.length>0&&e.every(n=>typeof n=="object"&&n!==null&&typeof n.field=="string"&&typeof n.message=="string")}function re(e){let n=b(b(e,"data"),"fields");if(j(n))return n;let t=b(e,"fields");return j(t)?t:void 0}function oe(e){return N(e,"retry_after")??N(b(e,"data"),"retryAfter")}function b(e,n){if(typeof e=="object"&&e!==null)return e[n]}function N(e,n){let t=b(e,n);return typeof t=="number"?t:void 0}function se(e,n){let t=b(e,n);return typeof t=="string"?t:void 0}var ie=/^[A-Za-z_$][A-Za-z0-9_$]*$/,ae=Object.freeze(["adoptSession","analytics","appContext","appVersion","auth","callOnSignOut","cancelCallOnSignOut","configuration","consent","currentSession","flags","installation","module","moduleDirectory","notify","onSessionChange","onSignOut","preferences","realtime","scope","send","socket","storage","storedUserId","telemetry","transport","version","palbe","data","stores","purchases","messaging","notifications","perf","debug","equals","hashCode","toString","self","Type","init","deinit","subscript","then","constructor","__proto__"]),ce=new Set(ae),de=new Set(["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]);function S(e){return e==="then"||e==="toJSON"||de.has(e)}function A(e){return e==="call"||e==="join"||S(e)}function C(e){return typeof e=="string"&&ie.test(e)&&!ce.has(e)&&!S(e)}function B(e){return typeof e=="string"&&/^[a-z][a-z0-9-]{0,62}$/.test(e)}function I(e){_(e)}function J(e){return _(e).origin}var R=class extends Error{reason;constructor(n,t){super(n),this.name="RoomError",this.reason=t}},q=new WeakMap;async function U(e,n,t){let{pattern:r,events:o,messages:s}=pe(n),i=ue(r,t),c=q.get(e);c||q.set(e,c=new Map);let p=c;p.set(i,(p.get(i)??0)+1);let u=e.channel(i),l=()=>{let d=(p.get(i)??1)-1;d>0?p.set(i,d):(p.delete(i),u.leave())};try{await u.join()}catch{let d=u.state==="refused"?K(u.refusal,"unavailable"):"socket closed";throw l(),new R(`room ${JSON.stringify(i)} was not joined: ${d}`,d)}let m=!1,w=new Set,k=()=>{if(!m){m=!0,h();for(let d of[...w])d();l()}},h=u.onClosed(k),y=d=>{if(m)return()=>{};let v=u.on("broadcast",f=>{typeof f.event=="string"&&o.has(f.event)&&d(f.event,E(f.payload))}),g=()=>{w.delete(g),v()};return w.add(g),g};return{topic:i,on(d,v){if(typeof d=="function")return y((g,f)=>d({event:g,payload:f}));if(!o.has(d))throw new TypeError(`room ${JSON.stringify(r)} declares no event ${JSON.stringify(String(d))}`);if(typeof v!="function")throw new TypeError(`room ${JSON.stringify(r)}: on(${JSON.stringify(d)}, \u2026) takes the function the event is handed to`);return y((g,f)=>{g===d&&v(f)})},off(d){w.has(d)&&d()},async send(d,v){if(!s.has(d))throw new TypeError(`room ${JSON.stringify(r)} declares no message ${JSON.stringify(String(d))}`);let g=m?{status:"error",response:{reason:"not joined"}}:await u.push("broadcast",{type:"broadcast",event:d,payload:v});if(g.status==="ok")return;let f=K(g.response,"unavailable");throw new R(`room ${JSON.stringify(i)} did not take ${JSON.stringify(d)}: ${f}`,f)},leave:k}}function pe(e){let n=typeof e=="object"&&e!==null?e:{},t=r=>Array.isArray(r)&&r.every(o=>typeof o=="string");if(typeof n.pattern!="string"||n.pattern===""||!t(n.events)||!t(n.messages))throw new TypeError("join takes a room of the backend's generated module: its pattern, its events and its messages");return{pattern:n.pattern,events:new Set(n.events),messages:new Set(n.messages)}}function ue(e,n){let t=typeof n=="object"&&n!==null?n:{};return e.split(":").map(r=>{if(!(r.startsWith("{")&&r.endsWith("}")&&r.length>2))return r;let o=r.slice(1,-1),s=Object.hasOwn(t,o)?t[o]:void 0;if(typeof s!="string"||s==="")throw new TypeError(`room ${JSON.stringify(e)} needs a value for ${JSON.stringify(o)}`);if(s.includes(":"))throw new TypeError(`room ${JSON.stringify(e)}: the value of ${JSON.stringify(o)} is one segment of the channel's name and cannot hold ":"`);return s}).join(":")}function K(e,n){let t=e?.reason;return typeof t=="string"&&t!==""?t:n}var x=class{pending="";dataLines=[];eventName;consume(n){this.pending+=n.replace(/\r\n/g,`
3
3
  `);let t=[],r=this.pending.indexOf(`
4
4
  `);for(;r!==-1;){let o=this.pending.slice(0,r);this.pending=this.pending.slice(r+1);let s=o.endsWith("\r")?o.slice(0,-1):o;if(s==="")this.dataLines.length>0&&t.push({event:this.eventName,payload:this.dataLines.join(`
5
5
  `)}),this.dataLines=[],this.eventName=void 0;else if(!s.startsWith(":")){if(s.startsWith("data:")){let i=s.slice(5);this.dataLines.push(i.startsWith(" ")?i.slice(1):i)}else if(s.startsWith("event:")){let i=s.slice(6);this.eventName=i.startsWith(" ")?i.slice(1):i}}r=this.pending.indexOf(`
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
2
  function o(){let n=globalThis;if(typeof n.document<"u"||n.navigator?.product==="ReactNative")return!0;let t=n.navigator?.userAgent;return typeof t=="string"&&t.startsWith("Mozilla/")}export{o as a};
@@ -1,5 +1,5 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{a as sn,c as se,d as an,e as Ee,g as S}from"./4UPL27ED.js";import{b as Ye,d as ht,e as tn,f as nn,g as Ge,h as Ze,k as rn,q as on}from"./FVIHTHHV.js";import{b as $e}from"./MJPUCGXY.js";import"reflect-metadata";var gt=[{name:"minute",lo:0,hi:59},{name:"hour",lo:0,hi:23},{name:"day of the month",lo:1,hi:31},{name:"month",lo:1,hi:12},{name:"day of the week",lo:0,hi:7}],dn="a schedule is five fields \u2014 minute hour day-of-month month day-of-week, in UTC \u2014 of numbers, *, lists (1,15), ranges (1-5) and steps (*/10)",Xe=/^\d+$/;function $r(e,t,r){let n=new Set;for(let o of e.split(",")){let s=o.indexOf("/"),a=s===-1?o:o.slice(0,s),i=1;if(s!==-1){let f=o.slice(s+1);if(!Xe.test(f)||Number(f)<1||Number(f)>r)return;i=Number(f)}let c=t,u=r;if(a!=="*")if(a.includes("-")){let f=a.indexOf("-"),y=a.slice(0,f),E=a.slice(f+1);if(!Xe.test(y)||!Xe.test(E)||Number(y)<t||Number(E)>r||Number(y)>Number(E))return;c=Number(y),u=Number(E)}else{if(!Xe.test(a)||Number(a)<t||Number(a)>r)return;c=Number(a),u=s===-1?c:r}for(let f=c;f<=u;f+=i)n.add(f)}return n}function cn(e){let t=e.trim().split(/\s+/);if(t.length!==5||t[0]==="")return`${dn}; "${e}" is not`;let r=[];for(let u=0;u<5;u++){let f=$r(t[u],gt[u].lo,gt[u].hi);if(!f)return`${dn}; its ${gt[u].name} "${t[u]}" is not one`;r.push(f)}let[,,n,o,s]=r;s.has(7)&&s.add(0);let a=t[2].startsWith("*"),i=t[4].startsWith("*"),c=new Date(Date.UTC(2e3,0,1));for(let u=0;u<366*8+2;u++,c.setUTCDate(c.getUTCDate()+1)){if(!o.has(c.getUTCMonth()+1))continue;let f=n.has(c.getUTCDate()),y=s.has(c.getUTCDay());if(a||i?f&&y:f||y)return}return`"${e}" is never due: no date has that day in that month`}var Re=Symbol.for("palbase.backend.controller"),Se=Symbol.for("palbase.backend.routes"),wt=Symbol.for("palbase.backend.params"),bt=Symbol.for("palbase.backend.injectable"),vt=Symbol.for("palbase.backend.module"),he=Symbol.for("palbase.backend.events"),Oe=Symbol.for("palbase.backend.webhook"),ue=Symbol.for("palbase.backend.jobs");function X(e,t,r){let n=e;return Object.prototype.hasOwnProperty.call(n,t)||Object.defineProperty(n,t,{value:r(),enumerable:!1}),n[t]}var yt=Symbol.for("palbase.backend.declared");function oe(){let e=globalThis;return e[yt]instanceof Set||(e[yt]=new Set),e[yt]}var _e=new Set(["webhooks","_palbase"]);function Ls(e,t={}){if(typeof e!="string")throw new TypeError("@Controller(path, options): path is a string");return r=>{let n=e.split("/").filter(Boolean)[0];if(n!==void 0&&_e.has(n))throw new TypeError(`@Controller("${e}") on ${r.name}: /${n} is the platform's; a controller is served elsewhere`);X(r,Re,()=>({basePath:e,options:t})),oe().add(r)}}function xe(e){return(t,r={})=>{if(typeof t!="string")throw new TypeError(`@${e[0]}${e.slice(1).toLowerCase()}(path, options): path is a string \u2014 the query string is read with @QueryParams(schema)`);return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@${e}("${t}") goes on a method`);X(n.constructor,Se,()=>[]).push({method:e,subpath:t,fn:o,options:r})}}}var qs=xe("GET"),Hs=xe("POST"),Js=xe("PUT"),Bs=xe("PATCH"),zs=xe("DELETE"),Fs=xe("QUERY");function te(e,t={}){return(r,n,o)=>{if(typeof n!="string")throw new TypeError(`@${e} goes on a route method's parameter`);let s=X(r.constructor,wt,()=>new Map);s.has(n)||s.set(n,[]),s.get(n).push({index:o,kind:e,...t})}}function kt(e,t){if(typeof t!="object"||t===null||typeof t["~standard"]?.validate!="function")throw new TypeError(`@${e}(schema): schema is a Standard Schema (a zod, valibot or arktype schema)`);return t}var Ks=e=>te("body",{schema:kt("Body",e)}),Ws=e=>te("query",{schema:kt("QueryParams",e)}),Vs=e=>te("headers",e===void 0?{}:{schema:kt("Headers",e)}),Ys=e=>{if(typeof e!="string"||e==="")throw new TypeError("@Param(name): name is the path parameter");return te("param",{name:e})},Gs=()=>te("user"),Zs=()=>te("optionalUser"),Xs=()=>te("req"),Qs=()=>te("requestId"),ea=()=>te("requestId"),ta=()=>te("client");function na(e,...t){if(typeof e!="function"||typeof e.prototype?.resolve!="function")throw new TypeError(`@Resolve(resolver): resolver is a class with a resolve(context, options) method${typeof e=="function"?` \u2014 ${e.name} has none`:""}`);return te("resolve",{resolver:e,options:t[0]})}function ra(){return e=>{X(e,bt,()=>!0),oe().add(e)}}function oa(e){return t=>{X(t,vt,()=>({imports:[],controllers:[],providers:[],exports:[],...e}))}}var ln=/^[a-z]+(\.[a-z_]+)+$/,Er=/^[a-z][a-z0-9-]{1,62}$/,$t=e=>e.startsWith("file.");function sa(e,t={}){if(typeof e!="string")throw new TypeError("@On(event): event is the type its handler takes, like user.deleted");let r=t?.bucket;if(r!==void 0){if(typeof r!="string"||!Er.test(r))throw new TypeError(`@On("${e}", { bucket }): ${JSON.stringify(r)} is not a bucket's name \u2014 lowercase letters, digits and dashes, starting with a letter, 2 to 63 of them`);if(!$t(e))throw new TypeError(`@On("${e}", { bucket: "${r}" }): only a storage event (file.uploaded, file.deleted, file.moved) is of a bucket`)}return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@On("${e}") goes on a method`);X(n.constructor,he,()=>[]).push(r===void 0?{event:e,fn:o}:{event:e,fn:o,bucket:r}),oe().add(n.constructor)}}var Rr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;function aa(e){let t=e??{},r=`@Job(${JSON.stringify(t.name??null)})`;if(typeof t.name!="string"||!Rr.test(t.name))throw new TypeError(`${r}: name is letters, digits, '.', '_' and '-', at most 64, starting with a letter or digit`);if(typeof t.schedule!="string")throw new TypeError(`${r}: schedule is five fields of cron's, like "0 3 * * *"`);let n=cn(t.schedule);if(n)throw new TypeError(`${r}: ${n}`);if(t.timeout!==void 0&&(!Number.isInteger(t.timeout)||t.timeout<1||t.timeout>300))throw new TypeError(`${r}: timeout is whole seconds, 1 to 300 (got ${String(t.timeout)})`);if(t.retry!==void 0&&(!Number.isInteger(t.retry)||t.retry<0||t.retry>10))throw new TypeError(`${r}: retry is a whole number, 0 to 10 (got ${String(t.retry)})`);let o={name:t.name,schedule:t.schedule.trim().split(/\s+/).join(" "),timeout:t.timeout??30,retries:t.retry??5};return s=>{if(typeof s.prototype.run!="function")throw new TypeError(`${r} on ${s.name}: a job is a class with a run(meta) method`);if(Object.prototype.hasOwnProperty.call(s,ue))throw new TypeError(`${r} on ${s.name}: a class is one job`);Object.defineProperty(s,ue,{value:o,enumerable:!1}),oe().add(s)}}var un=["stripe","github","twilio","sendgrid","slack","discord","livekit"],Sr=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;function ia(e){return t=>{let r=`@Webhook on ${t.name}`,n=e??{};if(typeof n.name!="string"||n.name==="")throw new TypeError(`${r}: name is required \u2014 the last segment of its URL, /webhooks/<name>, which the sender is configured with`);if(!Sr.test(n.name))throw new TypeError(`${r}: name "${n.name}" is the last segment of its URL: lowercase letters, digits and dashes, starting and ending with one of those`);if(n.name==="palbase")throw new TypeError(`${r}: /webhooks/palbase is the platform's own deliveries (an @On outside a @Webhook class takes them); this webhook is served under another name`);if(n.provider===void 0&&n.signature===void 0)throw new TypeError(`${r}: a provider or a signature is required \u2014 an endpoint that verifies nothing takes forged deliveries`);if(n.provider!==void 0&&n.signature!==void 0)throw new TypeError(`${r}: a provider and a signature are alternatives \u2014 keep the one that describes the sender`);if(n.provider!==void 0&&!un.includes(n.provider))throw new TypeError(`${r}: provider "${String(n.provider)}" is not one of ${un.join(", ")} \u2014 another sender's scheme is spelled out as signature`);if(n.signature!==void 0&&Or(n.signature,r),typeof n.secret?.env!="string"||n.secret.env==="")throw new TypeError(`${r}: secret: { env: "VAR_NAME" } is required \u2014 the env var holding the signing secret`);let o=T(t,he)??[];if(o.length===0)throw new TypeError(`${r}: at least one @On is required \u2014 a webhook that runs nothing for every delivery is a mistake`);let s=new Set;for(let{event:a,bucket:i}of o){if(s.has(a))throw new TypeError(`${r}: @On("${a}") is declared twice; one method takes an event`);if(i!==void 0)throw new TypeError(`${r}: @On("${a}", { bucket: "${i}" }) \u2014 a bucket keeps a handler to the project's storage events, and ${n.name}'s are a third party's`);s.add(a)}X(t,Oe,()=>({name:n.name,provider:n.provider,signature:n.signature&&{...n.signature},secret:{env:n.secret.env},events:o.map(({event:a,fn:i})=>({event:a,fn:i}))})),oe().add(t)}}function Or(e,t){if(typeof e.header!="string"||e.header==="")throw new TypeError(`${t}: signature.header is required \u2014 the header the signature arrives in`);if(e.prefix!==void 0&&typeof e.prefix!="string")throw new TypeError(`${t}: signature.prefix is the text before the signature, like "sha256="`);if(e.algo!=="hmac-sha256"&&e.algo!=="hmac-sha1")throw new TypeError(`${t}: signature.algo "${String(e.algo)}" is not hmac-sha256 or hmac-sha1`);if(e.encoding!=="hex"&&e.encoding!=="base64")throw new TypeError(`${t}: signature.encoding "${String(e.encoding)}" is not hex or base64`);if(typeof e.signs!="string"||!e.signs.includes("{body}"))throw new TypeError(`${t}: signature.signs must contain {body} \u2014 a signature of a constant signs nothing`);if(e.signs.includes("{ts}")&&(typeof e.timestampHeader!="string"||e.timestampHeader===""))throw new TypeError(`${t}: signature.signs uses {ts} but no timestampHeader says where to read it`)}function T(e,t){return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0}function da(){return[...oe()].filter(e=>T(e,Re)!==void 0)}function ca(e){return(T(e,Se)??[]).map(t=>({method:t.method,path:t.subpath,fnName:t.fn,options:{...t.options,...t.upload!==void 0?{uploadConfig:t.upload}:{}}}))}var Et="/_palbase/storage/upload/authorize",fn="/_palbase/storage/upload/complete",Rt="/_palbase/realtime/rooms";var _r=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Te(e){if(!_r(e)||typeof e.role!="string"||e.role===""||e.id!==void 0&&typeof e.id!="string"||e.session!==void 0&&typeof e.session!="string")return;let t={role:e.role};return typeof e.id=="string"&&e.id!==""&&(t.id=e.id),typeof e.session=="string"&&e.session!==""&&(t.session=e.session),t.id&&typeof e.email=="string"&&e.email!==""&&(t.email=e.email),t.id&&typeof e.emailVerified=="boolean"&&(t.emailVerified=e.emailVerified),t}function mn(e){return typeof e=="string"&&e!==""&&e.length<=64?e:void 0}function pn(e,t){return e.id?`u:${e.id}`:e.session?`s:${e.session}`:t?`a:${t}`:`r:${e.role}`}function Qe(e){return e?.id?{sub:e.id,role:e.role,...e.session?{session_id:e.session}:{}}:null}var xr=/^[a-z][a-z0-9-]{1,62}$/,hn=1024,Tr=new Set(["userId","uploadId","filename"]);function pa(e,t){if(typeof e!="string")throw new TypeError("@Upload(path, { bucket, pathTemplate }): path is a string");let r=t??{};if(typeof t!="object"||t===null)throw new TypeError(`@Upload("${e}"): the second argument is { bucket, pathTemplate } \u2014 where its files go`);if(typeof r.bucket!="string"||r.bucket==="")throw new TypeError(`@Upload("${e}"): bucket is required \u2014 the name of the bucket its files go to`);if(!xr.test(r.bucket))throw new TypeError(`@Upload("${e}"): bucket "${r.bucket}" is no bucket's name \u2014 lowercase letters, digits and dashes, starting with a letter, 2 to 63 long`);if(typeof r.pathTemplate!="string"||r.pathTemplate==="")throw new TypeError(`@Upload("${e}"): pathTemplate is required \u2014 the path each file is stored under, like "{userId}/{uploadId}-{filename}"`);let n=Ar(r.pathTemplate);if(n)throw new TypeError(`@Upload("${e}"): pathTemplate "${r.pathTemplate}" ${n}`);let o={bucket:r.bucket,pathTemplate:r.pathTemplate},s={...r.auth!==void 0?{auth:r.auth}:{},...r.rateLimit!==void 0?{rateLimit:r.rateLimit}:{}};return(a,i,c)=>{if(typeof i!="string"||c===void 0||typeof c.value!="function")throw new TypeError(`@Upload("${e}") goes on a method`);X(a.constructor,Se,()=>[]).push({method:"POST",subpath:e,fn:i,options:s,upload:o})}}function ha(){return te("uploadedObject")}function Ar(e){for(let r of e.matchAll(/\{([^{}]*)\}/g))if(!Tr.has(r[1]))return`names {${r[1]}}: its tokens are {userId}, {uploadId} and {filename}`;if(/[{}]/.test(e.replace(/\{(userId|uploadId|filename)\}/g,"")))return"has a brace of no token: its tokens are {userId}, {uploadId} and {filename}";let t=e.replace(/\{(userId|uploadId|filename)\}/g,"x");if(!gn(t))return"is no path storage keeps: segments separated by /, none empty, . or .., no control character, at most 1024 bytes"}function gn(e){if(e===""||new TextEncoder().encode(e).byteLength>hn)return!1;for(let t=0;t<e.length;t++){let r=e.charCodeAt(t);if(r<32||r===127)return!1}return e.split("/").every(t=>t!==""&&t!=="."&&t!=="..")}function Pr(e,t){return e.replace(/\{(userId|uploadId|filename)\}/g,(r,n)=>jr(n==="userId"?t.userId??"anonymous":n==="uploadId"?t.uploadId:t.filename??"file"))}function jr(e){let t=e.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200F\u2028-\u202E\u2060-\u2069\uFEFF]/g,"").replace(/[/\\]/g,"-").replace(/\.{2,}/g,".").replace(/^[\s.]+/,"").trimEnd();return t===""?"file":Array.from(t).slice(0,200).join("")}function yn(e,t){let r=Pr(e,t);return gn(r)?{path:r}:{problem:`the file's name makes its path longer than storage keeps (${hn} bytes)`}}function wn(e){let t=new Map;for(let r of e)r.meta.upload&&t.set(r.controller,(t.get(r.controller)??new Set).add(r.fn));for(let r of e){let n=`${r.controller.name}.${r.fn}`;if(!r.meta.upload){if(t.get(r.controller)?.has(r.fn))throw new TypeError(`${n}: @Upload and @${r.method[0]}${r.method.slice(1).toLowerCase()} on one method \u2014 an upload's handler runs with the stored object, which an ordinary route has none of; give each its own method`);if(r.params.some(s=>s.kind==="uploadedObject"))throw new TypeError(`${n}: @UploadedObject() on ${r.id}, which is no @Upload route \u2014 only an upload has a stored object`);continue}let o=r.params.find(s=>s.kind==="headers"||s.kind==="req"||s.kind==="client");if(o){let s=o.kind==="headers"?"Headers":o.kind==="req"?"Req":"Client";throw new TypeError(`${n}: @${s}() on an @Upload route \u2014 the client's request reaches storage, which forwards none of its headers; the handler is given the caller (@User), the body (@Body) and the stored object`)}}}var St=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function bn(e,t){if(!St(t))return"a call is a JSON object";let{route:r,method:n,query:o,uploadId:s}=t;if(typeof r!="string"||!r.startsWith("/"))return"route is the upload route's path";if(typeof n!="string"||n==="")return"method is the route's";if(typeof o!="string")return'query is the query string, "" for none';if(typeof s!="string"||s==="")return"uploadId is the upload's id";let a=Te(t.user);if(!a)return"user is { id?, session?, role }";let i=mn(t.client);if(e==="authorize")return t.filename!==void 0&&typeof t.filename!="string"?"filename is the file's name":{route:r,method:n,query:o,uploadId:s,user:a,...i?{client:i}:{},filename:t.filename??"",...Object.hasOwn(t,"body")?{body:t.body??null}:{}};let c=Cr(t.uploadedObject);return c?c.uploadId!==s?"uploadedObject is another upload's":{route:r,method:n,query:o,uploadId:s,user:a,...i?{client:i}:{},filename:"",uploadedObject:c,body:t.body??null}:"uploadedObject is the stored object: { uploadId, path, bucket, size, contentType, checksum, width?, height?, thumbhash?, variants }"}function Cr(e){if(!St(e))return;let{uploadId:t,path:r,bucket:n,size:o,contentType:s,checksum:a,width:i,height:c,thumbhash:u,variants:f}=e;if(!(typeof t!="string"||typeof r!="string"||typeof n!="string"||typeof s!="string"||typeof a!="string")&&!(typeof o!="number"||!Number.isInteger(o)||o<0)&&!(i!==void 0&&typeof i!="number"||c!==void 0&&typeof c!="number"||u!==void 0&&typeof u!="string")&&!(!St(f)||!Object.values(f).every(y=>typeof y=="string")))return{uploadId:t,path:r,bucket:n,size:o,contentType:s,checksum:a,...i!==void 0?{width:i}:{},...c!==void 0?{height:c}:{},...u!==void 0?{thumbhash:u}:{},variants:{...f}}}import{markData as Mr}from"palgres";var ge=Symbol.for("palbase.backend.room"),Pe=Symbol.for("palbase.backend.roomHooks"),Dr=6e4,Ae=255,Ur=["roles:","flags:","messaging:","debug:"],xt=e=>new TextEncoder().encode(e).byteLength,vn=e=>typeof e=="object"&&e!==null&&typeof e["~standard"]?.validate=="function";function Nr(e){if(e.includes("/"))return`channel patterns are colon-separated, not slash-separated. Write "${e.replace(/\//g,":")}" \u2014 a slash matches no live topic.`;if(xt(e)>Ae)return`a channel is ${Ae} bytes at most`;if(/[\x00-\x1F\x7F]/.test(e))return"a channel has no control character";if(e==="phoenix")return"phoenix is the socket's own";let t=Ur.find(n=>e.startsWith(n));if(t)return`${t} channels are the platform's`;let r=new Set;for(let n of e.split(":")){if(n==="")return"empty segment \u2014 every segment must be non-empty.";if(/[{}]/.test(n)){if(n==="{}")return'"{}" names no parameter.';if(!/^\{[^{}]+\}$/.test(n))return`"${n}" \u2014 a parameter is a whole segment, {name}`;if(r.has(n))return`parameter "${n}" appears twice.`;r.add(n)}}}function kn(e){if(typeof e!="string"||e==="")return"is a name";if(xt(e)>Ae)return`is ${Ae} bytes at most`}function ka(e,t){if(typeof e!="string"||e==="")throw new TypeError('@Room(pattern, { events }): pattern is the channels it is, like "ai:{sessionId}"');let r=Nr(e);if(r)throw new TypeError(`@Room("${e}"): ${r}`);let n=t??{};if(typeof n.events!="object"||n.events===null||Array.isArray(n.events))throw new TypeError(`@Room("${e}"): events is required \u2014 what the room sends, by name, each its payload's schema ({} for none)`);for(let[a,i]of Object.entries(n.events)){let c=kn(a);if(c)throw new TypeError(`@Room("${e}"): event "${a}" ${c}`);if(!vn(i))throw new TypeError(`@Room("${e}"): event "${a}" is a Standard Schema (a zod, valibot or arktype schema) \u2014 its payload's`)}if(n.graceMs!==void 0&&(!Number.isSafeInteger(n.graceMs)||n.graceMs<=0))throw new TypeError(`@Room("${e}"): graceMs is whole milliseconds, more than 0 (got ${String(n.graceMs)})`);let o={...n.events},s=n.graceMs??Dr;return a=>{let i=X(a,Pe,Tt);X(a,ge,()=>({pattern:e,events:o,graceMs:s,hooks:{...i.hooks},messages:Object.assign(Object.create(null),i.messages)})),oe().add(a)}}var Tt=()=>({hooks:Object.create(null),messages:Object.create(null)});function Ue(e){let t=`On${e[0].toUpperCase()}${e.slice(1)}`;return()=>(r,n,o)=>{if(typeof n!="string"||o===void 0||typeof o.value!="function")throw new TypeError(`@${t}() goes on a method`);if(typeof r=="function")throw new TypeError(`@${t}() on static ${r.name}.${n}: a room's methods are its instance's`);let s=X(r.constructor,Pe,Tt),a=s.hooks[e];if(a!==void 0&&a!==n)throw new TypeError(`@${t}() is declared twice in one room (${a} and ${n}). A room has one of each hook.`);s.hooks[e]=n,oe().add(r.constructor)}}var $a=Ue("authorize"),Ea=Ue("first"),Ra=Ue("join"),Sa=Ue("leave"),Oa=Ue("empty");function _a(e,t){let r=kn(e);if(r)throw new TypeError(`@OnMessage(name, schema): name ${r}`);if(!vn(t))throw new TypeError(`@OnMessage("${e}", schema): schema is a Standard Schema (a zod, valibot or arktype schema)`);return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@OnMessage("${e}") goes on a method`);if(typeof n=="function")throw new TypeError(`@OnMessage("${e}") on static ${n.name}.${o}: a room's methods are its instance's`);let a=X(n.constructor,Pe,Tt),i=a.messages[e];if(i!==void 0&&i.fn!==o)throw new TypeError(`@OnMessage("${e}") is declared twice in one room (${i.fn} and ${o}).`);a.messages[e]={fn:o,schema:t},oe().add(n.constructor)}}function Ir(e){return T(e,ge)}function Lr(e,t){let r=e.split(":"),n=t.split(":");if(r.length!==n.length)return;let o=[];for(let s=0;s<r.length;s++){let a=r[s];if(a.length>=2&&a.startsWith("{")&&a.endsWith("}")){if(n[s]==="")return;o.push([a.slice(1,-1),n[s]])}else if(a!==n[s])return}return Object.fromEntries(o)}var qr=1e4,Hr=1e3,Jr=100,At=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ae=(e,t,r,n)=>({status:e,code:t,message:r,...n!==void 0?{retryAfter:n}:{}}),Br=new Set(["first","join","leave","empty"]);function $n(e,t){let r=new Map,n=new Map;for(let{cls:b,instance:$}of e){let w=Ir(b),R=w.pattern.split(":").map(C=>C.startsWith("{")?"{}":C).join(":"),P=n.get(R);if(P!==void 0)throw new TypeError(`@Room("${w.pattern}") on ${b.name}: ${r.get(P)?.cls.name}'s "${P}" is the same channels \u2014 one room is told of them; keep one`);n.set(R,w.pattern);for(let[C,I]of[...Object.entries(w.hooks),...Object.entries(w.messages).map(([L,U])=>[`message ${L}`,U.fn])])if(typeof $[I]!="function")throw new TypeError(`@Room("${w.pattern}") on ${b.name}: its ${C} is ${I}, which is no method of it`);r.set(w.pattern,{cls:b,instance:$,room:w})}let o=new Map,s=new Set,a=new Set,i=new _t(t.broadcast),c=b=>{let $=o.get(b);return $||($=new AbortController,o.set(b,$)),$},u=(b,$)=>{$?.abort(),o.get(b)===$&&o.delete(b)};function f(b,$,w,R,P,C,I){let L=R?.signal??AbortSignal.abort(),U=`${b.cls.name} (${$})`;return{room:$,params:Object.freeze({...w}),signal:L,count:P,user:C,emit:(M,q)=>i.send({topic:$,event:M,payload:q??{},...I!==void 0?{conn_id:I}:{}},U),owner:{hold(M){se.exit(async()=>{try{await M(L)}catch(q){L.aborted||S.error(`[palbase] ${U}: a task owner.hold ran failed`,{error:q})}}).catch(()=>{})},release:()=>u($,R)}}}function y(b){let{room:$,channel:w}=b;if(typeof $!="string"||typeof w!="string")return ae(400,"bad_request","A room's call names its room (the pattern) and its channel");let R=r.get($);return R?{entry:R,channel:w,params:Lr($,w)}:ae(404,"not_found",`This app declares no room "${$}"`)}let E=(b,$)=>ae(400,"bad_request",`"${$}" is not a channel of the room "${b}"`);async function N(b,$){let w=y(b);if("status"in w)return w;let{entry:R,channel:P,params:C}=w,I={status:200,body:{subscribe:!1,publish:!1}};if(!C)return S.warn(`[palbase] ${R.cls.name}: realtime asked about "${P}", which is not a channel of the room "${R.room.pattern}"; the join is refused`),I;let L=Te(b.user),U=L?.id;if(!U)return I;let M=R.room.hooks.authorize;if(!M)return I;let q,re;try{q=await t.run(L,`${R.cls.name}.${M}`,$,async()=>R.instance[M]({user:{id:U},params:Object.freeze({...C})})),re=zr(q)}catch(Q){if(t.isOutage(Q)||$?.aborted)throw Q;return S.error(`[palbase] ${R.cls.name}.${M} (@OnAuthorize of ${P}) failed; the join is refused`,{error:Q}),I}return re==="malformed"?(S.warn(`[palbase] ${R.cls.name}.${M} (@OnAuthorize of ${P}) answered ${Fr(q)}, which is no grant (true, { read, write } or null); the join is refused`),I):{status:200,body:re}}async function g(b,$){let w=y(b);if("status"in w)return w;if(!w.params)return E(w.entry.room.pattern,w.channel);let R=Te(b.user);if(!R?.id||typeof b.event!="string")return ae(400,"bad_request","A message names its member (user) and its event");let P=Object.hasOwn(w.entry.room.messages,b.event)?w.entry.room.messages[b.event]:void 0;if(!P)return{status:200,body:{ok:!1,reason:En(`room "${w.channel}" declares no message "${b.event}"`,Ot)}};let C=await P.schema["~standard"].validate(Mr(b.payload??{}));if(C.issues)return{status:200,body:{ok:!1,reason:Wr(C.issues)}};let I=c(w.channel),L={...f(w.entry,w.channel,w.params,I,0,{id:R.id}),payload:C.value};try{await t.run(R,`${w.entry.cls.name}.${P.fn}`,$,async()=>w.entry.instance[P.fn](L))}catch(U){if(t.isOutage(U))throw U;return $?.aborted||S.error(`[palbase] ${w.entry.cls.name}.${P.fn} (@OnMessage "${b.event}" of ${w.channel}) failed`,{error:U}),{status:200,body:{ok:!1,reason:"handler_failed"}}}return{status:200,body:{ok:!0}}}async function A(b,$){let w=y(b);if("status"in w)return w;if(!w.params)return E(w.entry.room.pattern,w.channel);let R=b.event;if(typeof R!="string"||!Br.has(R))return ae(400,"bad_request","A room's moment is first, join, leave or empty");let P=typeof b.count=="number"&&Number.isInteger(b.count)&&b.count>=0?b.count:void 0;if(P===void 0)return ae(400,"bad_request","A room's moment says its count of members");let C=R==="join"||R==="leave",I=C?Te(b.user):void 0,L=C?b.connId:void 0;if(C&&(!I?.id||typeof L!="string"||L===""))return ae(400,"bad_request",`A ${R} names its member: user and connId`);let U=`${R}\0${w.channel}\0${typeof L=="string"?L:""}`;if(C&&s.has(U))return{status:204};if(a.has(U))return ae(503,"in_progress","This moment of the room is being handled",5);a.add(U);try{let M=w.entry.room.hooks[R],q;if(R==="empty"?(q=o.get(w.channel),u(w.channel,q)):q=R==="leave"?o.get(w.channel):c(w.channel),M){let re=f(w.entry,w.channel,w.params,q,P,{id:I?.id??""},R==="join"?L:void 0);try{await t.run(I,`${w.entry.cls.name}.${M}`,$,async()=>w.entry.instance[M](re))}catch(Q){if(t.isOutage(Q))throw Q;return $?.aborted||S.error(`[palbase] ${w.entry.cls.name}.${M} (${R} of ${w.channel}) failed; realtime tells it again`,{error:Q}),ae(500,"handler_failed",`The room's ${R} could not be handled`)}}return C&&(s.add(U),s.size>qr&&s.delete(s.values().next().value)),{status:204}}finally{a.delete(U)}}return{declarations:[...r.values()].map(b=>b.room),async serve(b,$,w){return At($)?b==="authorize"?N($,w):b==="message"?g($,w):b==="lifecycle"?A($,w):ae(404,"not_found",`No room call ${JSON.stringify(b)}`):ae(400,"bad_request","A room's call is a JSON object")},close(){for(let b of o.values())b.abort();o.clear()}}}function zr(e){let t={subscribe:!1,publish:!1};if(e==null||e===!1)return t;if(e===!0)return{subscribe:!0,publish:!0};if(!At(e))return"malformed";let r=Object.hasOwn(e,"read"),n=Object.hasOwn(e,"write");if(r&&typeof e.read!="boolean"||n&&typeof e.write!="boolean"||!r&&!n)return"malformed";let o=r?e.read:void 0,s=n?e.write:void 0;return o===!1?t:{subscribe:!0,publish:s!==!1}}function Fr(e){return Array.isArray(e)?"an array":At(e)?Object.hasOwn(e,"read")||Object.hasOwn(e,"write")?"an object whose read or write is not true or false":"an object that says neither read nor write":typeof e=="function"?"a function":typeof e=="string"?"a string":`${typeof e} ${String(e)}`}var Kr=20,Ot=256;function Wr(e){let t="";for(let r of e.slice(0,Kr)){let n=(r.path??[]).slice(0,8).map(s=>String(typeof s=="object"&&s!==null&&"key"in s?s.key:s).slice(0,64)).join("."),o=n===""?r.message:`${n}: ${r.message}`;if(t=t===""?o:`${t}; ${o}`,Buffer.byteLength(t)>=Ot)break}return En(t,Ot)}function En(e,t){if(Buffer.byteLength(e)<=t)return e;let r="";for(let n of e){if(Buffer.byteLength(r+n)>t-3)break;r+=n}return`${r}\u2026`}var _t=class{constructor(t){this.broadcast=t}broadcast;queues=new Map;dropped=new Map;send(t,r){if(typeof t.event!="string"||t.event===""||xt(t.event)>Ae){S.warn(`[palbase] ${r}: emit(${JSON.stringify(t.event)}) is not sent \u2014 an event's name is 1 to ${Ae} bytes`);return}try{JSON.stringify(t.payload)}catch(s){S.warn(`[palbase] ${r}: emit("${t.event}") is not sent \u2014 its payload is not JSON`,{error:s});return}let n=this.queues.get(t.topic);if(n){n.length>=Hr?this.dropped.set(t.topic,(this.dropped.get(t.topic)??0)+1):n.push(t);return}let o=[t];this.queues.set(t.topic,o),se.exit(()=>this.drain(t.topic,o,r))}async drain(t,r,n){for(;;){if(r.length===0){this.queues.delete(t);return}let o=r.splice(0,Jr);try{await this.broadcast(o)}catch(a){S.warn(`[palbase] ${n}: ${o.length} event(s) to ${t} were not sent`,{error:a})}let s=this.dropped.get(t);s&&(this.dropped.delete(t),S.warn(`[palbase] ${n}: ${s} event(s) to ${t} dropped \u2014 realtime took them slower than they were emitted`))}}};import{createHash as Pt,createHmac as Vr,createPublicKey as _n,timingSafeEqual as Yr,verify as xn}from"node:crypto";function Pa(e){let t=T(e,Oe);if(!t)throw new TypeError(`${e.name} is not a @Webhook`);return{name:t.name,provider:t.provider,secretEnv:t.secret.env,events:t.events.map(r=>r.event)}}function Tn(e,t,r,n={}){let o=new Map,s=[];for(let a of e){let i=T(a,Oe),c=o.get(i.name);if(c)throw new TypeError(`@Webhook "${i.name}" is declared by ${c.cls.name} and by ${a.name}: /webhooks/${i.name} is one endpoint`);let u=`@Webhook "${i.name}" (${a.name})`,f=r[i.secret.env],y;if(n.secrets!==!1)if(f===void 0||f==="")s.push(`${u} reads its signing secret from ${i.secret.env}, which is not set`);else try{y=Gr(i,f)}catch(g){s.push(`${u}: ${i.secret.env} ${g.message}`)}let E=t(a),N=new Map(i.events.map(({event:g,fn:A})=>[g,{name:`${a.name}.${A}`,call:(b,$)=>E[A](b,$)}]));o.set(i.name,{name:i.name,cls:a,provider:i.provider,signatureHeader:i.signature?.header,secretEnv:i.secret.env,scheme:y,events:N})}if(s.length>0)throw new Error(`[palbase] the app cannot start:
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{a as sn,c as se,d as an,e as Ee,g as S}from"./M5B52IE6.js";import{b as Ye,d as ht,e as tn,f as nn,g as Ge,h as Ze,k as rn,q as on}from"./PB7UKHCY.js";import{b as $e}from"./UXRIXHHY.js";import"reflect-metadata";var gt=[{name:"minute",lo:0,hi:59},{name:"hour",lo:0,hi:23},{name:"day of the month",lo:1,hi:31},{name:"month",lo:1,hi:12},{name:"day of the week",lo:0,hi:7}],dn="a schedule is five fields \u2014 minute hour day-of-month month day-of-week, in UTC \u2014 of numbers, *, lists (1,15), ranges (1-5) and steps (*/10)",Xe=/^\d+$/;function $r(e,t,r){let n=new Set;for(let o of e.split(",")){let s=o.indexOf("/"),a=s===-1?o:o.slice(0,s),i=1;if(s!==-1){let f=o.slice(s+1);if(!Xe.test(f)||Number(f)<1||Number(f)>r)return;i=Number(f)}let c=t,u=r;if(a!=="*")if(a.includes("-")){let f=a.indexOf("-"),y=a.slice(0,f),E=a.slice(f+1);if(!Xe.test(y)||!Xe.test(E)||Number(y)<t||Number(E)>r||Number(y)>Number(E))return;c=Number(y),u=Number(E)}else{if(!Xe.test(a)||Number(a)<t||Number(a)>r)return;c=Number(a),u=s===-1?c:r}for(let f=c;f<=u;f+=i)n.add(f)}return n}function cn(e){let t=e.trim().split(/\s+/);if(t.length!==5||t[0]==="")return`${dn}; "${e}" is not`;let r=[];for(let u=0;u<5;u++){let f=$r(t[u],gt[u].lo,gt[u].hi);if(!f)return`${dn}; its ${gt[u].name} "${t[u]}" is not one`;r.push(f)}let[,,n,o,s]=r;s.has(7)&&s.add(0);let a=t[2].startsWith("*"),i=t[4].startsWith("*"),c=new Date(Date.UTC(2e3,0,1));for(let u=0;u<366*8+2;u++,c.setUTCDate(c.getUTCDate()+1)){if(!o.has(c.getUTCMonth()+1))continue;let f=n.has(c.getUTCDate()),y=s.has(c.getUTCDay());if(a||i?f&&y:f||y)return}return`"${e}" is never due: no date has that day in that month`}var Re=Symbol.for("palbase.backend.controller"),Se=Symbol.for("palbase.backend.routes"),wt=Symbol.for("palbase.backend.params"),bt=Symbol.for("palbase.backend.injectable"),vt=Symbol.for("palbase.backend.module"),he=Symbol.for("palbase.backend.events"),Oe=Symbol.for("palbase.backend.webhook"),ue=Symbol.for("palbase.backend.jobs");function X(e,t,r){let n=e;return Object.prototype.hasOwnProperty.call(n,t)||Object.defineProperty(n,t,{value:r(),enumerable:!1}),n[t]}var yt=Symbol.for("palbase.backend.declared");function oe(){let e=globalThis;return e[yt]instanceof Set||(e[yt]=new Set),e[yt]}var _e=new Set(["webhooks","_palbase"]);function Ls(e,t={}){if(typeof e!="string")throw new TypeError("@Controller(path, options): path is a string");return r=>{let n=e.split("/").filter(Boolean)[0];if(n!==void 0&&_e.has(n))throw new TypeError(`@Controller("${e}") on ${r.name}: /${n} is the platform's; a controller is served elsewhere`);X(r,Re,()=>({basePath:e,options:t})),oe().add(r)}}function xe(e){return(t,r={})=>{if(typeof t!="string")throw new TypeError(`@${e[0]}${e.slice(1).toLowerCase()}(path, options): path is a string \u2014 the query string is read with @QueryParams(schema)`);return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@${e}("${t}") goes on a method`);X(n.constructor,Se,()=>[]).push({method:e,subpath:t,fn:o,options:r})}}}var qs=xe("GET"),Hs=xe("POST"),Js=xe("PUT"),Bs=xe("PATCH"),zs=xe("DELETE"),Fs=xe("QUERY");function te(e,t={}){return(r,n,o)=>{if(typeof n!="string")throw new TypeError(`@${e} goes on a route method's parameter`);let s=X(r.constructor,wt,()=>new Map);s.has(n)||s.set(n,[]),s.get(n).push({index:o,kind:e,...t})}}function kt(e,t){if(typeof t!="object"||t===null||typeof t["~standard"]?.validate!="function")throw new TypeError(`@${e}(schema): schema is a Standard Schema (a zod, valibot or arktype schema)`);return t}var Ks=e=>te("body",{schema:kt("Body",e)}),Ws=e=>te("query",{schema:kt("QueryParams",e)}),Vs=e=>te("headers",e===void 0?{}:{schema:kt("Headers",e)}),Ys=e=>{if(typeof e!="string"||e==="")throw new TypeError("@Param(name): name is the path parameter");return te("param",{name:e})},Gs=()=>te("user"),Zs=()=>te("optionalUser"),Xs=()=>te("req"),Qs=()=>te("requestId"),ea=()=>te("requestId"),ta=()=>te("client");function na(e,...t){if(typeof e!="function"||typeof e.prototype?.resolve!="function")throw new TypeError(`@Resolve(resolver): resolver is a class with a resolve(context, options) method${typeof e=="function"?` \u2014 ${e.name} has none`:""}`);return te("resolve",{resolver:e,options:t[0]})}function ra(){return e=>{X(e,bt,()=>!0),oe().add(e)}}function oa(e){return t=>{X(t,vt,()=>({imports:[],controllers:[],providers:[],exports:[],...e}))}}var ln=/^[a-z]+(\.[a-z_]+)+$/,Er=/^[a-z][a-z0-9-]{1,62}$/,$t=e=>e.startsWith("file.");function sa(e,t={}){if(typeof e!="string")throw new TypeError("@On(event): event is the type its handler takes, like user.deleted");let r=t?.bucket;if(r!==void 0){if(typeof r!="string"||!Er.test(r))throw new TypeError(`@On("${e}", { bucket }): ${JSON.stringify(r)} is not a bucket's name \u2014 lowercase letters, digits and dashes, starting with a letter, 2 to 63 of them`);if(!$t(e))throw new TypeError(`@On("${e}", { bucket: "${r}" }): only a storage event (file.uploaded, file.deleted, file.moved) is of a bucket`)}return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@On("${e}") goes on a method`);X(n.constructor,he,()=>[]).push(r===void 0?{event:e,fn:o}:{event:e,fn:o,bucket:r}),oe().add(n.constructor)}}var Rr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;function aa(e){let t=e??{},r=`@Job(${JSON.stringify(t.name??null)})`;if(typeof t.name!="string"||!Rr.test(t.name))throw new TypeError(`${r}: name is letters, digits, '.', '_' and '-', at most 64, starting with a letter or digit`);if(typeof t.schedule!="string")throw new TypeError(`${r}: schedule is five fields of cron's, like "0 3 * * *"`);let n=cn(t.schedule);if(n)throw new TypeError(`${r}: ${n}`);if(t.timeout!==void 0&&(!Number.isInteger(t.timeout)||t.timeout<1||t.timeout>300))throw new TypeError(`${r}: timeout is whole seconds, 1 to 300 (got ${String(t.timeout)})`);if(t.retry!==void 0&&(!Number.isInteger(t.retry)||t.retry<0||t.retry>10))throw new TypeError(`${r}: retry is a whole number, 0 to 10 (got ${String(t.retry)})`);let o={name:t.name,schedule:t.schedule.trim().split(/\s+/).join(" "),timeout:t.timeout??30,retries:t.retry??5};return s=>{if(typeof s.prototype.run!="function")throw new TypeError(`${r} on ${s.name}: a job is a class with a run(meta) method`);if(Object.prototype.hasOwnProperty.call(s,ue))throw new TypeError(`${r} on ${s.name}: a class is one job`);Object.defineProperty(s,ue,{value:o,enumerable:!1}),oe().add(s)}}var un=["stripe","github","twilio","sendgrid","slack","discord","livekit"],Sr=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;function ia(e){return t=>{let r=`@Webhook on ${t.name}`,n=e??{};if(typeof n.name!="string"||n.name==="")throw new TypeError(`${r}: name is required \u2014 the last segment of its URL, /webhooks/<name>, which the sender is configured with`);if(!Sr.test(n.name))throw new TypeError(`${r}: name "${n.name}" is the last segment of its URL: lowercase letters, digits and dashes, starting and ending with one of those`);if(n.name==="palbase")throw new TypeError(`${r}: /webhooks/palbase is the platform's own deliveries (an @On outside a @Webhook class takes them); this webhook is served under another name`);if(n.provider===void 0&&n.signature===void 0)throw new TypeError(`${r}: a provider or a signature is required \u2014 an endpoint that verifies nothing takes forged deliveries`);if(n.provider!==void 0&&n.signature!==void 0)throw new TypeError(`${r}: a provider and a signature are alternatives \u2014 keep the one that describes the sender`);if(n.provider!==void 0&&!un.includes(n.provider))throw new TypeError(`${r}: provider "${String(n.provider)}" is not one of ${un.join(", ")} \u2014 another sender's scheme is spelled out as signature`);if(n.signature!==void 0&&Or(n.signature,r),typeof n.secret?.env!="string"||n.secret.env==="")throw new TypeError(`${r}: secret: { env: "VAR_NAME" } is required \u2014 the env var holding the signing secret`);let o=T(t,he)??[];if(o.length===0)throw new TypeError(`${r}: at least one @On is required \u2014 a webhook that runs nothing for every delivery is a mistake`);let s=new Set;for(let{event:a,bucket:i}of o){if(s.has(a))throw new TypeError(`${r}: @On("${a}") is declared twice; one method takes an event`);if(i!==void 0)throw new TypeError(`${r}: @On("${a}", { bucket: "${i}" }) \u2014 a bucket keeps a handler to the project's storage events, and ${n.name}'s are a third party's`);s.add(a)}X(t,Oe,()=>({name:n.name,provider:n.provider,signature:n.signature&&{...n.signature},secret:{env:n.secret.env},events:o.map(({event:a,fn:i})=>({event:a,fn:i}))})),oe().add(t)}}function Or(e,t){if(typeof e.header!="string"||e.header==="")throw new TypeError(`${t}: signature.header is required \u2014 the header the signature arrives in`);if(e.prefix!==void 0&&typeof e.prefix!="string")throw new TypeError(`${t}: signature.prefix is the text before the signature, like "sha256="`);if(e.algo!=="hmac-sha256"&&e.algo!=="hmac-sha1")throw new TypeError(`${t}: signature.algo "${String(e.algo)}" is not hmac-sha256 or hmac-sha1`);if(e.encoding!=="hex"&&e.encoding!=="base64")throw new TypeError(`${t}: signature.encoding "${String(e.encoding)}" is not hex or base64`);if(typeof e.signs!="string"||!e.signs.includes("{body}"))throw new TypeError(`${t}: signature.signs must contain {body} \u2014 a signature of a constant signs nothing`);if(e.signs.includes("{ts}")&&(typeof e.timestampHeader!="string"||e.timestampHeader===""))throw new TypeError(`${t}: signature.signs uses {ts} but no timestampHeader says where to read it`)}function T(e,t){return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0}function da(){return[...oe()].filter(e=>T(e,Re)!==void 0)}function ca(e){return(T(e,Se)??[]).map(t=>({method:t.method,path:t.subpath,fnName:t.fn,options:{...t.options,...t.upload!==void 0?{uploadConfig:t.upload}:{}}}))}var Et="/_palbase/storage/upload/authorize",fn="/_palbase/storage/upload/complete",Rt="/_palbase/realtime/rooms";var _r=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Te(e){if(!_r(e)||typeof e.role!="string"||e.role===""||e.id!==void 0&&typeof e.id!="string"||e.session!==void 0&&typeof e.session!="string")return;let t={role:e.role};return typeof e.id=="string"&&e.id!==""&&(t.id=e.id),typeof e.session=="string"&&e.session!==""&&(t.session=e.session),t.id&&typeof e.email=="string"&&e.email!==""&&(t.email=e.email),t.id&&typeof e.emailVerified=="boolean"&&(t.emailVerified=e.emailVerified),t}function mn(e){return typeof e=="string"&&e!==""&&e.length<=64?e:void 0}function pn(e,t){return e.id?`u:${e.id}`:e.session?`s:${e.session}`:t?`a:${t}`:`r:${e.role}`}function Qe(e){return e?.id?{sub:e.id,role:e.role,...e.session?{session_id:e.session}:{}}:null}var xr=/^[a-z][a-z0-9-]{1,62}$/,hn=1024,Tr=new Set(["userId","uploadId","filename"]);function pa(e,t){if(typeof e!="string")throw new TypeError("@Upload(path, { bucket, pathTemplate }): path is a string");let r=t??{};if(typeof t!="object"||t===null)throw new TypeError(`@Upload("${e}"): the second argument is { bucket, pathTemplate } \u2014 where its files go`);if(typeof r.bucket!="string"||r.bucket==="")throw new TypeError(`@Upload("${e}"): bucket is required \u2014 the name of the bucket its files go to`);if(!xr.test(r.bucket))throw new TypeError(`@Upload("${e}"): bucket "${r.bucket}" is no bucket's name \u2014 lowercase letters, digits and dashes, starting with a letter, 2 to 63 long`);if(typeof r.pathTemplate!="string"||r.pathTemplate==="")throw new TypeError(`@Upload("${e}"): pathTemplate is required \u2014 the path each file is stored under, like "{userId}/{uploadId}-{filename}"`);let n=Ar(r.pathTemplate);if(n)throw new TypeError(`@Upload("${e}"): pathTemplate "${r.pathTemplate}" ${n}`);let o={bucket:r.bucket,pathTemplate:r.pathTemplate},s={...r.auth!==void 0?{auth:r.auth}:{},...r.rateLimit!==void 0?{rateLimit:r.rateLimit}:{}};return(a,i,c)=>{if(typeof i!="string"||c===void 0||typeof c.value!="function")throw new TypeError(`@Upload("${e}") goes on a method`);X(a.constructor,Se,()=>[]).push({method:"POST",subpath:e,fn:i,options:s,upload:o})}}function ha(){return te("uploadedObject")}function Ar(e){for(let r of e.matchAll(/\{([^{}]*)\}/g))if(!Tr.has(r[1]))return`names {${r[1]}}: its tokens are {userId}, {uploadId} and {filename}`;if(/[{}]/.test(e.replace(/\{(userId|uploadId|filename)\}/g,"")))return"has a brace of no token: its tokens are {userId}, {uploadId} and {filename}";let t=e.replace(/\{(userId|uploadId|filename)\}/g,"x");if(!gn(t))return"is no path storage keeps: segments separated by /, none empty, . or .., no control character, at most 1024 bytes"}function gn(e){if(e===""||new TextEncoder().encode(e).byteLength>hn)return!1;for(let t=0;t<e.length;t++){let r=e.charCodeAt(t);if(r<32||r===127)return!1}return e.split("/").every(t=>t!==""&&t!=="."&&t!=="..")}function Pr(e,t){return e.replace(/\{(userId|uploadId|filename)\}/g,(r,n)=>jr(n==="userId"?t.userId??"anonymous":n==="uploadId"?t.uploadId:t.filename??"file"))}function jr(e){let t=e.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200F\u2028-\u202E\u2060-\u2069\uFEFF]/g,"").replace(/[/\\]/g,"-").replace(/\.{2,}/g,".").replace(/^[\s.]+/,"").trimEnd();return t===""?"file":Array.from(t).slice(0,200).join("")}function yn(e,t){let r=Pr(e,t);return gn(r)?{path:r}:{problem:`the file's name makes its path longer than storage keeps (${hn} bytes)`}}function wn(e){let t=new Map;for(let r of e)r.meta.upload&&t.set(r.controller,(t.get(r.controller)??new Set).add(r.fn));for(let r of e){let n=`${r.controller.name}.${r.fn}`;if(!r.meta.upload){if(t.get(r.controller)?.has(r.fn))throw new TypeError(`${n}: @Upload and @${r.method[0]}${r.method.slice(1).toLowerCase()} on one method \u2014 an upload's handler runs with the stored object, which an ordinary route has none of; give each its own method`);if(r.params.some(s=>s.kind==="uploadedObject"))throw new TypeError(`${n}: @UploadedObject() on ${r.id}, which is no @Upload route \u2014 only an upload has a stored object`);continue}let o=r.params.find(s=>s.kind==="headers"||s.kind==="req"||s.kind==="client");if(o){let s=o.kind==="headers"?"Headers":o.kind==="req"?"Req":"Client";throw new TypeError(`${n}: @${s}() on an @Upload route \u2014 the client's request reaches storage, which forwards none of its headers; the handler is given the caller (@User), the body (@Body) and the stored object`)}}}var St=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function bn(e,t){if(!St(t))return"a call is a JSON object";let{route:r,method:n,query:o,uploadId:s}=t;if(typeof r!="string"||!r.startsWith("/"))return"route is the upload route's path";if(typeof n!="string"||n==="")return"method is the route's";if(typeof o!="string")return'query is the query string, "" for none';if(typeof s!="string"||s==="")return"uploadId is the upload's id";let a=Te(t.user);if(!a)return"user is { id?, session?, role }";let i=mn(t.client);if(e==="authorize")return t.filename!==void 0&&typeof t.filename!="string"?"filename is the file's name":{route:r,method:n,query:o,uploadId:s,user:a,...i?{client:i}:{},filename:t.filename??"",...Object.hasOwn(t,"body")?{body:t.body??null}:{}};let c=Cr(t.uploadedObject);return c?c.uploadId!==s?"uploadedObject is another upload's":{route:r,method:n,query:o,uploadId:s,user:a,...i?{client:i}:{},filename:"",uploadedObject:c,body:t.body??null}:"uploadedObject is the stored object: { uploadId, path, bucket, size, contentType, checksum, width?, height?, thumbhash?, variants }"}function Cr(e){if(!St(e))return;let{uploadId:t,path:r,bucket:n,size:o,contentType:s,checksum:a,width:i,height:c,thumbhash:u,variants:f}=e;if(!(typeof t!="string"||typeof r!="string"||typeof n!="string"||typeof s!="string"||typeof a!="string")&&!(typeof o!="number"||!Number.isInteger(o)||o<0)&&!(i!==void 0&&typeof i!="number"||c!==void 0&&typeof c!="number"||u!==void 0&&typeof u!="string")&&!(!St(f)||!Object.values(f).every(y=>typeof y=="string")))return{uploadId:t,path:r,bucket:n,size:o,contentType:s,checksum:a,...i!==void 0?{width:i}:{},...c!==void 0?{height:c}:{},...u!==void 0?{thumbhash:u}:{},variants:{...f}}}import{markData as Mr}from"palgres";var ge=Symbol.for("palbase.backend.room"),Pe=Symbol.for("palbase.backend.roomHooks"),Dr=6e4,Ae=255,Ur=["roles:","flags:","messaging:","debug:"],xt=e=>new TextEncoder().encode(e).byteLength,vn=e=>typeof e=="object"&&e!==null&&typeof e["~standard"]?.validate=="function";function Nr(e){if(e.includes("/"))return`channel patterns are colon-separated, not slash-separated. Write "${e.replace(/\//g,":")}" \u2014 a slash matches no live topic.`;if(xt(e)>Ae)return`a channel is ${Ae} bytes at most`;if(/[\x00-\x1F\x7F]/.test(e))return"a channel has no control character";if(e==="phoenix")return"phoenix is the socket's own";let t=Ur.find(n=>e.startsWith(n));if(t)return`${t} channels are the platform's`;let r=new Set;for(let n of e.split(":")){if(n==="")return"empty segment \u2014 every segment must be non-empty.";if(/[{}]/.test(n)){if(n==="{}")return'"{}" names no parameter.';if(!/^\{[^{}]+\}$/.test(n))return`"${n}" \u2014 a parameter is a whole segment, {name}`;if(r.has(n))return`parameter "${n}" appears twice.`;r.add(n)}}}function kn(e){if(typeof e!="string"||e==="")return"is a name";if(xt(e)>Ae)return`is ${Ae} bytes at most`}function ka(e,t){if(typeof e!="string"||e==="")throw new TypeError('@Room(pattern, { events }): pattern is the channels it is, like "ai:{sessionId}"');let r=Nr(e);if(r)throw new TypeError(`@Room("${e}"): ${r}`);let n=t??{};if(typeof n.events!="object"||n.events===null||Array.isArray(n.events))throw new TypeError(`@Room("${e}"): events is required \u2014 what the room sends, by name, each its payload's schema ({} for none)`);for(let[a,i]of Object.entries(n.events)){let c=kn(a);if(c)throw new TypeError(`@Room("${e}"): event "${a}" ${c}`);if(!vn(i))throw new TypeError(`@Room("${e}"): event "${a}" is a Standard Schema (a zod, valibot or arktype schema) \u2014 its payload's`)}if(n.graceMs!==void 0&&(!Number.isSafeInteger(n.graceMs)||n.graceMs<=0))throw new TypeError(`@Room("${e}"): graceMs is whole milliseconds, more than 0 (got ${String(n.graceMs)})`);let o={...n.events},s=n.graceMs??Dr;return a=>{let i=X(a,Pe,Tt);X(a,ge,()=>({pattern:e,events:o,graceMs:s,hooks:{...i.hooks},messages:Object.assign(Object.create(null),i.messages)})),oe().add(a)}}var Tt=()=>({hooks:Object.create(null),messages:Object.create(null)});function Ue(e){let t=`On${e[0].toUpperCase()}${e.slice(1)}`;return()=>(r,n,o)=>{if(typeof n!="string"||o===void 0||typeof o.value!="function")throw new TypeError(`@${t}() goes on a method`);if(typeof r=="function")throw new TypeError(`@${t}() on static ${r.name}.${n}: a room's methods are its instance's`);let s=X(r.constructor,Pe,Tt),a=s.hooks[e];if(a!==void 0&&a!==n)throw new TypeError(`@${t}() is declared twice in one room (${a} and ${n}). A room has one of each hook.`);s.hooks[e]=n,oe().add(r.constructor)}}var $a=Ue("authorize"),Ea=Ue("first"),Ra=Ue("join"),Sa=Ue("leave"),Oa=Ue("empty");function _a(e,t){let r=kn(e);if(r)throw new TypeError(`@OnMessage(name, schema): name ${r}`);if(!vn(t))throw new TypeError(`@OnMessage("${e}", schema): schema is a Standard Schema (a zod, valibot or arktype schema)`);return(n,o,s)=>{if(typeof o!="string"||s===void 0||typeof s.value!="function")throw new TypeError(`@OnMessage("${e}") goes on a method`);if(typeof n=="function")throw new TypeError(`@OnMessage("${e}") on static ${n.name}.${o}: a room's methods are its instance's`);let a=X(n.constructor,Pe,Tt),i=a.messages[e];if(i!==void 0&&i.fn!==o)throw new TypeError(`@OnMessage("${e}") is declared twice in one room (${i.fn} and ${o}).`);a.messages[e]={fn:o,schema:t},oe().add(n.constructor)}}function Ir(e){return T(e,ge)}function Lr(e,t){let r=e.split(":"),n=t.split(":");if(r.length!==n.length)return;let o=[];for(let s=0;s<r.length;s++){let a=r[s];if(a.length>=2&&a.startsWith("{")&&a.endsWith("}")){if(n[s]==="")return;o.push([a.slice(1,-1),n[s]])}else if(a!==n[s])return}return Object.fromEntries(o)}var qr=1e4,Hr=1e3,Jr=100,At=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ae=(e,t,r,n)=>({status:e,code:t,message:r,...n!==void 0?{retryAfter:n}:{}}),Br=new Set(["first","join","leave","empty"]);function $n(e,t){let r=new Map,n=new Map;for(let{cls:b,instance:$}of e){let w=Ir(b),R=w.pattern.split(":").map(C=>C.startsWith("{")?"{}":C).join(":"),P=n.get(R);if(P!==void 0)throw new TypeError(`@Room("${w.pattern}") on ${b.name}: ${r.get(P)?.cls.name}'s "${P}" is the same channels \u2014 one room is told of them; keep one`);n.set(R,w.pattern);for(let[C,I]of[...Object.entries(w.hooks),...Object.entries(w.messages).map(([L,U])=>[`message ${L}`,U.fn])])if(typeof $[I]!="function")throw new TypeError(`@Room("${w.pattern}") on ${b.name}: its ${C} is ${I}, which is no method of it`);r.set(w.pattern,{cls:b,instance:$,room:w})}let o=new Map,s=new Set,a=new Set,i=new _t(t.broadcast),c=b=>{let $=o.get(b);return $||($=new AbortController,o.set(b,$)),$},u=(b,$)=>{$?.abort(),o.get(b)===$&&o.delete(b)};function f(b,$,w,R,P,C,I){let L=R?.signal??AbortSignal.abort(),U=`${b.cls.name} (${$})`;return{room:$,params:Object.freeze({...w}),signal:L,count:P,user:C,emit:(M,q)=>i.send({topic:$,event:M,payload:q??{},...I!==void 0?{conn_id:I}:{}},U),owner:{hold(M){se.exit(async()=>{try{await M(L)}catch(q){L.aborted||S.error(`[palbase] ${U}: a task owner.hold ran failed`,{error:q})}}).catch(()=>{})},release:()=>u($,R)}}}function y(b){let{room:$,channel:w}=b;if(typeof $!="string"||typeof w!="string")return ae(400,"bad_request","A room's call names its room (the pattern) and its channel");let R=r.get($);return R?{entry:R,channel:w,params:Lr($,w)}:ae(404,"not_found",`This app declares no room "${$}"`)}let E=(b,$)=>ae(400,"bad_request",`"${$}" is not a channel of the room "${b}"`);async function N(b,$){let w=y(b);if("status"in w)return w;let{entry:R,channel:P,params:C}=w,I={status:200,body:{subscribe:!1,publish:!1}};if(!C)return S.warn(`[palbase] ${R.cls.name}: realtime asked about "${P}", which is not a channel of the room "${R.room.pattern}"; the join is refused`),I;let L=Te(b.user),U=L?.id;if(!U)return I;let M=R.room.hooks.authorize;if(!M)return I;let q,re;try{q=await t.run(L,`${R.cls.name}.${M}`,$,async()=>R.instance[M]({user:{id:U},params:Object.freeze({...C})})),re=zr(q)}catch(Q){if(t.isOutage(Q)||$?.aborted)throw Q;return S.error(`[palbase] ${R.cls.name}.${M} (@OnAuthorize of ${P}) failed; the join is refused`,{error:Q}),I}return re==="malformed"?(S.warn(`[palbase] ${R.cls.name}.${M} (@OnAuthorize of ${P}) answered ${Fr(q)}, which is no grant (true, { read, write } or null); the join is refused`),I):{status:200,body:re}}async function g(b,$){let w=y(b);if("status"in w)return w;if(!w.params)return E(w.entry.room.pattern,w.channel);let R=Te(b.user);if(!R?.id||typeof b.event!="string")return ae(400,"bad_request","A message names its member (user) and its event");let P=Object.hasOwn(w.entry.room.messages,b.event)?w.entry.room.messages[b.event]:void 0;if(!P)return{status:200,body:{ok:!1,reason:En(`room "${w.channel}" declares no message "${b.event}"`,Ot)}};let C=await P.schema["~standard"].validate(Mr(b.payload??{}));if(C.issues)return{status:200,body:{ok:!1,reason:Wr(C.issues)}};let I=c(w.channel),L={...f(w.entry,w.channel,w.params,I,0,{id:R.id}),payload:C.value};try{await t.run(R,`${w.entry.cls.name}.${P.fn}`,$,async()=>w.entry.instance[P.fn](L))}catch(U){if(t.isOutage(U))throw U;return $?.aborted||S.error(`[palbase] ${w.entry.cls.name}.${P.fn} (@OnMessage "${b.event}" of ${w.channel}) failed`,{error:U}),{status:200,body:{ok:!1,reason:"handler_failed"}}}return{status:200,body:{ok:!0}}}async function A(b,$){let w=y(b);if("status"in w)return w;if(!w.params)return E(w.entry.room.pattern,w.channel);let R=b.event;if(typeof R!="string"||!Br.has(R))return ae(400,"bad_request","A room's moment is first, join, leave or empty");let P=typeof b.count=="number"&&Number.isInteger(b.count)&&b.count>=0?b.count:void 0;if(P===void 0)return ae(400,"bad_request","A room's moment says its count of members");let C=R==="join"||R==="leave",I=C?Te(b.user):void 0,L=C?b.connId:void 0;if(C&&(!I?.id||typeof L!="string"||L===""))return ae(400,"bad_request",`A ${R} names its member: user and connId`);let U=`${R}\0${w.channel}\0${typeof L=="string"?L:""}`;if(C&&s.has(U))return{status:204};if(a.has(U))return ae(503,"in_progress","This moment of the room is being handled",5);a.add(U);try{let M=w.entry.room.hooks[R],q;if(R==="empty"?(q=o.get(w.channel),u(w.channel,q)):q=R==="leave"?o.get(w.channel):c(w.channel),M){let re=f(w.entry,w.channel,w.params,q,P,{id:I?.id??""},R==="join"?L:void 0);try{await t.run(I,`${w.entry.cls.name}.${M}`,$,async()=>w.entry.instance[M](re))}catch(Q){if(t.isOutage(Q))throw Q;return $?.aborted||S.error(`[palbase] ${w.entry.cls.name}.${M} (${R} of ${w.channel}) failed; realtime tells it again`,{error:Q}),ae(500,"handler_failed",`The room's ${R} could not be handled`)}}return C&&(s.add(U),s.size>qr&&s.delete(s.values().next().value)),{status:204}}finally{a.delete(U)}}return{declarations:[...r.values()].map(b=>b.room),async serve(b,$,w){return At($)?b==="authorize"?N($,w):b==="message"?g($,w):b==="lifecycle"?A($,w):ae(404,"not_found",`No room call ${JSON.stringify(b)}`):ae(400,"bad_request","A room's call is a JSON object")},close(){for(let b of o.values())b.abort();o.clear()}}}function zr(e){let t={subscribe:!1,publish:!1};if(e==null||e===!1)return t;if(e===!0)return{subscribe:!0,publish:!0};if(!At(e))return"malformed";let r=Object.hasOwn(e,"read"),n=Object.hasOwn(e,"write");if(r&&typeof e.read!="boolean"||n&&typeof e.write!="boolean"||!r&&!n)return"malformed";let o=r?e.read:void 0,s=n?e.write:void 0;return o===!1?t:{subscribe:!0,publish:s!==!1}}function Fr(e){return Array.isArray(e)?"an array":At(e)?Object.hasOwn(e,"read")||Object.hasOwn(e,"write")?"an object whose read or write is not true or false":"an object that says neither read nor write":typeof e=="function"?"a function":typeof e=="string"?"a string":`${typeof e} ${String(e)}`}var Kr=20,Ot=256;function Wr(e){let t="";for(let r of e.slice(0,Kr)){let n=(r.path??[]).slice(0,8).map(s=>String(typeof s=="object"&&s!==null&&"key"in s?s.key:s).slice(0,64)).join("."),o=n===""?r.message:`${n}: ${r.message}`;if(t=t===""?o:`${t}; ${o}`,Buffer.byteLength(t)>=Ot)break}return En(t,Ot)}function En(e,t){if(Buffer.byteLength(e)<=t)return e;let r="";for(let n of e){if(Buffer.byteLength(r+n)>t-3)break;r+=n}return`${r}\u2026`}var _t=class{constructor(t){this.broadcast=t}broadcast;queues=new Map;dropped=new Map;send(t,r){if(typeof t.event!="string"||t.event===""||xt(t.event)>Ae){S.warn(`[palbase] ${r}: emit(${JSON.stringify(t.event)}) is not sent \u2014 an event's name is 1 to ${Ae} bytes`);return}try{JSON.stringify(t.payload)}catch(s){S.warn(`[palbase] ${r}: emit("${t.event}") is not sent \u2014 its payload is not JSON`,{error:s});return}let n=this.queues.get(t.topic);if(n){n.length>=Hr?this.dropped.set(t.topic,(this.dropped.get(t.topic)??0)+1):n.push(t);return}let o=[t];this.queues.set(t.topic,o),se.exit(()=>this.drain(t.topic,o,r))}async drain(t,r,n){for(;;){if(r.length===0){this.queues.delete(t);return}let o=r.splice(0,Jr);try{await this.broadcast(o)}catch(a){S.warn(`[palbase] ${n}: ${o.length} event(s) to ${t} were not sent`,{error:a})}let s=this.dropped.get(t);s&&(this.dropped.delete(t),S.warn(`[palbase] ${n}: ${s} event(s) to ${t} dropped \u2014 realtime took them slower than they were emitted`))}}};import{createHash as Pt,createHmac as Vr,createPublicKey as _n,timingSafeEqual as Yr,verify as xn}from"node:crypto";function Pa(e){let t=T(e,Oe);if(!t)throw new TypeError(`${e.name} is not a @Webhook`);return{name:t.name,provider:t.provider,secretEnv:t.secret.env,events:t.events.map(r=>r.event)}}function Tn(e,t,r,n={}){let o=new Map,s=[];for(let a of e){let i=T(a,Oe),c=o.get(i.name);if(c)throw new TypeError(`@Webhook "${i.name}" is declared by ${c.cls.name} and by ${a.name}: /webhooks/${i.name} is one endpoint`);let u=`@Webhook "${i.name}" (${a.name})`,f=r[i.secret.env],y;if(n.secrets!==!1)if(f===void 0||f==="")s.push(`${u} reads its signing secret from ${i.secret.env}, which is not set`);else try{y=Gr(i,f)}catch(g){s.push(`${u}: ${i.secret.env} ${g.message}`)}let E=t(a),N=new Map(i.events.map(({event:g,fn:A})=>[g,{name:`${a.name}.${A}`,call:(b,$)=>E[A](b,$)}]));o.set(i.name,{name:i.name,cls:a,provider:i.provider,signatureHeader:i.signature?.header,secretEnv:i.secret.env,scheme:y,events:N})}if(s.length>0)throw new Error(`[palbase] the app cannot start:
3
3
  - ${s.join(`
4
4
  - `)}`);return o}function An(e,t){return`https://${(e.headers.get("host")??t.host).toLowerCase()}${t.pathname}${t.search}`}var je=1024,Rn=1024*je;function Gr(e,t){if(e.signature)return ye(void 0,e.signature.header,1/0,io(e.signature,t));switch(e.provider){case"stripe":return ye("stripe","stripe-signature",512*je,Qr(t));case"github":return ye("github","x-hub-signature-256",25*Rn,eo(t));case"slack":return ye("slack","x-slack-signature",64*je,to(t));case"discord":return ye("discord","x-signature-ed25519",64*je,no(t));case"twilio":return{header:"x-twilio-signature",maxBytes:r=>Math.min(r,64*je),check:oo(t)};case"sendgrid":return ye("sendgrid","x-twilio-email-event-webhook-signature",Rn,so(t));case"livekit":return ye("livekit","authorization",512*je,ao(t));default:throw new TypeError(`names no scheme: provider ${String(e.provider)}`)}}function ye(e,t,r,n){return{header:t,maxBytes:o=>Math.min(o,r),check:(o,s)=>n(o,s)??Pn(e,o)}}function Pn(e,t){let r=jt(t.body),n;try{n=JSON.parse(r)}catch{if(n=r,e==="slack"){let o=new URLSearchParams(r).get("payload");if(o!==null)try{n=JSON.parse(o)}catch{}}}return{type:jn(e,t.headers,n),event:n,...Zr(e,t,n)}}function jn(e,t,r){switch(e){case"github":{let n=t.get("x-github-event")??"",o=we(r,"action");return n!==""&&o!==""?`${n}.${o}`:n}case"discord":{let n=Dn(r)?r.type:void 0;return n===1?"PING":n===2?"INTERACTION_CREATE":Number.isInteger(n)?`type_${String(n)}`:""}case"sendgrid":return"event_batch";case"twilio":return we(r,"EventType");case"livekit":return we(r,"event");default:return we(r,"type")}}function Zr(e,t,r){let n=o=>o?{id:o}:{};switch(e){case"stripe":case"discord":case"livekit":return n(we(r,"id"));case"slack":return n(we(r,"event_id"));case"github":{let o=t.headers.get("x-github-delivery");return o?{id:`${o}:${Cn(t.body)}`}:{}}case"sendgrid":return Array.isArray(r)?{ids:r.map(o=>we(o,"sg_event_id")||void 0)}:{};default:return{}}}var Xr=300;function Qr(e){return(t,r)=>{let n=t.headers.get("stripe-signature");if(!n)return"missing_signature";let o,s=[];for(let c of n.split(",")){let u=c.indexOf("=");if(u<=0)continue;let f=c.slice(0,u).trim(),y=c.slice(u+1).trim();if(f==="t"){if(o!==void 0)return"malformed_signature";o=y}else if(f==="v1"){let E=ne(y,"hex");if(!E)return"malformed_signature";s.push(E)}}let a=Ne(o);if(a===void 0||s.length===0)return"malformed_signature";if(Ie(a,r))return"stale_timestamp";let i=Ce("sha256",e,`${o}.`,t.body);return s.some(c=>le(c,i))?void 0:"signature_mismatch"}}function eo(e){return t=>{let r=t.headers.get("x-hub-signature-256");if(!r)return"missing_signature";let n=r.startsWith("sha256=")?ne(r.slice(7),"hex"):void 0;return n?le(n,Ce("sha256",e,t.body))?void 0:"signature_mismatch":"malformed_signature"}}function to(e){return(t,r)=>{let n=t.headers.get("x-slack-signature");if(!n)return"missing_signature";let o=t.headers.get("x-slack-request-timestamp")?.trim(),s=Ne(o),a=n.startsWith("v0=")?ne(n.slice(3),"hex"):void 0;return s===void 0||!a?"malformed_signature":Ie(s,r)?"stale_timestamp":le(a,Ce("sha256",e,`v0:${o}:`,t.body))?void 0:"signature_mismatch"}}function no(e){let t=ne(e,"hex");if(!t||t.byteLength!==32)throw new TypeError("is not an Ed25519 public key: the application's PUBLIC KEY, 64 hex characters");let r=_n({key:{kty:"OKP",crv:"Ed25519",x:Buffer.from(t).toString("base64url")},format:"jwk"});return(n,o)=>{let s=n.headers.get("x-signature-ed25519");if(!s)return"missing_signature";let a=n.headers.get("x-signature-timestamp")??void 0,i=Ne(a),c=ne(s,"hex");return i===void 0||!c||c.byteLength!==64?"malformed_signature":Ie(i,o)?"stale_timestamp":xn(null,Mn(a,n.body),r,c)?void 0:"signature_mismatch"}}var ro=1e3;function oo(e){return t=>{let r=t.headers.get("x-twilio-signature");if(!r)return"missing_signature";let n=ne(r.trim(),"base64");if(!n||n.byteLength!==20)return"malformed_signature";let o;try{o=new URL(t.url)}catch{return"signature_mismatch"}let s=o.searchParams.get("bodySHA256"),a="",i;if(s!==null){if(!le(Buffer.from(s.toLowerCase()),Buffer.from(Pt("sha256").update(t.body).digest("hex"))))return"signature_mismatch"}else{let N=1;for(let b of t.body)if(b===38&&++N>ro)return"malformed_signature";let g=new Map;for(let[b,$]of new URLSearchParams(jt(t.body))){let w=g.get(b);w||g.set(b,w=new Set),w.add($)}let A=[];for(let b of[...g.keys()].sort()){let $=[...g.get(b)].sort();for(let w of $)a+=b+w;A.push([b,$.length===1?$[0]:$])}i=Object.fromEntries(A)}let c=o.protocol==="https:"?"443":"80",u=`${o.protocol}//${o.hostname}${o.pathname}${o.search}`,f=`${o.protocol}//${o.hostname}:${o.port||c}${o.pathname}${o.search}`;if(![u,f].some(N=>le(n,Ce("sha1",e,N,a))))return"signature_mismatch";let y=t.headers.get("i-twilio-idempotency-token"),E=y?{id:`${y}:${Cn(`${u}
5
5
  ${a}`)}`}:{};return i?{type:jn("twilio",t.headers,i),event:i,...E}:{...Pn("twilio",t),...E}}}function so(e){let t;try{let r=ne(e,"base64");if(!r)throw new Error;t=_n({key:Buffer.from(r),format:"der",type:"spki"})}catch{throw new TypeError("is not the Event Webhook's verification key: the base64 public key SendGrid shows")}if(t.asymmetricKeyType!=="ec"||t.asymmetricKeyDetails?.namedCurve!=="prime256v1")throw new TypeError("is not the Event Webhook's verification key: an ECDSA P-256 public key");return(r,n)=>{let o=r.headers.get("x-twilio-email-event-webhook-signature");if(!o)return"missing_signature";let s=r.headers.get("x-twilio-email-event-webhook-timestamp")?.trim(),a=Ne(s),i=ne(o.trim(),"base64");return a===void 0||!i?"malformed_signature":Ie(a,n)?"stale_timestamp":xn("sha256",Mn(s,r.body),{key:t,dsaEncoding:"der"},i)?void 0:"signature_mismatch"}}var Sn=60;function ao(e){return(t,r)=>{let n=t.headers.get("authorization");if(!n)return"missing_signature";let o=n.split(".");if(o.length!==3)return"malformed_signature";let s=On(ne(o[0],"base64url")),a=ne(o[2],"base64url");if(s?.alg!=="HS256"||!a)return"malformed_signature";if(!le(a,Ce("sha256",e,`${o[0]}.${o[1]}`)))return"signature_mismatch";let i=On(ne(o[1],"base64url"));if(typeof i?.exp!="number")return"malformed_signature";if(r>i.exp+Sn||typeof i.nbf=="number"&&r<i.nbf-Sn)return"stale_timestamp";let c=typeof i.sha256=="string"?ne(i.sha256,"base64"):void 0;return c&&le(c,Pt("sha256").update(t.body).digest())?void 0:"signature_mismatch"}}function io(e,t){let r=e.signs.split(/(\{body\}|\{ts\})/),n=e.algo==="hmac-sha1"?"sha1":"sha256";return(o,s)=>{let a=o.headers.get(e.header);if(!a)return"missing_signature";if(e.prefix){if(!a.startsWith(e.prefix))return"malformed_signature";a=a.slice(e.prefix.length)}let i="";if(r.includes("{ts}")){i=o.headers.get(e.timestampHeader)?.trim()??"";let u=Ne(i);if(u===void 0)return"malformed_signature";if(Ie(u,s))return"stale_timestamp"}let c=ne(a.trim(),e.encoding);return c?le(c,Ce(n,t,...r.map(u=>u==="{body}"?o.body:u==="{ts}"?i:u)))?void 0:"signature_mismatch":"malformed_signature"}}var co=new TextEncoder;function Ce(e,t,...r){let n=Vr(e,t);for(let o of r)n.update(o);return n.digest()}function Cn(e){return Pt("sha256").update(e).digest("hex")}function Mn(e,t){return Buffer.concat([co.encode(e),t])}function le(e,t){return e.byteLength===t.byteLength&&Yr(e,t)}var uo={hex:/^(?:[0-9a-fA-F]{2})+$/,base64:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/,base64url:/^[A-Za-z0-9_-]+$/};function ne(e,t){return uo[t].test(e)?Buffer.from(e,t):void 0}function Ne(e){return e!==void 0&&/^[0-9]{1,12}$/.test(e)?Number(e):void 0}function Ie(e,t){return Math.abs(t-e)>Xr}function jt(e){return new TextDecoder().decode(e)}function On(e){if(e)try{return JSON.parse(jt(e))}catch{return}}function Dn(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function we(e,t){let r=Dn(e)?e[t]:void 0;return typeof r=="string"?r:""}import"reflect-metadata";var J=class extends Error{kind;path;constructor(t,r,n,o,s){super(`
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{c as f}from"./4UPL27ED.js";var A=512,b=8,x=64,O=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/,p={"i-klingon":"tlh","en-gb-oed":"en-GB-oxendict","sgn-be-fr":"sfb","zh-cmn-hans":"cmn-Hans","zh-yue":"yue","hy-arevela":"hy-arevela"};function m(e){let n=e.indexOf("-");return n>0?e.slice(0,n):e}function _(e){let n=e.split("-"),r=(n[0]??"").toLowerCase();return r==="mo"&&n.length===1?"ro-MD":r==="tl"?(n[0]="fil",n.join("-")):r==="sh"?(n[0]="sr",n.length>1&&/^[A-Za-z]{4}$/.test(n[1]??"")||n.splice(1,0,"Latn"),n.join("-")):e}function E(e){let n=e.trim().replaceAll("_","-");if(n===""||n==="*"||n.length>x)return;let r=n.toLowerCase(),s=Object.hasOwn(p,r)?p[r]:void 0;if(s===void 0){try{s=Intl.getCanonicalLocales(_(n))[0]}catch{return}if(s===void 0)return}let i=m(s);if(!(i===""||i==="und"||i==="mul"))return s}function S(e,n){let r=[],s=i=>{i!==""&&!r.includes(i)&&r.push(i)};if(e!==null&&e.length<=A){let i=[];for(let o of e.split(",")){let t=o.trim();if(t==="")continue;let c=1,u=t.indexOf(";");if(u>=0){let l=t.slice(u+1);t=t.slice(0,u).trim();let a=l.indexOf("q=");if(a>=0){let d=l.slice(a+2).trim();if(O.test(d)){let g=Number(d);Number.isFinite(g)&&(c=g)}}}c>0&&i.push({tag:t,q:c,at:i.length})}i.sort((o,t)=>t.q-o.q||o.at-t.at);for(let{tag:o}of i.slice(0,b)){let t=E(o);t!==void 0&&(s(t),s(m(t)))}}return n!==void 0&&n!==""&&s(n),r}function L(e,n,r){let s=e.strings??{},i=Object.hasOwn(s,n),o=i?s[n]:null;for(let t of r){if(t===e.source){if(i)return{text:n,locale:t};continue}let c=o!=null&&Object.hasOwn(o,t)?o[t]:void 0;if(c!=null&&c.state!=="missing")return{text:c.value,locale:t}}return{text:n,locale:e.source}}var w=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;function h(e,n){return e.replace(w,(r,s,i,o)=>{if(o[i-1]==="{"||o[i+r.length]==="}")return r;let t=n!==void 0&&Object.hasOwn(n,s)?n[s]:void 0;return t==null?"":String(t)})}function T(e,n){let r=f.getStore(),s=r?.strings;if(s===void 0)return h(e,n);let{text:i,locale:o}=L(s,e,r?.locales??[s.source]),t=r?.usedLocales;return t!==void 0&&!t.includes(o)&&t.push(o),h(i,n)}export{S as a,T as b};
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{c as f}from"./M5B52IE6.js";var A=512,b=8,x=64,O=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/,p={"i-klingon":"tlh","en-gb-oed":"en-GB-oxendict","sgn-be-fr":"sfb","zh-cmn-hans":"cmn-Hans","zh-yue":"yue","hy-arevela":"hy-arevela"};function m(e){let n=e.indexOf("-");return n>0?e.slice(0,n):e}function _(e){let n=e.split("-"),r=(n[0]??"").toLowerCase();return r==="mo"&&n.length===1?"ro-MD":r==="tl"?(n[0]="fil",n.join("-")):r==="sh"?(n[0]="sr",n.length>1&&/^[A-Za-z]{4}$/.test(n[1]??"")||n.splice(1,0,"Latn"),n.join("-")):e}function E(e){let n=e.trim().replaceAll("_","-");if(n===""||n==="*"||n.length>x)return;let r=n.toLowerCase(),s=Object.hasOwn(p,r)?p[r]:void 0;if(s===void 0){try{s=Intl.getCanonicalLocales(_(n))[0]}catch{return}if(s===void 0)return}let i=m(s);if(!(i===""||i==="und"||i==="mul"))return s}function S(e,n){let r=[],s=i=>{i!==""&&!r.includes(i)&&r.push(i)};if(e!==null&&e.length<=A){let i=[];for(let o of e.split(",")){let t=o.trim();if(t==="")continue;let c=1,u=t.indexOf(";");if(u>=0){let l=t.slice(u+1);t=t.slice(0,u).trim();let a=l.indexOf("q=");if(a>=0){let d=l.slice(a+2).trim();if(O.test(d)){let g=Number(d);Number.isFinite(g)&&(c=g)}}}c>0&&i.push({tag:t,q:c,at:i.length})}i.sort((o,t)=>t.q-o.q||o.at-t.at);for(let{tag:o}of i.slice(0,b)){let t=E(o);t!==void 0&&(s(t),s(m(t)))}}return n!==void 0&&n!==""&&s(n),r}function L(e,n,r){let s=e.strings??{},i=Object.hasOwn(s,n),o=i?s[n]:null;for(let t of r){if(t===e.source){if(i)return{text:n,locale:t};continue}let c=o!=null&&Object.hasOwn(o,t)?o[t]:void 0;if(c!=null&&c.state!=="missing")return{text:c.value,locale:t}}return{text:n,locale:e.source}}var w=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;function h(e,n){return e.replace(w,(r,s,i,o)=>{if(o[i-1]==="{"||o[i+r.length]==="}")return r;let t=n!==void 0&&Object.hasOwn(n,s)?n[s]:void 0;return t==null?"":String(t)})}function T(e,n){let r=f.getStore(),s=r?.strings;if(s===void 0)return h(e,n);let{text:i,locale:o}=L(s,e,r?.locales??[s.source]),t=r?.usedLocales;return t!==void 0&&!t.includes(o)&&t.push(o),h(i,n)}export{S as a,T as b};
@@ -1,2 +1,2 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
2
- import{b as c,f as u}from"./MJPUCGXY.js";var l={attempts:3,maxWaitSeconds:30},y=new Set([429,502,503,504]);function x(e,t=l){let r=t.sleep??h;return{async send(o){let n=p(o),a=n.body,m=!a||a.kind!=="raw"||u(a.value),f=(n.method==="GET"||n.method==="HEAD"||n.idempotent===!0)&&m;for(let i=1;;i++)try{return await e.send(n)}catch(s){if(!f||i>=t.attempts||!(s instanceof c)||n.signal?.aborted)throw s;let d=b(s,i,t.maxWaitSeconds);if(d===void 0)throw s;await r(d*1e3,n.signal)}}}}function p(e){return e.idempotent?Object.entries(e.headers??{}).some(([r,o])=>r.toLowerCase()==="idempotency-key"&&o!==void 0&&o!==null&&o!=="")?e:{...e,headers:{...e.headers,"Idempotency-Key":w()}}:e}function b(e,t,r){return y.has(e.status)||e.code==="network_error"?e.retryAfter!==void 0?e.retryAfter<=r?e.retryAfter:void 0:Math.min(.5*2**(t-1),r)*(.8+Math.random()*.4):void 0}function h(e,t){return new Promise((r,o)=>{if(t?.aborted)return o(t.reason);let n=()=>{clearTimeout(a),o(t?.reason)},a=setTimeout(()=>{t?.removeEventListener("abort",n),r()},e);t?.addEventListener("abort",n,{once:!0})})}function w(){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();let e=crypto.getRandomValues(new Uint8Array(16));e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[...e].map(r=>r.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}export{l as a,x as b,w as c};
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
+ import{b as c,f as u}from"./UXRIXHHY.js";var l={attempts:3,maxWaitSeconds:30},y=new Set([429,502,503,504]);function x(e,t=l){let r=t.sleep??h;return{async send(o){let n=p(o),a=n.body,m=!a||a.kind!=="raw"||u(a.value),f=(n.method==="GET"||n.method==="HEAD"||n.idempotent===!0)&&m;for(let i=1;;i++)try{return await e.send(n)}catch(s){if(!f||i>=t.attempts||!(s instanceof c)||n.signal?.aborted)throw s;let d=b(s,i,t.maxWaitSeconds);if(d===void 0)throw s;await r(d*1e3,n.signal)}}}}function p(e){return e.idempotent?Object.entries(e.headers??{}).some(([r,o])=>r.toLowerCase()==="idempotency-key"&&o!==void 0&&o!==null&&o!=="")?e:{...e,headers:{...e.headers,"Idempotency-Key":w()}}:e}function b(e,t,r){return y.has(e.status)||e.code==="network_error"?e.retryAfter!==void 0?e.retryAfter<=r?e.retryAfter:void 0:Math.min(.5*2**(t-1),r)*(.8+Math.random()*.4):void 0}function h(e,t){return new Promise((r,o)=>{if(t?.aborted)return o(t.reason);let n=()=>{clearTimeout(a),o(t?.reason)},a=setTimeout(()=>{t?.removeEventListener("abort",n),r()},e);t?.addEventListener("abort",n,{once:!0})})}function w(){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();let e=crypto.getRandomValues(new Uint8Array(16));e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[...e].map(r=>r.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}export{l as a,x as b,w as c};
@@ -1,4 +1,4 @@
1
- /*! palbase 0.3.1 — Palbase SDK License (see LICENSE) */
1
+ /*! palbase 0.3.3 — Palbase SDK License (see LICENSE) */
2
2
  import{AsyncLocalStorage as g}from"node:async_hooks";function b(e,r){return new Proxy(r,{get(t,n,s){if(d.getStore()?.services===void 0)return Reflect.get(t,n,s);let o=f(e,n,t),a=o[n];return typeof a=="function"?a.bind(o):a}})}function f(e,r,t){let n=d.getStore()?.services;if(n===void 0)return t;let s=n[e];if(s!==void 0)return s;if(e==="Log"||typeof r=="symbol"||r==="then")return t;throw new Error(`${e}.${String(r)} was read, but this test did not provide ${e}. Pass it: withServices({ ${e}: \u2026 }, () => \u2026)`)}var p=Symbol.for("palbase.backend.requestScope"),d=globalThis[p]??=new g,u;function S(e){u=e}var m=new Proxy({},{get(e,r){if(!u)throw new Error(`Palbase.${String(r)} is reached before the app is served (serve() binds it)`);return u[r]}}),v=new Proxy({},{get(e,r){let t=d.getStore(),n=t?.database;if(!n)throw new Error(t?.services?`Database.${String(r)} was read, and this test gave no Database: withServices({ Database: fake.raw }, \u2026)`:t?`Database.${String(r)}: this app declares no database \u2014 PalbaseFactory.create(\u2026, { db: { schemas } })`:`Database.${String(r)} is reached outside a request: it is the request's transaction, reached from a handler, a service it calls or an @On`);let s=n[r];return typeof s=="function"?s.bind(n):s}});function c(e,r,t){let n={time:new Date().toISOString(),level:e,msg:r},s=d.getStore();if(s&&(n.request_id=s.requestId),t)for(let[a,i]of Object.entries(t))n[a]=i instanceof Error?{name:i.name,message:i.message,stack:i.stack}:i;let o=w(n);e==="error"||e==="warn"?process.stderr.write(`${o}
3
3
  `):process.stdout.write(`${o}
4
4
  `)}function w(e){try{return JSON.stringify(e)}catch{let r=new WeakSet;try{return JSON.stringify(e,(t,n)=>{if(typeof n=="bigint")return n.toString();if(typeof n=="object"&&n!==null){if(r.has(n))return"[circular]";r.add(n)}return n})}catch{return JSON.stringify({time:e.time,level:e.level,msg:e.msg,request_id:e.request_id,unwritable:"a field of this line could not be written"})}}}var y=b("Log",{debug:(e,r)=>c("debug",e,r),info:(e,r)=>c("info",e,r),warn:(e,r)=>c("warn",e,r),error:(e,r)=>c("error",e,r)});export{b as a,f as b,d as c,S as d,m as e,v as f,y as g};