palbase 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.js +2 -2
- package/dist/backend/engine.js +2 -2
- package/dist/backend/env.js +1 -1
- package/dist/backend/index.js +3 -3
- package/dist/backend/stack.js +1 -1
- package/dist/backend/test.js +2 -2
- package/dist/chunks/{6SINT3YD.js → 22JG5QKQ.js} +1 -1
- package/dist/chunks/{C2WFUOF7.js → 2DBSGJ7Z.js} +2 -2
- package/dist/chunks/{7MBBS4BC.js → 53ZQBGJV.js} +2 -2
- package/dist/chunks/{BJL7ZBG7.js → 66QSZDXV.js} +2 -2
- package/dist/chunks/{2J3RT5GV.js → 7ZSVOQFN.js} +2 -2
- package/dist/chunks/{AZ3Z3ME2.js → ABRUIWQ3.js} +1 -1
- package/dist/chunks/{CMDUL3VE.js → B33QXIR5.js} +1 -1
- package/dist/chunks/{W33A3OUV.js → B5XYZZDJ.js} +1 -1
- package/dist/chunks/{3CFHP6H7.js → DLQT5KPC.js} +1 -1
- package/dist/chunks/{MYHRHZYN.js → IYUDOOD7.js} +2 -2
- package/dist/chunks/{2QE7TIVQ.js → JEI4RW55.js} +2 -2
- package/dist/chunks/{SGDOCWYB.js → JWLK6SLN.js} +2 -2
- package/dist/chunks/{EWXQUZSU.js → LDZ7OKNS.js} +2 -2
- package/dist/chunks/{QRWMVBF4.js → MWTLLONV.js} +2 -2
- package/dist/chunks/{GXLUNOFZ.js → NRWY25JZ.js} +1 -1
- package/dist/chunks/{SGCYJGSM.js → QCZJK4GZ.js} +2 -2
- package/dist/chunks/{L4NDDBYW.js → UMCUTNWL.js} +2 -2
- package/dist/chunks/{MERWSLS2.js → WAMYRYDY.js} +2 -2
- package/dist/chunks/{C3UPTONG.js → WUYO4O77.js} +2 -2
- package/dist/chunks/{R26ROMEG.js → X2BWW2WC.js} +1 -1
- package/dist/chunks/{5MMZNWFL.js → YWEI45Q6.js} +2 -2
- package/dist/chunks/{EQ4HNSWU.js → ZOF56QTG.js} +2 -2
- package/dist/chunks/{5U3YIYBP.js → ZT4AKS6D.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/refuse/ai.js +1 -1
- package/dist/refuse/backend.js +1 -1
- package/dist/refuse/server.js +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/testing.js +2 -2
- package/dist/web/index.js +2 -2
- package/dist/web/message.js +2 -2
- package/dist/web/palbe.js +2 -2
- package/dist/web/paywall.js +2 -2
- package/dist/web/push-sw.js +1 -1
- package/dist/web/ssr.js +2 -2
- package/dist/web/vite.js +2 -2
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! palbase 0.13.
|
|
2
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
3
3
|
var yf=Object.defineProperty;var Xe=(e,t)=>{for(var n in t)yf(e,n,{get:t[n],enumerable:!0})};import{parseArgs as ey}from"node:util";var bf=Symbol.for("palbase.data"),wf=globalThis,zo=wf[bf]??=new WeakSet;function vf(e){return e instanceof Date||ArrayBuffer.isView(e)||e instanceof ArrayBuffer}function sa(e){let t=[e];for(;t.length>0;){let n=t.pop();if(!(typeof n!="object"||n===null||zo.has(n)||vf(n))){zo.add(n);for(let s of Array.isArray(n)?n:Object.values(n))t.push(s)}}return e}var _f="X-PoW-Challenge-ID",kf="X-PoW-Nonce";function Fo(e){if(typeof e!="object"||e===null)return null;let t=e;if(t.error!=="pow_required"||typeof t.challenge!="object"||t.challenge===null)return null;let{id:n,prefix:s,difficulty:a}=t.challenge;return typeof n!="string"||typeof s!="string"||typeof a!="number"||!Number.isInteger(a)||a<0?null:{id:n,prefix:s,difficulty:a}}function Sf(e){return 8*2**e}var Cn;async function $f(){if(Cn)return Cn;let e=globalThis;if(e.process?.versions?.node!==void 0||e.process?.versions?.bun!==void 0)try{let s=(await import("node:crypto")).createHash;if(typeof s=="function")return Cn=a=>new Uint8Array(s("sha256").update(a).digest()),Cn}catch{}let t=new TextEncoder;return Cn=async n=>new Uint8Array(await crypto.subtle.digest("SHA-256",t.encode(n))),Cn}function Pf(e){let t=0;for(let n of e){if(n===0){t+=8;continue}return t+Math.clz32(n)-24}return t}var Af=4096,Rf=typeof globalThis.setImmediate=="function"?()=>new Promise(e=>globalThis.setImmediate(e)):()=>new Promise(e=>setTimeout(e,0));async function Jo(e,t={}){if(e.difficulty>24)throw new Error(`proof-of-work: difficulty ${e.difficulty} is above auth's ceiling of 24`);let n=await $f(),s=Sf(e.difficulty),a=Date.now()+(t.timeLimitMs??12e4);for(let r=0;r<s;r++){if(r%Af===0&&r>0){if(await Rf(),t.signal?.aborted)throw t.signal.reason??new DOMException("proof-of-work aborted","AbortError");if(Date.now()>a)throw new Error(`proof-of-work: gave up on difficulty ${e.difficulty} after ${r} attempts`)}let i=n(e.prefix+r),o=i instanceof Uint8Array?i:await i;if(Pf(o)>=e.difficulty)return{[_f]:e.id,[kf]:String(r)}}throw new Error(`proof-of-work: no nonce for difficulty ${e.difficulty} within ${s} attempts`)}var I=class extends Error{status;code;requestId;retryAfter;body;op;get isNetworkError(){return this.code==="network_error"}constructor(t){super(t.message,t.cause===void 0?void 0:{cause:t.cause}),this.name="PalbaseError",this.op=t.op,this.status=t.status,this.code=t.code,this.requestId=t.requestId,this.retryAfter=t.retryAfter,this.body=t.body}};function u(e,t,n){let s=String(n);if(s===""||s==="."||s==="..")throw new I({op:e,status:0,code:"invalid_path_parameter",message:`${e}: ${t} cannot be ${s===""?"empty":JSON.stringify(s)}`});return encodeURIComponent(s)}var Tf=new Set(["apikey","authorization"]),Ef=64*1024;function Mr(e){let t=aa(e.baseUrl),n=e.fetch??globalThis.fetch,s=e.solveProofOfWork??!0,a=async(r,i)=>{let o=Of(t,r),l=new Headers;for(let[m,w]of Object.entries(r.headers??{}))w!=null&&!Tf.has(m.toLowerCase())&&l.set(m,String(w));for(let[m,w]of Object.entries(i))l.set(m,w);await xf(r,e.credentials,l),l.has("accept")||l.set("accept","application/json");let d={method:r.method,headers:l,redirect:"manual",signal:r.signal,...r.keepalive?{keepalive:!0}:{}};r.body&&r.body.value!==void 0&&(l.set("content-type",r.body.contentType),d.body=If(r.body.kind,r.body.value),jn(d.body)||(d.duplex="half"));let p;try{p=r.onUploadProgress&&e.xmlHttpRequest?await Cf(e.xmlHttpRequest,r.op,o,d,r.onUploadProgress):await n(o,d)}catch(m){throw r.signal?.aborted||m instanceof I?m:new I({op:r.op,status:0,code:"network_error",message:`${r.op}: the request did not reach ${t.origin}`,cause:m})}let c=r.answers[p.status];if(c===void 0)throw p.status>=200&&p.status<300?(await p.body?.cancel(),new I({op:r.op,status:p.status,code:"undeclared_answer",message:`${r.op}: the server answered ${p.status}, which its contract does not declare; the request may have taken effect`})):await Lf(r.op,p);let h;switch(c){case"json":try{h=sa(await p.json())}catch(m){throw new I({op:r.op,status:p.status,code:"invalid_json",message:`${r.op}: the answer is not JSON`,cause:m})}break;case"raw":h=p;break;default:await p.body?.cancel(),h=void 0}return{status:p.status,data:h,headers:p.headers}};return{async send(r){try{return await a(r,{})}catch(i){let o=s&&i instanceof I&&i.status===403?Fo(i.body):null,l=r.body?.value;if(!o||r.body?.kind==="raw"&&!jn(l))throw i;let d=i,p;try{p=await Jo(o,{signal:r.signal})}catch(c){throw r.signal?.aborted?c:new I({op:r.op,status:403,code:"pow_unsolved",message:`${r.op}: ${c instanceof Error?c.message:String(c)}`,requestId:d.requestId,body:d.body,cause:c})}return a(r,p)}}}}function Cf(e,t,n,s,a){return new Promise((r,i)=>{let o=s.signal;if(o?.aborted)return i(o.reason);let l=new e,d=()=>l.abort();o?.addEventListener("abort",d,{once:!0});let p=c=>{o?.removeEventListener("abort",d),c()};l.open(s.method??"GET",n.href),l.responseType="arraybuffer",new Headers(s.headers).forEach((c,h)=>l.setRequestHeader(h,c)),l.upload&&(l.upload.onprogress=c=>{c.lengthComputable&&a(c.loaded,c.total)}),l.onload=()=>p(()=>{if(l.responseURL!==""&&l.responseURL!==n.href){i(new I({op:t,status:0,code:"undeclared_redirect",message:`${t}: the server redirected; the answer is another address's, and was not read`}));return}if(l.status<200||l.status>599)return i(new TypeError(`${t}: answered ${l.status}`));let c=l.status===204||l.status===205||l.status===304;r(new Response(c?null:l.response,{status:l.status,statusText:l.statusText,headers:jf(l.getAllResponseHeaders())}))}),l.onerror=()=>p(()=>i(new TypeError(`${t}: the request failed`))),l.onabort=()=>p(()=>i(o?.reason??new DOMException("The request was aborted","AbortError"))),l.send(s.body)})}function jf(e){let t=new Headers;for(let n of e.split(/\r?\n/)){let s=n.indexOf(":");if(!(s<=0))try{t.append(n.slice(0,s).trim(),n.slice(s+1).trim())}catch{}}return t}function aa(e){let t;try{t=new URL(e)}catch{throw new TypeError(`baseUrl ${JSON.stringify(e)} is not an absolute URL`)}let n=t.hostname==="localhost"||t.hostname.endsWith(".localhost")||t.hostname==="127.0.0.1"||t.hostname==="[::1]";if(t.protocol!=="https:"&&!(t.protocol==="http:"&&n))throw new TypeError(`baseUrl must be https (http only for a loopback address): ${t.origin}`);if(t.username||t.password||t.search||t.hash)throw new TypeError("baseUrl carries no user, query or fragment");if(t.pathname!=="/"&&t.pathname!=="")throw new TypeError("baseUrl is the project origin alone, with no path");return t}function Of(e,t){if(!t.path.startsWith("/")||t.path.startsWith("//"))throw new I({op:t.op,status:0,code:"invalid_path",message:`${t.op}: path ${JSON.stringify(t.path)} is not absolute`});let n=new URL(t.path+Mf(t.query),e);if(n.origin!==e.origin)throw new I({op:t.op,status:0,code:"invalid_path",message:`${t.op}: path leaves the project's origin`});return n}async function xf(e,t,n){if(e.auth.length===0)return;let s=e.auth.some(i=>i.includes("userJWT"))?await t.accessToken?.():void 0,a=i=>{switch(i){case"ApiKeyAuth":return!!(t.publishableKey??t.secretKey);case"SecretKeyAuth":case"AdminAuth":return!!t.secretKey;case"userJWT":return!!s;default:return!1}},r=e.auth.filter(i=>i.every(a)).reduce((i,o)=>i===void 0||o.length>i.length?o:i,void 0);if(!r)throw new I({op:e.op,status:0,code:"missing_credential",message:`${e.op} needs one of: ${e.auth.map(i=>i.length===0?"nothing":i.join(" + ")).join(" | ")}`});for(let i of r)i==="ApiKeyAuth"?n.set("apikey",t.publishableKey??t.secretKey):i==="SecretKeyAuth"||i==="AdminAuth"?n.set("apikey",t.secretKey):i==="userJWT"&&n.set("authorization",`Bearer ${s}`)}function If(e,t){switch(e){case"json":return JSON.stringify(t);case"form":{let n=new URLSearchParams;for(let[s,a]of Object.entries(t))Lr(n,s,a);return n}case"raw":return t}}function jn(e){return!!(e==null||typeof e=="string"||e instanceof URLSearchParams||e instanceof Blob||e instanceof FormData||e instanceof ArrayBuffer||ArrayBuffer.isView(e))}function Mf(e){if(!e)return"";let t=new URLSearchParams;for(let[s,a]of Object.entries(e))Lr(t,s,a);let n=t.toString();return n===""?"":`?${n}`}function Lr(e,t,n){if(n!=null){if(Array.isArray(n)){for(let s of n)Lr(e,t,s);return}if(n instanceof Date){e.append(t,n.toISOString());return}e.append(t,typeof n=="object"?JSON.stringify(n):String(n))}}async function Lf(e,t){let n=await Df(t,Ef).catch(()=>""),s;try{s=n===""?void 0:JSON.parse(n)}catch{s=n}let a=Nf(s)?s:void 0,r=Number(t.headers.get("retry-after")),i=t.status>=300&&t.status<400;return new I({op:e,status:t.status,code:a?.error??(i?"undeclared_redirect":`http_${t.status}`),message:a?.error_description??(i?`${e}: the server redirected (${t.status}); the request was not followed, its credentials stay here`:`${e}: ${t.status} ${t.statusText}`.trim()),requestId:a?.request_id??t.headers.get("x-request-id")??void 0,retryAfter:a?.retry_after??(Number.isFinite(r)&&r>0?r:void 0),body:s})}async function Df(e,t){if(!e.body)return"";let n=e.body.getReader(),s=[],a=0;for(;a<t;){let{done:o,value:l}=await n.read();if(o)break;s.push(l),a+=l.byteLength}await n.cancel().catch(()=>{});let r=new Uint8Array(Math.min(a,t)),i=0;for(let o of s){let l=Math.min(o.byteLength,r.byteLength-i);if(r.set(o.subarray(0,l),i),i+=l,i>=r.byteLength)break}return new TextDecoder().decode(r)}function Nf(e){return typeof e=="object"&&e!==null&&typeof e.error=="string"}var ra={project:{type:"string",short:"P",value:"project",description:"the project (name or id; org/project when the name is in two organizations)"},env:{type:"string",short:"E",value:"env",description:"the project's environment (slug or ref)"},json:{type:"boolean",description:"print the answer as JSON"},"non-interactive":{type:"boolean",description:"never ask: refuse what would need a question"},yes:{type:"boolean",short:"y",description:"confirm a change to a production environment without asking"},debug:{type:"boolean",description:"print each request the command sends"},help:{type:"boolean",short:"h",description:"show help"}};var y=class extends Error{exitCode;hint;code;constructor(t,n,s={}){super(n),this.name="CliError",this.code=t,this.hint=s.hint,this.exitCode=s.exitCode??1}};function g(e,t){return new y("usage",e,{hint:t,exitCode:2})}var ia=class{io;json;constructor(t,n){this.io=t,this.json=n}result(t,n){this.json?this.io.stdout(`${JSON.stringify(t,null,2)}
|
|
4
4
|
`):n()}line(t=""){this.io.stdout(`${K(t)}
|
|
5
5
|
`)}note(t){this.io.stderr(`${K(t)}
|
|
@@ -9,7 +9,7 @@ var yf=Object.defineProperty;var Xe=(e,t)=>{for(var n in t)yf(e,n,{get:t[n],enum
|
|
|
9
9
|
`);let i;try{i=await this.io.fetch(t,{method:n.method,headers:{...n.headers,...a},body:n.body,signal:n.signal,...s?{}:{duplex:"half"},redirect:"manual"})}catch(l){throw n.signal?.aborted?l:new y("network_error",`${new URL(t).origin} could not be reached: ${l instanceof Error?l.message:String(l)}`)}if(this.debug&&this.io.stderr(`< ${i.status} ${i.headers.get("x-request-id")??""}
|
|
10
10
|
`),i.status!==503||!s||r>=Yf||!Xf.has(await qr(i)??""))return i;await i.body?.cancel();let o=Number(i.headers.get("retry-after")??"");await this.io.sleep((Number.isFinite(o)&&o>0?Math.min(o,30):1)*1e3)}}async exchange(t,n,s){let a=await this.token(),r=await this.send(t,n,s,a.value);if(r.status===401&&a.renewable){let i=await this.renew(await this.currentSession());r=await this.send(t,n,s,i.access_token)}return{res:r,renewable:a.renewable}}async answered(t,n,s,a){if(s.status===204)return;let r=await s.text(),i=r===""?void 0:Zf(r);if(s.ok)return i;let o=i??{};throw s.status===401?o.error==="token_not_for_machines"?ll(new URL(this.cloud.studioApi).host):a?On():this.tokenRefused("Studio"):new I({op:`${t} ${n}`,status:s.status,code:o.error??`http_${s.status}`,message:o.error_description??`Studio answered ${s.status}`,requestId:o.request_id??s.headers.get("x-request-id")??void 0,body:i})}tokenRefused(t){return(this.io.env.PALBASE_TOKEN??"").startsWith("pbe_")?new y("token_refused",`${t} refused PALBASE_TOKEN, an environment's token: it ended (a few hours at most), it was revoked, or what minted it no longer holds`,{hint:"mint another: palbase env:tokens:create --scope <scope> (an admin), or with the environment's secret key (Studio's POST /environments/{ref}/tokens)"}):new y("token_refused",`${t} refused PALBASE_TOKEN: it was revoked, it ended, or the one who made it no longer holds its role`,{hint:"an admin makes a new one: palbase tokens:create <name>"})}async token(){let t=this.io.env.PALBASE_TOKEN;return t&&t!==""?{value:t,renewable:!1}:{value:(await this.currentSession()).access_token,renewable:!0}}async renew(t){let n=await al(this.io,this.cloud,t);return await this.state.writeSession(n),this.session=n,n}async send(t,n,s,a){let r=`${this.cloud.studioApi}${Hf}${n}`;this.debug&&this.io.stderr(`> ${t} ${r}
|
|
11
11
|
`);try{let i=await this.io.fetch(r,{method:t,headers:{authorization:`Bearer ${a}`,accept:"application/json",...s===void 0?{}:{"content-type":"application/json"}},body:s===void 0?void 0:JSON.stringify(s),redirect:"manual"});return this.debug&&this.io.stderr(`< ${i.status} ${i.headers.get("x-request-id")??""}
|
|
12
|
-
`),i}catch(i){throw new y("network_error",`Studio (${this.cloud.studioApi}) could not be reached: ${i instanceof Error?i.message:String(i)}`)}}};function ll(e){return new y("token_not_for_machines",`the platform's edge refused PALBASE_TOKEN at ${e}, taking it for a machine's address (token_not_for_machines): the token itself was not refused`,{hint:"nothing is wrong with the token: run this again in a few minutes, and tell Palbase if it lasts"})}async function qr(e){let t=await e.clone().json().catch(()=>null),n=t&&typeof t=="object"?t.error:void 0;return typeof n=="string"&&/^(console|token|edge)_/.test(n)?n:void 0}function Zf(e){try{return JSON.parse(e)}catch{return e}}var pl={version:"0.13.
|
|
12
|
+
`),i}catch(i){throw new y("network_error",`Studio (${this.cloud.studioApi}) could not be reached: ${i instanceof Error?i.message:String(i)}`)}}};function ll(e){return new y("token_not_for_machines",`the platform's edge refused PALBASE_TOKEN at ${e}, taking it for a machine's address (token_not_for_machines): the token itself was not refused`,{hint:"nothing is wrong with the token: run this again in a few minutes, and tell Palbase if it lasts"})}async function qr(e){let t=await e.clone().json().catch(()=>null),n=t&&typeof t=="object"?t.error:void 0;return typeof n=="string"&&/^(console|token|edge)_/.test(n)?n:void 0}function Zf(e){try{return JSON.parse(e)}catch{return e}}var pl={version:"0.13.2"};var ca=pl.version;async function gl(e,t,n){let s=new Map(n.map(i=>[i.name,i])),a=e.includes("--json"),r=e.includes("--debug");try{let{name:i,at:o}=ty(e);if(i===void 0)return e.includes("--version")?(t.stdout(`palbase ${ca}
|
|
13
13
|
`),0):(t.stdout(hl(n)),e.length===0||e.includes("--help")||e.includes("-h")?0:2);if(i==="help"){let _=e[o+1],$=_===void 0?void 0:s.get(_);if(_!==void 0&&!$)throw dl(_,n);return t.stdout($?ul($):hl(n)),0}let l=s.get(i);if(!l)throw dl(i,n);let d=[...e.slice(0,o),...e.slice(o+1)];if(d.includes("--help")||d.includes("-h"))return t.stdout(ul(l)),0;let{flags:p,positionals:c}=ny(l,d),h=l.args??{min:0,max:0};if(c.length<h.min)throw g(`${l.name} needs ${h.min===1?"an argument":`${h.min} arguments`}`,Gr(l));if(c.length>h.max)throw g(`${l.name} takes ${h.max===0?"no argument":`at most ${h.max}`}: ${JSON.stringify(c.slice(h.max))} is left over`,Gr(l));let m={project:p.project,env:p.env,json:p.json===!0,nonInteractive:p["non-interactive"]===!0,yes:p.yes===!0,debug:p.debug===!0},w=Zo(t.env),v=new oa(tl(t.configDir,w)),T={io:t,state:v,out:new ia(t,m.json),global:m,args:c,flags:p,interactive:t.interactive&&!m.nonInteractive,cloud:w,studio:new da(t,w,v,m.debug)};return await l.run(T)??0}catch(i){return sy(i,t,a,r)}}function ty(e){let t=new Set;for(let[n,s]of Object.entries(ra))s.type==="string"&&(t.add(`--${n}`),s.short&&t.add(`-${s.short}`));for(let n=0;n<e.length;n++){let s=e[n];if(s==="--")return{at:-1};if(t.has(s)){n++;continue}if(!s.startsWith("-"))return{name:s,at:n}}return{at:-1}}function ny(e,t){let n={...ra,...e.flags??{}},s={};for(let[a,r]of Object.entries(n))s[a]={type:r.type,...r.short?{short:r.short}:{},...r.multiple?{multiple:!0}:{}};try{let{values:a,positionals:r}=ey({args:t,options:s,strict:!0,allowPositionals:!0});return{flags:a,positionals:r}}catch(a){throw g(a instanceof Error?a.message.replace(/^.*?: /,""):String(a),`palbase help ${e.name}`)}}function sy(e,t,n,s){let a="error",r,i,o=1,l;return e instanceof y?(a=e.code,r=e.message,i=e.hint,o=e.exitCode):e instanceof I?(a=e.code,r=e.message,l=e.requestId):r=e instanceof Error?e.message:String(e),n?t.stdout(`${JSON.stringify({error:a,message:r,...i?{hint:i}:{},...l?{request_id:l}:{}},null,2)}
|
|
14
14
|
`):(t.stderr(`error: ${K(r)}${l?` (request ${K(l)})`:""}
|
|
15
15
|
`),i&&t.stderr(` ${K(i)}
|
|
@@ -681,7 +681,7 @@ ${t}}`}var jt=e=>["",e.toUpperCase(),"-".repeat(e.length)],Z_=[{title:"One packa
|
|
|
681
681
|
`,{mode:384}),e.out.result({file:e.flags.out,bytes:Buffer.byteLength(r)},()=>e.out.line(`Wrote the audit trail to ${e.flags.out} (${Buffer.byteLength(r)} bytes).`))):e.io.stdout(r.endsWith(`
|
|
682
682
|
`)||r===""?r:`${r}
|
|
683
683
|
`)}},yR={name:"auth:signing-keys",summary:"the keys the environment's tokens are signed with: the active one, those still verifying, the retired",scope:"environment",async run(e){let t=await b(e),n=await f(e,t,"GET","/admin/signing-keys");e.out.result(n,()=>{e.out.table(n.keys,[{header:"kid",value:s=>C(s.kid)+(s.kid===n.active_kid?" (signing)":"")},{header:"status",value:s=>C(s.status)},{header:"algorithm",value:s=>C(s.algorithm)},{header:"created",value:s=>Mt(s.created_at)},{header:"retired",value:s=>Mt(s.retired_at)}]),n.next_rotation&&e.out.line(`The next key starts signing ${Mt(n.next_rotation)}.`)})}},bR={name:"auth:signing-keys:rotate",summary:"sign with a new key from now on; tokens the old one signed go on verifying until they end",scope:"environment",async run(e){let t=await b(e);await k(e,t,"rotate the token signing key");let n=await f(e,t,"POST","/admin/signing-keys/rotate");e.out.result(n,()=>e.out.line(`Tokens are signed with ${C(n.new_kid)} from now on; the old key goes on verifying the tokens it signed.`))}},wR={name:"auth:users:export",summary:"everything the environment holds about one user, as the law lets them ask for it (GDPR art. 15/20): JSON",usage:"<user-id> [--out <file>]",args:{min:1,max:1},flags:{out:{type:"string",value:"file",description:"write it here instead of to standard output"}},scope:"environment",async run(e){let t=await b(e),n=Qt(e.args[0]),s=await f(e,t,"GET",`/admin/users/${S(n)}/export`),a=`${JSON.stringify(s,null,2)}
|
|
684
|
-
`;typeof e.flags.out=="string"?(await lm(pm(e.io.cwd,e.flags.out),a,{mode:384}),e.out.result({file:e.flags.out},()=>e.out.line(`Wrote ${n}'s data to ${e.flags.out}.`))):e.io.stdout(a)}},vR={name:"realtime:broadcast",summary:"send an event to a channel's subscribers, as the server does: its payload JSON (or text)",usage:"<topic> <event> [payload]",args:{min:2,max:3},scope:"environment",async run(e){let t=await b(e),[n,s,a]=e.args,r=a===void 0?null:ut(a);await k(e,t,`broadcast ${s} on ${n}`);let i=await f(e,t,"POST","/realtime/broadcast",{messages:[{topic:n,event:s,payload:r}]});e.out.result(i??{sent:1},()=>e.out.line(`Broadcast ${C(s)} on ${C(n)}.`))}},_R={name:"analytics:events",summary:"the events analytics recorded, newest first: by name, by user, over a window",usage:"[--name <event>] [--user <distinct-id>] [--window <24h>] [--limit <n>]",flags:{name:{type:"string",value:"event",description:"only this event's"},user:{type:"string",value:"id",description:"only this user's (their distinct id)"},window:{type:"string",value:"span",description:"how far back: 30m, 24h, 7d (default 24h)"},limit:{type:"string",value:"n",description:"how many (default 50)"}},scope:"environment",async run(e){let t=await b(e),n=new URLSearchParams({window_seconds:String(dm(e.flags.window,"window")??86400),limit:String(rs(e.flags.limit,"limit",1,1e3)??50),...e.flags.name?{name:e.flags.name}:{},...e.flags.user?{distinct_id:e.flags.user}:{}}),s=await f(e,t,"GET",`/analytics/events?${n}`);e.out.result(s,()=>{s.events.length===0&&e.out.line("No event in the window.");for(let a of s.events)e.out.line(`${C(Mt(a.timestamp??a.ts))} ${C(a.name)} ${C(a.distinct_id??"")}${a.properties&&Object.keys(a.properties).length?` ${C(JSON.stringify(a.properties)).slice(0,200)}`:""}`)})}},kR={name:"analytics:summary",summary:"what analytics counted over a window: events, users, sessions, the top events",usage:"[--window <24h>]",flags:{window:{type:"string",value:"span",description:"how far back: 30m, 24h, 7d (default 24h)"}},scope:"environment",async run(e){let t=await b(e),n=await f(e,t,"GET",`/analytics/summary?window_seconds=${dm(e.flags.window,"window")??86400}`);e.out.result(n,()=>{for(let[s,a]of Object.entries(n))e.out.line(`${C(s)}: ${typeof a=="object"?JSON.stringify(a):C(String(a))}`)})}},ym=[HA,XA,YA,ZA,QA,eR,tR,wR,gR,mR,fR,yR,bR,sR,aR,rR,iR,oR,lR,pR,cR,uR,hR,vR,_R,kR];var Hs=["machines:read","machines:logs","apps:sync","auth:test-users"];function bm(e){return e.scopes===null?"its minter's role":e.scopes.join(", ")}var SR={name:"env:tokens:create",summary:"mint a token of the environment for a program (an AI agent): your role in this environment alone, a few hours; shown this once",usage:"[--scope <scope>[,<scope>]] [--minutes <n>] [--name <name>]",details:["It does in this environment what your role does \u2014 as your own CLI would \u2014 but never makes or shows a standing credential (a key, a token), changes people or roles, or deletes a project or an environment; nothing beyond this environment.",`--scope narrows it to: ${Hs.join(", ")} \u2014 machines:read reads the machines, their builds, crons and queues; machines:logs their logs; apps:sync what palbase apps:sync reads; auth:test-users makes and deletes test users.`,"Give it to the program as PALBASE_TOKEN: the CLI acts in this environment alone with it. It ends after --minutes (default 60, at most 240), and with what minted it."],flags:{scope:{type:"string",multiple:!0,value:"scope",description:`narrow it to: ${Hs.join(", ")} (comma-separated, or given again); none: your role`},minutes:{type:"string",value:"n",description:"how long it lives (default 60, at most 240)"},name:{type:"string",value:"name",description:"what it is for, as the environment lists it"}},scope:"environment",async run(e){let t=ie(e.flags.scope),n=t===void 0?void 0:[...new Set(t)];if(n!==void 0&&n.length===0)throw g(`--scope names what the token is narrowed to: ${Hs.join(", ")}`);let s=(n??[]).filter(o=>!Hs.includes(o));if(s.length>0)throw g(`${s.join(", ")}: no scope of an environment's token (${Hs.join(", ")})`);let a=e.flags.minutes===void 0?60:Number(e.flags.minutes);if(!Number.isInteger(a)||a<5||a>240)throw g("--minutes is a whole number from 5 to 240");let r=await b(e),i=await e.studio.post(`/environments/${r.env_ref}/tokens`,{...n!==void 0?{scopes:n}:{},expires_in_minutes:a,...typeof e.flags.name=="string"?{name:e.flags.name}:{}});e.out.result(i,()=>{e.out.line(`Minted ${K(i.name)} for ${q(r)} (${bm(i)}; until ${i.expires_at.slice(0,16).replace("T"," ")} UTC).`),e.out.line(`token (shown this once \u2014 the program's PALBASE_TOKEN): ${i.token}`)})}},$R={name:"env:tokens:list",summary:"the environment's live tokens, by their hint (never their values)",scope:"environment",async run(e){let t=await b(e),{tokens:n}=await e.studio.get(`/environments/${t.env_ref}/tokens`);e.out.result({tokens:n},()=>{n.length===0&&e.out.line(`${q(t)} has no live token: palbase env:tokens:create --scope <scope> mints one.`),e.out.table(n,[{header:"id",value:s=>s.id},{header:"name",value:s=>K(s.name)},{header:"can",value:s=>bm(s)},{header:"ends",value:s=>s.expires_at.slice(0,16).replace("T"," ")},{header:"minted by",value:s=>s.minted_by},{header:"hint",value:s=>`\u2026${s.hint}`}])})}},PR={name:"env:tokens:revoke",summary:"revoke an environment's token (by its id; with PALBASE_TOKEN an environment's token, `self` revokes it): refused from its next request on",usage:"<id|self>",args:{min:1,max:1},scope:"environment",async run(e){let t=await b(e),n=e.args[0];if(n==="self"){let s=(await e.studio.get("/environments")).environments.find(a=>a.ref===t.env_ref)?.token_id;if(!s)throw new y("not_a_token","self is the environment token PALBASE_TOKEN is, and it is none",{hint:"name the token by its id: palbase env:tokens:list"});n=s}await e.studio.request("DELETE",`/environments/${H("the environment's ref",t.env_ref)}/tokens/${H("the token's id",n)}`),e.out.result({revoked:n},()=>e.out.line(`Revoked the environment token ${n} of ${q(t)}.`))}},wm=[$R,SR,PR];var wn={org:{type:"string",value:"org",description:"the organization (name or id; the one of the environment chosen here, or your only one)"}};function $e(e){let t=e<0?"-":"",n=Math.abs(e);if(n>0&&n<1e4)return`${t}$${(n/1e6).toFixed(6).replace(/0{1,4}$/,"")}`;let s=Math.round(n/1e4);return`${t}$${Math.floor(s/100).toLocaleString("en-US")}.${String(s%100).padStart(2,"0")}`}function is(e,t){let n=typeof e=="string"?/^\s*\$?\s*(\d{1,9})(?:\.(\d{1,2}))?\s*$/.exec(e):null;if(!n)throw g(`${t} is an amount in US dollars, to the cent (20 or 20.50)`);return Number(n[1])*1e6+Number((n[2]??"").padEnd(2,"0"))*1e4}var Xs=e=>`${(e/2**30).toFixed(2)} GiB`,AR=e=>e.toLocaleString("en-US"),RR={egress:Xs,storage:e=>`${Xs(e)} (month's peak)`,"db.backups":e=>`${Xs(e)} (month's peak)`,images:e=>`${Xs(e)} (month's peak)`,logs:Xs,cache:e=>`${(e/2**20).toFixed(1)} MiB (month's peak)`,builds:e=>`${(e/60).toFixed(1)} min`,"ai.workspaces":e=>`${(e/3600).toFixed(1)} h`,"ai.models":e=>`$${(e/1e9).toFixed(4)} at the provider`};function TR(e,t){return e.startsWith("machine.")||e.startsWith("db.")&&e!=="db.backups"?`${(t/3600).toFixed(1)} h`:(RR[e]??AR)(t)}async function vn(e){let t=e.flags.org;return t===void 0&&(t=(await e.state.targetFor(e.io.cwd))?.target.org_id),mt(e,t)}function vm(e){return e.gone?"left the organization":e.deleted?"deleted":e.frozen?"frozen":e.free?"Free":e.cap_micros!==null&&(e.gross_micros??0)>=e.cap_micros?"at its cap":e.paid?"Pay as you go":"Free quotas"}function ER(e){return e.exempt?"Not billed: measured, never charged":e.has_account&&e.account?.terms_version?e.paying||!e.enforced?"Pay as you go (the free quota once for the organization)":"Pay as you go, no balance: the Free limits hold until a top-up":"Free (open the payment account in Studio, Billing, for paid sizes and more than 2 projects)"}function _m(e,t,n){let s=new Map(n.environments.map(i=>[i.platform_id,`${i.project_name} \u203A ${i.name}`])),a=n.account;e.out.line(`${K(t)} \u2014 ${ER(n)}`),a&&(e.out.line(`balance: ${$e(a.balance_micros)}${a.exhausted?" (ran out: what is paid for has stopped)":""} \xB7 ${a.payment_method?`card ${K(a.payment_method)}`:"no card saved yet"}${a.stripe_mode==="test"?" \xB7 test mode":""}`),e.out.line(`automatic top-up: ${a.auto_topup?`${$e(a.auto_amount_micros)} under ${$e(a.auto_threshold_micros)}${a.monthly_cap_micros?`, at most ${$e(a.monthly_cap_micros)} a month`:""}`:"off (the balance is the ceiling)"}`),e.out.line(`told when it lasts fewer than ${a.low_balance_days} days of spend`));let r=new Date(`${n.period}-01T00:00:00Z`).toLocaleDateString("en-US",{month:"long",year:"numeric",timeZone:"UTC"});n.taken_micros!==void 0&&e.out.line(`${r}: ${$e(n.exempt?n.charged_micros??0:n.taken_micros)} ${n.exempt?"priced, not taken":"taken from the balance so far"}`),e.out.line(),e.out.table(n.projects,[{header:"environment",value:i=>K(s.get(i.project_id)??i.name)},{header:"ref",value:i=>i.ref},{header:"plan",value:vm},{header:"gross",value:i=>i.gross_micros===void 0?"":$e(i.gross_micros)},{header:"cap",value:i=>i.cap_micros===null?"":$e(i.cap_micros)}])}var CR={name:"billing",summary:"an organization's plan, balance, card, automatic top-up and this month \u2014 each environment's place in the bill and what it came to",usage:"[--org <org>]",details:["A member reads the plan and the environments; the money (balance, amounts) is an owner's or an admin's."],flags:wn,scope:"account",async run(e){let t=await vn(e),n=await e.studio.get(`/orgs/${t.id}/billing`);e.out.result(n,()=>_m(e,t.name,n))}},jR={name:"billing:charges",summary:"a month's charges, by environment and item, gross \u2014 then the organization's, its free quota taken once \u2014 as a table or as CSV",usage:"[--period <YYYY-MM>] [--csv] [--org <org>]",details:["--csv prints the CSV Studio downloads: what an organization bills its own customers by."],flags:{...wn,period:{type:"string",value:"YYYY-MM",description:"the month (this one by default)"},csv:{type:"boolean",description:"print the charges as CSV"}},scope:"account",async run(e){let t=e.flags.period;if(t!==void 0&&!/^\d{4}-(0[1-9]|1[0-2])$/.test(t))throw g("--period is a month: YYYY-MM");let n=await vn(e),s=t?`?period=${t}`:"";if(e.flags.csv===!0){e.io.stdout(K(await e.studio.get(`/orgs/${n.id}/billing/charges.csv${s}`)));return}let a=await e.studio.get(`/orgs/${n.id}/billing/charges${s}`);e.out.result(a,()=>{let r=[...a.charges.filter(i=>i.project_id!==""),...a.charges.filter(i=>i.project_id==="")];r.length===0?e.out.line(`${K(n.name)} used nothing in ${a.period}.`):e.out.table(r,[{header:"environment",value:i=>i.project_id===""?"(organization)":K(i.project_name&&i.name?`${i.project_name} \u203A ${i.name}`:i.ref??i.project_id)},{header:"item",value:i=>i.item==="total"?"priced":i.item},{header:"used",value:i=>i.item==="total"?"":TR(i.item,i.units)},{header:"amount",value:i=>$e(i.micros)}]),e.out.line(`${a.period}: ${$e(a.taken_micros)} taken from the balance.`)})}},OR={checkout:"top-up (card)",auto:"automatic top-up",card:"top-up (saved card)",bank_transfer:"bank transfer"},xR={name:"billing:invoices",summary:"the invoices of an organization's top-ups: Stripe makes one of each, and emails it",usage:"[--org <org>]",flags:wn,scope:"account",async run(e){let t=await vn(e),{invoices:n}=await e.studio.get(`/orgs/${t.id}/billing/invoices`);e.out.result({invoices:n},()=>{n.length===0?e.out.line(`${K(t.name)} has no invoice yet.`):e.out.table(n,[{header:"date",value:s=>s.created_at.slice(0,16).replace("T"," ")},{header:"top-up",value:s=>OR[s.kind]??s.kind},{header:"amount",value:s=>`${$e(s.amount_micros)}${s.tax_micros>0?` + ${$e(s.tax_micros)} tax`:""}`},{header:"status",value:s=>s.status==="void"&&(s.kind==="auto"||s.kind==="card")?"declined":s.status},{header:"invoice",value:s=>s.hosted_url??""}])})}},IR={name:"billing:ledger",summary:"every change of an organization's balance, newest first: top-ups, usage taken, refunds, what expired",usage:"[--limit <n>] [--org <org>]",flags:{...wn,limit:{type:"string",value:"n",description:"how many at most (default 50)"}},scope:"account",async run(e){let t=e.flags.limit===void 0?50:Number(e.flags.limit);if(!Number.isInteger(t)||t<1||t>1e4)throw g("--limit is a whole number from 1 to 10000");let n=await vn(e),s=[],a;for(;;){let i=await e.studio.get(`/orgs/${n.id}/billing/ledger${a?`?before=${a}`:""}`);if(s.push(...i.lines),i.lines.length===0||s.length>=t)break;a=i.lines[i.lines.length-1].id}let r=s.slice(0,t);e.out.result({lines:r},()=>{r.length===0?e.out.line(`${K(n.name)}'s balance has not changed yet.`):e.out.table(r,[{header:"when",value:i=>i.created_at.slice(0,16).replace("T"," ")},{header:"kind",value:i=>i.kind},{header:"amount",value:i=>$e(i.amount_micros)},{header:"left of it",value:i=>i.remaining_micros===null?"":$e(i.remaining_micros)},{header:"ref",value:i=>K(i.ref)}])})}},MR={name:"billing:settings",summary:"an organization's automatic top-up \u2014 on or off, under what balance, by how much, at most how much a month \u2014 and when it is told the balance runs low",usage:"[--auto-topup yes|no] [--threshold <usd>] [--amount <usd>] [--monthly-cap <usd>|none] [--low-balance-days <n>] [--org <org>]",details:["A month's cap takes what is left of it, and nothing once it is spent: the owners are emailed once a month when it holds a top-up back."],flags:{...wn,"auto-topup":{type:"string",value:"yes|no",description:"take a top-up from the saved card when the balance is under the threshold"},threshold:{type:"string",value:"usd",description:"the balance under which it is taken"},amount:{type:"string",value:"usd",description:"how much it takes ($10 at least)"},"monthly-cap":{type:"string",value:"usd|none",description:"at most this much a calendar month; none for no cap"},"low-balance-days":{type:"string",value:"n",description:"email the owners when the balance lasts fewer than n days of spend (1 to 60)"}},scope:"account",async run(e){let t={},n=ht(e.flags["auto-topup"],"auto-topup");if(n!==void 0&&(t.auto_topup=n),e.flags.threshold!==void 0&&(t.auto_threshold_micros=is(e.flags.threshold,"--threshold")),e.flags.amount!==void 0&&(t.auto_amount_micros=is(e.flags.amount,"--amount")),e.flags["monthly-cap"]!==void 0&&(t.monthly_cap_micros=e.flags["monthly-cap"]==="none"?null:is(e.flags["monthly-cap"],"--monthly-cap")),e.flags["low-balance-days"]!==void 0){let r=Number(e.flags["low-balance-days"]);if(!Number.isInteger(r)||r<1||r>60)throw g("--low-balance-days is a whole number from 1 to 60");t.low_balance_days=r}if(Object.keys(t).length===0)throw g("nothing to change: pass --auto-topup, --threshold, --amount, --monthly-cap or --low-balance-days");let s=await vn(e),a=await e.studio.request("PATCH",`/orgs/${s.id}/billing`,t);e.out.result(a,()=>_m(e,s.name,a))}},LR={name:"billing:env",summary:"an environment's place in its organization's bill: a monthly cap, pulled to the Free plan, frozen",usage:"<project/env | ref> [--cap <usd>|none] [--free yes|no] [--frozen yes|no] [-y]",details:["At its cap the environment is Free until the month ends; the others go on. Frozen, its requests are refused and its machines and databases stopped, its data kept; only what it stores is charged.","Freezing asks first; -y does not."],args:{min:1,max:1},flags:{cap:{type:"string",value:"usd|none",description:"at most this much a month; none for no cap"},free:{type:"string",value:"yes|no",description:"on the Free plan: charged nothing, held to the free quotas"},frozen:{type:"string",value:"yes|no",description:"frozen: its requests refused, its machines and databases stopped, its data kept"}},scope:"account",async run(e){let t={};e.flags.cap!==void 0&&(t.cap_micros=e.flags.cap==="none"?null:is(e.flags.cap,"--cap"));let n=ht(e.flags.free,"free");n!==void 0&&(t.free=n);let s=ht(e.flags.frozen,"frozen");if(s!==void 0&&(t.frozen=s),Object.keys(t).length===0)throw g("nothing to change: pass --cap, --free or --frozen");let a=e.args[0],r=await Le(e.studio),i=a.lastIndexOf("/"),o=r.filter(h=>h.ref===a||i>0&&h.slug===a.slice(i+1)&&(h.project_name===a.slice(0,i)||`${h.org_name}/${h.project_name}`===a.slice(0,i)));if(o.length===0)throw new y("no_such_environment",`no environment ${JSON.stringify(a)} among yours`,{hint:"name it by its ref, or project/env: palbase projects:list shows them"});if(o.length>1)throw new y("ambiguous_environment",`${JSON.stringify(a)} names more than one environment`,{hint:"name it by its ref"});let l=o[0],d=`${l.org_name} \u203A ${l.project_name} \u203A ${l.name}`;if(e.out.note(`${d}: ${Object.entries(t).map(([h,m])=>`${h} ${m===null?"none":typeof m=="number"?$e(m):m}`).join(", ")}`),s===!0&&!e.global.yes){if(!e.interactive)throw new y("confirmation_needed","freezing an environment refuses its requests",{hint:"confirm with -y"});let h=(await e.io.prompt(K(`Freeze ${d}: its requests are refused until it is thawed. Go ahead? [y/N] `))).trim().toLowerCase();if(h!=="y"&&h!=="yes")throw new y("cancelled","nothing was changed")}let p=await e.studio.request("PATCH",`/orgs/${l.organization_id}/billing/environments/${l.ref}`,t),c=p.projects.find(h=>h.ref===l.ref);e.out.result(c??p,()=>{c?e.out.line(`${K(d)}: ${vm(c)}${c.cap_micros===null?"":`, cap ${$e(c.cap_micros)}`}${c.gross_micros===void 0?"":`, ${$e(c.gross_micros)} this month`}.`):e.out.line(`${K(d)} saved.`)})}},DR={name:"billing:topup",summary:"put money on an organization's balance from its saved card, now: $10 to $10,000, the tax on top, an invoice made of it",usage:"<usd> [-y] [--org <org>]",details:["It takes the money: it asks first, and -y does not. With no card saved yet, the first top-up is on Stripe's page, in Studio."],args:{min:1,max:1},flags:wn,scope:"account",async run(e){let t=is(e.args[0],"the amount");if(t<1e7||t>1e10)throw g("a top-up is $10 to $10,000");let n=await vn(e),s=await e.studio.get(`/orgs/${n.id}/billing`),a=s.account?.payment_method;if(!a)throw new y("no_card",`${n.name} has no card saved yet`,{hint:"the first top-up is on Stripe's page: Studio, Billing, Top up"});if(e.out.note(`${n.name}: take ${$e(t)} (tax on top) from ${a}${s.account?.stripe_mode==="test"?" (test mode)":""}`),!e.global.yes){if(!e.interactive)throw new y("confirmation_needed","a top-up takes money from the card",{hint:"confirm with -y"});let i=(await e.io.prompt(K(`Take ${$e(t)} from ${a}? [y/N] `))).trim().toLowerCase();if(i!=="y"&&i!=="yes")throw new y("cancelled","nothing was taken")}let r=await e.studio.post(`/orgs/${n.id}/billing/topups`,{amount_micros:t});e.out.result(r,()=>{r.status==="paid"?e.out.line(`${$e(t)} is on ${K(n.name)}'s balance (invoice ${r.invoice_id}).`):e.out.line(`The payment is not complete yet (${r.status}): the balance shows it once Stripe does${r.hosted_url?` \u2014 ${r.hosted_url}`:""}.`)})}},NR={name:"billing:bank-transfer",summary:"an invoice of a top-up to pay by bank transfer, to the organization's own bank details: credited as the money arrives",usage:"<usd> [--org <org>]",details:["Stripe emails the invoice with the bank details; nothing is taken until the transfer arrives."],args:{min:1,max:1},flags:wn,scope:"account",async run(e){let t=is(e.args[0],"the amount");if(t<1e7||t>1e12)throw g("a bank transfer is $10 to $1,000,000");let n=await vn(e),s=await e.studio.post(`/orgs/${n.id}/billing/bank-transfers`,{amount_micros:t});e.out.result(s,()=>e.out.line(`The invoice of ${$e(t)} is sent by email${s.hosted_url?`; with its bank details: ${s.hosted_url}`:""}. The balance shows it once the transfer arrives.`))}},km=[CR,jR,xR,IR,MR,LR,DR,NR];import{mkdtemp as qR,rm as KR}from"node:fs/promises";import{tmpdir as GR}from"node:os";import{extname as UR,join as Sm}from"node:path";async function Ys(e,t,n){if(n!==void 0)return n;let{body:s}=await ge(e.studio,t.env_ref,"GET","/databases?limit=100");if(s.databases.length===1)return s.databases[0].name;throw s.databases.length===0?new y("no_database","the environment has no database",{hint:"palbase databases:create opens one"}):g("which database? name it",`the environment's databases: ${s.databases.map(a=>a.name).join(", ")}`)}async function Lt(e,t,n,s,a){let{body:r}=await ge(e.studio,t.env_ref,"GET",`/databases/${H("the database's name",n)}/credentials`),i=(await e.state.databasePasswords(t.env_ref,n))[s];if(!i)throw new y("no_password",`this computer holds no ${s} password of ${n}: the platform showed it once, where the database was opened`,{hint:`palbase databases:password:reset ${n} --role ${s} makes a new one and keeps it here${s==="app"?" (the machines given it roll out with it)":""}`});let o=s==="owner"?r.owner:r.app,l=new URL(a?o.pooled_url:o.url);return l.password="",{url:l.toString(),password:i,role:s}}function BR(e){let t=new URL(e.url);return t.password=encodeURIComponent(e.password),t.toString()}var Pm={type:"string",value:"role",description:"owner (migrations, dumps) or app (what the machines use); default owner"};function Am(e){let t=e.flags.role??"owner";if(t!=="owner"&&t!=="app")throw g("--role is owner or app");return t}var Rm={PGSSLROOTCERT:"system"};async function _n(e,t,n,s,a=!1){let r=await e.io.run(t,n,{env:{PGPASSWORD:s.password,...Rm,PGAPPNAME:"palbase-cli"},inherit:a});if(r.code===127)throw new y("missing_tool",`${t} is not installed here`,{hint:"install the Postgres 18 client tools (brew install postgresql@18, apt install postgresql-client-18)"});return r}var Tm={name:"db:url",summary:"a database's connection address, for any tool (Prisma, Drizzle, pg_dump, a GUI)",usage:"[name] [--role owner|app] [--pooled] [--with-password]",details:["Without --with-password the address holds no password: give the tool PGPASSWORD, or pass --with-password and keep the line out of your history.","The address asks for a checked certificate (sslmode=verify-full). Node drivers check it against the system's roots by themselves; psql, pg_dump and other libpq tools do only with PGSSLROOTCERT=system (Postgres 16+). The address does not say so itself: a driver that sends what it does not know to the server (postgres.js) would be refused."],args:{min:0,max:1},flags:{role:Pm,pooled:{type:"boolean",description:"the pooled port (PgBouncer, transaction mode): for an app's many short connections"},"with-password":{type:"boolean",description:"put the password in the address"}},scope:"environment",async run(e){let t=await b(e),n=await Ys(e,t,e.args[0]),s=await Lt(e,t,n,Am(e),e.flags.pooled===!0),a=e.flags["with-password"]===!0?BR(s):s.url;e.out.result({database:n,role:s.role,url:a,libpq_env:Rm},()=>{e.io.stdout(`${a}
|
|
684
|
+
`;typeof e.flags.out=="string"?(await lm(pm(e.io.cwd,e.flags.out),a,{mode:384}),e.out.result({file:e.flags.out},()=>e.out.line(`Wrote ${n}'s data to ${e.flags.out}.`))):e.io.stdout(a)}},vR={name:"realtime:broadcast",summary:"send an event to a channel's subscribers, as the server does: its payload JSON (or text)",usage:"<topic> <event> [payload]",args:{min:2,max:3},scope:"environment",async run(e){let t=await b(e),[n,s,a]=e.args,r=a===void 0?null:ut(a);await k(e,t,`broadcast ${s} on ${n}`);let i=await f(e,t,"POST","/realtime/broadcast",{messages:[{topic:n,event:s,payload:r}]});e.out.result(i??{sent:1},()=>e.out.line(`Broadcast ${C(s)} on ${C(n)}.`))}},_R={name:"analytics:events",summary:"the events analytics recorded, newest first: by name, by user, over a window",usage:"[--name <event>] [--user <distinct-id>] [--window <24h>] [--limit <n>]",flags:{name:{type:"string",value:"event",description:"only this event's"},user:{type:"string",value:"id",description:"only this user's (their distinct id)"},window:{type:"string",value:"span",description:"how far back: 30m, 24h, 7d (default 24h)"},limit:{type:"string",value:"n",description:"how many (default 50)"}},scope:"environment",async run(e){let t=await b(e),n=new URLSearchParams({window_seconds:String(dm(e.flags.window,"window")??86400),limit:String(rs(e.flags.limit,"limit",1,1e3)??50),...e.flags.name?{name:e.flags.name}:{},...e.flags.user?{distinct_id:e.flags.user}:{}}),s=await f(e,t,"GET",`/analytics/events?${n}`);e.out.result(s,()=>{s.events.length===0&&e.out.line("No event in the window.");for(let a of s.events)e.out.line(`${C(Mt(a.timestamp??a.ts))} ${C(a.name)} ${C(a.distinct_id??"")}${a.properties&&Object.keys(a.properties).length?` ${C(JSON.stringify(a.properties)).slice(0,200)}`:""}`)})}},kR={name:"analytics:summary",summary:"what analytics counted over a window: events, users, sessions, the top events",usage:"[--window <24h>]",flags:{window:{type:"string",value:"span",description:"how far back: 30m, 24h, 7d (default 24h)"}},scope:"environment",async run(e){let t=await b(e),n=await f(e,t,"GET",`/analytics/summary?window_seconds=${dm(e.flags.window,"window")??86400}`);e.out.result(n,()=>{for(let[s,a]of Object.entries(n))e.out.line(`${C(s)}: ${typeof a=="object"?JSON.stringify(a):C(String(a))}`)})}},ym=[HA,XA,YA,ZA,QA,eR,tR,wR,gR,mR,fR,yR,bR,sR,aR,rR,iR,oR,lR,pR,cR,uR,hR,vR,_R,kR];var Hs=["machines:read","machines:logs","apps:sync","auth:test-users"];function bm(e){return e.scopes===null?"its minter's role":e.scopes.join(", ")}var SR={name:"env:tokens:create",summary:"mint a token of the environment for a program (an AI agent): your role in this environment alone, a few hours; shown this once",usage:"[--scope <scope>[,<scope>]] [--minutes <n>] [--name <name>]",details:["It does in this environment what your role does \u2014 as your own CLI would \u2014 but never makes or shows a standing credential (a key, a token), changes people or roles, or deletes a project or an environment; nothing beyond this environment.",`--scope narrows it to: ${Hs.join(", ")} \u2014 machines:read reads the machines, their builds, crons and queues; machines:logs their logs; apps:sync what palbase apps:sync reads; auth:test-users makes and deletes test users.`,"Give it to the program as PALBASE_TOKEN: the CLI acts in this environment alone with it. It ends after --minutes (default 60, at most 240), and with what minted it."],flags:{scope:{type:"string",multiple:!0,value:"scope",description:`narrow it to: ${Hs.join(", ")} (comma-separated, or given again); none: your role`},minutes:{type:"string",value:"n",description:"how long it lives (default 60, at most 240)"},name:{type:"string",value:"name",description:"what it is for, as the environment lists it"}},scope:"environment",async run(e){let t=ie(e.flags.scope),n=t===void 0?void 0:[...new Set(t)];if(n!==void 0&&n.length===0)throw g(`--scope names what the token is narrowed to: ${Hs.join(", ")}`);let s=(n??[]).filter(o=>!Hs.includes(o));if(s.length>0)throw g(`${s.join(", ")}: no scope of an environment's token (${Hs.join(", ")})`);let a=e.flags.minutes===void 0?60:Number(e.flags.minutes);if(!Number.isInteger(a)||a<5||a>240)throw g("--minutes is a whole number from 5 to 240");let r=await b(e),i=await e.studio.post(`/environments/${r.env_ref}/tokens`,{...n!==void 0?{scopes:n}:{},expires_in_minutes:a,...typeof e.flags.name=="string"?{name:e.flags.name}:{}});e.out.result(i,()=>{e.out.line(`Minted ${K(i.name)} for ${q(r)} (${bm(i)}; until ${i.expires_at.slice(0,16).replace("T"," ")} UTC).`),e.out.line(`token (shown this once \u2014 the program's PALBASE_TOKEN): ${i.token}`)})}},$R={name:"env:tokens:list",summary:"the environment's live tokens, by their hint (never their values)",scope:"environment",async run(e){let t=await b(e),{tokens:n}=await e.studio.get(`/environments/${t.env_ref}/tokens`);e.out.result({tokens:n},()=>{n.length===0&&e.out.line(`${q(t)} has no live token: palbase env:tokens:create --scope <scope> mints one.`),e.out.table(n,[{header:"id",value:s=>s.id},{header:"name",value:s=>K(s.name)},{header:"can",value:s=>bm(s)},{header:"ends",value:s=>s.expires_at.slice(0,16).replace("T"," ")},{header:"minted by",value:s=>s.minted_by},{header:"hint",value:s=>`\u2026${s.hint}`}])})}},PR={name:"env:tokens:revoke",summary:"revoke an environment's token (by its id; with PALBASE_TOKEN an environment's token, `self` revokes it): refused from its next request on",usage:"<id|self>",args:{min:1,max:1},scope:"environment",async run(e){let t=await b(e),n=e.args[0];if(n==="self"){let s=(await e.studio.get("/environments")).environments.find(a=>a.ref===t.env_ref)?.token_id;if(!s)throw new y("not_a_token","self is the environment token PALBASE_TOKEN is, and it is none",{hint:"name the token by its id: palbase env:tokens:list"});n=s}await e.studio.request("DELETE",`/environments/${H("the environment's ref",t.env_ref)}/tokens/${H("the token's id",n)}`),e.out.result({revoked:n},()=>e.out.line(`Revoked the environment token ${n} of ${q(t)}.`))}},wm=[$R,SR,PR];var wn={org:{type:"string",value:"org",description:"the organization (name or id; the one of the environment chosen here, or your only one)"}};function $e(e){let t=e<0?"-":"",n=Math.abs(e);if(n>0&&n<1e4)return`${t}$${(n/1e6).toFixed(6).replace(/0{1,4}$/,"")}`;let s=Math.round(n/1e4);return`${t}$${Math.floor(s/100).toLocaleString("en-US")}.${String(s%100).padStart(2,"0")}`}function is(e,t){let n=typeof e=="string"?/^\s*\$?\s*(\d{1,9})(?:\.(\d{1,2}))?\s*$/.exec(e):null;if(!n)throw g(`${t} is an amount in US dollars, to the cent (20 or 20.50)`);return Number(n[1])*1e6+Number((n[2]??"").padEnd(2,"0"))*1e4}var Xs=e=>`${(e/2**30).toFixed(2)} GiB`,AR=e=>e.toLocaleString("en-US"),RR={egress:Xs,storage:e=>`${Xs(e)} (month's peak)`,"db.backups":e=>`${Xs(e)} (month's peak)`,images:e=>`${Xs(e)} (month's peak)`,logs:Xs,cache:e=>`${(e/2**20).toFixed(1)} MiB (month's peak)`,builds:e=>`${(e/60).toFixed(1)} min`,"ai.workspaces":e=>`${(e/3600).toFixed(1)} h`,"ai.models":e=>`$${(e/1e9).toFixed(4)} at the provider`};function TR(e,t){return e.startsWith("machine.")||e.startsWith("db.")&&e!=="db.backups"?`${(t/3600).toFixed(1)} h`:(RR[e]??AR)(t)}async function vn(e){let t=e.flags.org;return t===void 0&&(t=(await e.state.targetFor(e.io.cwd))?.target.org_id),mt(e,t)}function vm(e){return e.gone?"left the organization":e.deleted?"deleted":e.frozen?"frozen":e.free?"Free":e.cap_micros!==null&&(e.gross_micros??0)>=e.cap_micros?"at its cap":e.paid?"Pay as you go":"Free quotas"}function ER(e){return e.exempt?"Not billed: measured, never charged":e.has_account&&e.account?.terms_version?e.paying||!e.enforced?"Pay as you go (the free quota once for the organization)":"Pay as you go, no balance: the Free limits hold until a top-up":"Free (open the payment account in Studio, Billing, for paid sizes and more than 2 projects)"}function _m(e,t,n){let s=new Map(n.environments.map(i=>[i.platform_id,`${i.project_name} \u203A ${i.name}`])),a=n.account;e.out.line(`${K(t)} \u2014 ${ER(n)}`),a&&(e.out.line(`balance: ${$e(a.balance_micros)}${a.exhausted?" (ran out: what is paid for has stopped)":""} \xB7 ${a.payment_method?`card ${K(a.payment_method)}`:"no card saved yet"}${a.stripe_mode==="test"?" \xB7 test mode":""}`),e.out.line(`automatic top-up: ${a.auto_topup?`${$e(a.auto_amount_micros)} under ${$e(a.auto_threshold_micros)}${a.monthly_cap_micros?`, at most ${$e(a.monthly_cap_micros)} a month`:""}`:"off (the balance is the ceiling)"}`),e.out.line(`told when it lasts fewer than ${a.low_balance_days} days of spend`));let r=new Date(`${n.period}-01T00:00:00Z`).toLocaleDateString("en-US",{month:"long",year:"numeric",timeZone:"UTC"});n.taken_micros!==void 0&&e.out.line(`${r}: ${$e(n.exempt?n.charged_micros??0:n.taken_micros)} ${n.exempt?"priced, not taken":"taken from the balance so far"}`),e.out.line(),e.out.table(n.projects,[{header:"environment",value:i=>K(s.get(i.project_id)??i.name)},{header:"ref",value:i=>i.ref},{header:"plan",value:vm},{header:"gross",value:i=>i.gross_micros===void 0?"":$e(i.gross_micros)},{header:"cap",value:i=>i.cap_micros===null?"":$e(i.cap_micros)}])}var CR={name:"billing",summary:"an organization's plan, balance, card, automatic top-up and this month \u2014 each environment's place in the bill and what it came to",usage:"[--org <org>]",details:["A member reads the plan and the environments; the money (balance, amounts) is an owner's or an admin's."],flags:wn,scope:"account",async run(e){let t=await vn(e),n=await e.studio.get(`/orgs/${t.id}/billing`);e.out.result(n,()=>_m(e,t.name,n))}},jR={name:"billing:charges",summary:"a month's charges, by environment and item, gross \u2014 then the organization's, its free quota taken once \u2014 as a table or as CSV",usage:"[--period <YYYY-MM>] [--csv] [--org <org>]",details:["--csv prints the CSV Studio downloads: what an organization bills its own customers by."],flags:{...wn,period:{type:"string",value:"YYYY-MM",description:"the month (this one by default)"},csv:{type:"boolean",description:"print the charges as CSV"}},scope:"account",async run(e){let t=e.flags.period;if(t!==void 0&&!/^\d{4}-(0[1-9]|1[0-2])$/.test(t))throw g("--period is a month: YYYY-MM");let n=await vn(e),s=t?`?period=${t}`:"";if(e.flags.csv===!0){e.io.stdout(K(await e.studio.get(`/orgs/${n.id}/billing/charges.csv${s}`)));return}let a=await e.studio.get(`/orgs/${n.id}/billing/charges${s}`);e.out.result(a,()=>{let r=[...a.charges.filter(i=>i.project_id!==""),...a.charges.filter(i=>i.project_id==="")];r.length===0?e.out.line(`${K(n.name)} used nothing in ${a.period}.`):e.out.table(r,[{header:"environment",value:i=>i.project_id===""?"(organization)":K(i.project_name&&i.name?`${i.project_name} \u203A ${i.name}`:i.ref??i.project_id)},{header:"item",value:i=>i.item==="total"?"priced":i.item},{header:"used",value:i=>i.item==="total"?"":TR(i.item,i.units)},{header:"amount",value:i=>$e(i.micros)}]),e.out.line(`${a.period}: ${$e(a.taken_micros)} taken from the balance.`)})}},OR={checkout:"top-up (card)",auto:"automatic top-up",card:"top-up (saved card)",bank_transfer:"bank transfer"},xR={name:"billing:invoices",summary:"the invoices of an organization's top-ups: Stripe makes one of each, and emails it",usage:"[--org <org>]",flags:wn,scope:"account",async run(e){let t=await vn(e),{invoices:n}=await e.studio.get(`/orgs/${t.id}/billing/invoices`);e.out.result({invoices:n},()=>{n.length===0?e.out.line(`${K(t.name)} has no invoice yet.`):e.out.table(n,[{header:"date",value:s=>s.created_at.slice(0,16).replace("T"," ")},{header:"top-up",value:s=>OR[s.kind]??s.kind},{header:"amount",value:s=>`${$e(s.amount_micros)}${s.tax_micros>0?` + ${$e(s.tax_micros)} tax`:""}`},{header:"status",value:s=>s.status==="void"&&(s.kind==="auto"||s.kind==="card")?"declined":s.status},{header:"invoice",value:s=>s.hosted_url??""}])})}},IR={name:"billing:ledger",summary:"every change of an organization's balance, newest first: top-ups, usage taken, refunds, what expired",usage:"[--limit <n>] [--org <org>]",flags:{...wn,limit:{type:"string",value:"n",description:"how many at most (default 50)"}},scope:"account",async run(e){let t=e.flags.limit===void 0?50:Number(e.flags.limit);if(!Number.isInteger(t)||t<1||t>1e4)throw g("--limit is a whole number from 1 to 10000");let n=await vn(e),s=[],a;for(;;){let i=await e.studio.get(`/orgs/${n.id}/billing/ledger${a?`?before=${a}`:""}`);if(s.push(...i.lines),i.lines.length===0||s.length>=t)break;a=i.lines[i.lines.length-1].id}let r=s.slice(0,t);e.out.result({lines:r},()=>{r.length===0?e.out.line(`${K(n.name)}'s balance has not changed yet.`):e.out.table(r,[{header:"when",value:i=>i.created_at.slice(0,16).replace("T"," ")},{header:"kind",value:i=>i.kind},{header:"amount",value:i=>$e(i.amount_micros)},{header:"left of it",value:i=>i.remaining_micros===null?"":$e(i.remaining_micros)},{header:"ref",value:i=>K(i.ref)}])})}},MR={name:"billing:settings",summary:"an organization's automatic top-up \u2014 on or off, under what balance, by how much, at most how much a month \u2014 and when it is told the balance runs low",usage:"[--auto-topup yes|no] [--threshold <usd>] [--amount <usd>] [--monthly-cap <usd>|none] [--low-balance-days <n>] [--org <org>]",details:["A month's cap takes what is left of it, and nothing once it is spent: the owners are emailed once a month when it holds a top-up back."],flags:{...wn,"auto-topup":{type:"string",value:"yes|no",description:"take a top-up from the saved card when the balance is under the threshold"},threshold:{type:"string",value:"usd",description:"the balance under which it is taken"},amount:{type:"string",value:"usd",description:"how much it takes ($10 at least)"},"monthly-cap":{type:"string",value:"usd|none",description:"at most this much a calendar month; none for no cap"},"low-balance-days":{type:"string",value:"n",description:"email the owners when the balance lasts fewer than n days of spend (1 to 60)"}},scope:"account",async run(e){let t={},n=ht(e.flags["auto-topup"],"auto-topup");if(n!==void 0&&(t.auto_topup=n),e.flags.threshold!==void 0&&(t.auto_threshold_micros=is(e.flags.threshold,"--threshold")),e.flags.amount!==void 0&&(t.auto_amount_micros=is(e.flags.amount,"--amount")),e.flags["monthly-cap"]!==void 0&&(t.monthly_cap_micros=e.flags["monthly-cap"]==="none"?null:is(e.flags["monthly-cap"],"--monthly-cap")),e.flags["low-balance-days"]!==void 0){let r=Number(e.flags["low-balance-days"]);if(!Number.isInteger(r)||r<1||r>60)throw g("--low-balance-days is a whole number from 1 to 60");t.low_balance_days=r}if(Object.keys(t).length===0)throw g("nothing to change: pass --auto-topup, --threshold, --amount, --monthly-cap or --low-balance-days");let s=await vn(e);await e.studio.request("PATCH",`/orgs/${s.id}/billing`,t);let a=await e.studio.get(`/orgs/${s.id}/billing`);e.out.result(a,()=>_m(e,s.name,a))}},LR={name:"billing:env",summary:"an environment's place in its organization's bill: a monthly cap, pulled to the Free plan, frozen",usage:"<project/env | ref> [--cap <usd>|none] [--free yes|no] [--frozen yes|no] [-y]",details:["At its cap the environment is Free until the month ends; the others go on. Frozen, its requests are refused and its machines and databases stopped, its data kept; only what it stores is charged.","Freezing asks first; -y does not."],args:{min:1,max:1},flags:{cap:{type:"string",value:"usd|none",description:"at most this much a month; none for no cap"},free:{type:"string",value:"yes|no",description:"on the Free plan: charged nothing, held to the free quotas"},frozen:{type:"string",value:"yes|no",description:"frozen: its requests refused, its machines and databases stopped, its data kept"}},scope:"account",async run(e){let t={};e.flags.cap!==void 0&&(t.cap_micros=e.flags.cap==="none"?null:is(e.flags.cap,"--cap"));let n=ht(e.flags.free,"free");n!==void 0&&(t.free=n);let s=ht(e.flags.frozen,"frozen");if(s!==void 0&&(t.frozen=s),Object.keys(t).length===0)throw g("nothing to change: pass --cap, --free or --frozen");let a=e.args[0],r=await Le(e.studio),i=a.lastIndexOf("/"),o=r.filter(h=>h.ref===a||i>0&&h.slug===a.slice(i+1)&&(h.project_name===a.slice(0,i)||`${h.org_name}/${h.project_name}`===a.slice(0,i)));if(o.length===0)throw new y("no_such_environment",`no environment ${JSON.stringify(a)} among yours`,{hint:"name it by its ref, or project/env: palbase projects:list shows them"});if(o.length>1)throw new y("ambiguous_environment",`${JSON.stringify(a)} names more than one environment`,{hint:"name it by its ref"});let l=o[0],d=`${l.org_name} \u203A ${l.project_name} \u203A ${l.name}`;if(e.out.note(`${d}: ${Object.entries(t).map(([h,m])=>`${h} ${m===null?"none":typeof m=="number"?$e(m):m}`).join(", ")}`),s===!0&&!e.global.yes){if(!e.interactive)throw new y("confirmation_needed","freezing an environment refuses its requests",{hint:"confirm with -y"});let h=(await e.io.prompt(K(`Freeze ${d}: its requests are refused until it is thawed. Go ahead? [y/N] `))).trim().toLowerCase();if(h!=="y"&&h!=="yes")throw new y("cancelled","nothing was changed")}let p=await e.studio.request("PATCH",`/orgs/${l.organization_id}/billing/environments/${l.ref}`,t),c=p.projects.find(h=>h.ref===l.ref);e.out.result(c??p,()=>{c?e.out.line(`${K(d)}: ${vm(c)}${c.cap_micros===null?"":`, cap ${$e(c.cap_micros)}`}${c.gross_micros===void 0?"":`, ${$e(c.gross_micros)} this month`}.`):e.out.line(`${K(d)} saved.`)})}},DR={name:"billing:topup",summary:"put money on an organization's balance from its saved card, now: $10 to $10,000, the tax on top, an invoice made of it",usage:"<usd> [-y] [--org <org>]",details:["It takes the money: it asks first, and -y does not. With no card saved yet, the first top-up is on Stripe's page, in Studio."],args:{min:1,max:1},flags:wn,scope:"account",async run(e){let t=is(e.args[0],"the amount");if(t<1e7||t>1e10)throw g("a top-up is $10 to $10,000");let n=await vn(e),s=await e.studio.get(`/orgs/${n.id}/billing`),a=s.account?.payment_method;if(!a)throw new y("no_card",`${n.name} has no card saved yet`,{hint:"the first top-up is on Stripe's page: Studio, Billing, Top up"});if(e.out.note(`${n.name}: take ${$e(t)} (tax on top) from ${a}${s.account?.stripe_mode==="test"?" (test mode)":""}`),!e.global.yes){if(!e.interactive)throw new y("confirmation_needed","a top-up takes money from the card",{hint:"confirm with -y"});let i=(await e.io.prompt(K(`Take ${$e(t)} from ${a}? [y/N] `))).trim().toLowerCase();if(i!=="y"&&i!=="yes")throw new y("cancelled","nothing was taken")}let r=await e.studio.post(`/orgs/${n.id}/billing/topups`,{amount_micros:t});e.out.result(r,()=>{r.status==="paid"?e.out.line(`${$e(t)} is on ${K(n.name)}'s balance (invoice ${r.invoice_id}).`):e.out.line(`The payment is not complete yet (${r.status}): the balance shows it once Stripe does${r.hosted_url?` \u2014 ${r.hosted_url}`:""}.`)})}},NR={name:"billing:bank-transfer",summary:"an invoice of a top-up to pay by bank transfer, to the organization's own bank details: credited as the money arrives",usage:"<usd> [--org <org>]",details:["Stripe emails the invoice with the bank details; nothing is taken until the transfer arrives."],args:{min:1,max:1},flags:wn,scope:"account",async run(e){let t=is(e.args[0],"the amount");if(t<1e7||t>1e12)throw g("a bank transfer is $10 to $1,000,000");let n=await vn(e),s=await e.studio.post(`/orgs/${n.id}/billing/bank-transfers`,{amount_micros:t});e.out.result(s,()=>e.out.line(`The invoice of ${$e(t)} is sent by email${s.hosted_url?`; with its bank details: ${s.hosted_url}`:""}. The balance shows it once the transfer arrives.`))}},km=[CR,jR,xR,IR,MR,LR,DR,NR];import{mkdtemp as qR,rm as KR}from"node:fs/promises";import{tmpdir as GR}from"node:os";import{extname as UR,join as Sm}from"node:path";async function Ys(e,t,n){if(n!==void 0)return n;let{body:s}=await ge(e.studio,t.env_ref,"GET","/databases?limit=100");if(s.databases.length===1)return s.databases[0].name;throw s.databases.length===0?new y("no_database","the environment has no database",{hint:"palbase databases:create opens one"}):g("which database? name it",`the environment's databases: ${s.databases.map(a=>a.name).join(", ")}`)}async function Lt(e,t,n,s,a){let{body:r}=await ge(e.studio,t.env_ref,"GET",`/databases/${H("the database's name",n)}/credentials`),i=(await e.state.databasePasswords(t.env_ref,n))[s];if(!i)throw new y("no_password",`this computer holds no ${s} password of ${n}: the platform showed it once, where the database was opened`,{hint:`palbase databases:password:reset ${n} --role ${s} makes a new one and keeps it here${s==="app"?" (the machines given it roll out with it)":""}`});let o=s==="owner"?r.owner:r.app,l=new URL(a?o.pooled_url:o.url);return l.password="",{url:l.toString(),password:i,role:s}}function BR(e){let t=new URL(e.url);return t.password=encodeURIComponent(e.password),t.toString()}var Pm={type:"string",value:"role",description:"owner (migrations, dumps) or app (what the machines use); default owner"};function Am(e){let t=e.flags.role??"owner";if(t!=="owner"&&t!=="app")throw g("--role is owner or app");return t}var Rm={PGSSLROOTCERT:"system"};async function _n(e,t,n,s,a=!1){let r=await e.io.run(t,n,{env:{PGPASSWORD:s.password,...Rm,PGAPPNAME:"palbase-cli"},inherit:a});if(r.code===127)throw new y("missing_tool",`${t} is not installed here`,{hint:"install the Postgres 18 client tools (brew install postgresql@18, apt install postgresql-client-18)"});return r}var Tm={name:"db:url",summary:"a database's connection address, for any tool (Prisma, Drizzle, pg_dump, a GUI)",usage:"[name] [--role owner|app] [--pooled] [--with-password]",details:["Without --with-password the address holds no password: give the tool PGPASSWORD, or pass --with-password and keep the line out of your history.","The address asks for a checked certificate (sslmode=verify-full). Node drivers check it against the system's roots by themselves; psql, pg_dump and other libpq tools do only with PGSSLROOTCERT=system (Postgres 16+). The address does not say so itself: a driver that sends what it does not know to the server (postgres.js) would be refused."],args:{min:0,max:1},flags:{role:Pm,pooled:{type:"boolean",description:"the pooled port (PgBouncer, transaction mode): for an app's many short connections"},"with-password":{type:"boolean",description:"put the password in the address"}},scope:"environment",async run(e){let t=await b(e),n=await Ys(e,t,e.args[0]),s=await Lt(e,t,n,Am(e),e.flags.pooled===!0),a=e.flags["with-password"]===!0?BR(s):s.url;e.out.result({database:n,role:s.role,url:a,libpq_env:Rm},()=>{e.io.stdout(`${a}
|
|
685
685
|
`),e.out.note("psql, pg_dump and other libpq tools: PGSSLROOTCERT=system (Postgres 16+), or they cannot check the certificate")})}},Em={name:"db:shell",summary:"psql on a database (it wakes if asleep); -c runs one statement and ends",usage:"[name] [--role owner|app] [--command <sql>]",args:{min:0,max:1},flags:{role:Pm,command:{type:"string",short:"c",value:"sql",description:"run this and end"}},scope:"environment",async run(e){let t=await b(e),n=await Ys(e,t,e.args[0]),s=await Lt(e,t,n,Am(e),!1),a=e.flags.command;if(a!==void 0){let i=await _n(e,"psql",[s.url,"-v","ON_ERROR_STOP=1","-X","-c",a],s);if(i.stdout&&e.io.stdout(i.stdout),i.code!==0)throw new y("psql_failed",i.stderr.trim()||`psql ended with ${i.code}`);return}if(!e.interactive)throw g("db:shell with no person at the terminal needs --command <sql>");return e.out.note(`${q(t)} \u203A ${n} as ${s.role}`),(await _n(e,"psql",[s.url],s,!0)).code}},Cm={name:"db:dump",summary:"a copy of a database (pg_dump's custom format), as its owner",usage:"[name] [--file <path>] [--schema-only]",args:{min:0,max:1},flags:{file:{type:"string",value:"path",description:"where to write it (default <database>-<time>.dump)"},"schema-only":{type:"boolean",description:"its structure, not its data"}},scope:"environment",async run(e){let t=await b(e),n=await Ys(e,t,e.args[0]),s=await Lt(e,t,n,"owner",!1),a=e.flags.file??`${n}-${new Date(e.io.now()).toISOString().replaceAll(":","-").slice(0,19)}.dump`,r=await _n(e,"pg_dump",["--format=custom","--no-owner","--no-acl",...e.flags["schema-only"]===!0?["--schema-only"]:[],"--file",a,s.url],s);if(r.code!==0)throw new y("pg_dump_failed",r.stderr.trim()||`pg_dump ended with ${r.code}`);e.out.result({database:n,file:a},()=>e.out.line(`Wrote ${a}.`))}},jm={name:"db:restore",summary:"load a dump into a database, as its owner: a custom-format dump (pg_restore) or a .sql file (psql)",usage:"<file> [--db <name>] [--clean]",details:["A database Palbase did not make is taken over by its first release: its tables stay as they are (palbase db:pull writes their schema files)."],args:{min:1,max:1},flags:{db:{type:"string",value:"name",description:"the database (default: the environment's only one)"},clean:{type:"boolean",description:"drop what the dump makes before making it again"}},scope:"environment",async run(e){let t=await b(e),n=await Ys(e,t,e.flags.db),s=e.args[0];await k(e,t,`load ${s} into the database ${n}`);let a=await Lt(e,t,n,"owner",!1);await Om(e,a,s,e.flags.clean===!0),e.out.result({database:n,loaded:s},()=>e.out.line(`Loaded ${s} into ${n}.`))}};async function Om(e,t,n,s){let a=UR(n).toLowerCase()===".sql",r=a?await _n(e,"psql",[t.url,"-v","ON_ERROR_STOP=1","-X","--single-transaction","-f",n],t):await _n(e,"pg_restore",["--no-owner","--no-acl","--exit-on-error","--single-transaction",...s?["--clean","--if-exists"]:[],"--dbname",t.url,n],t);if(r.code!==0)throw new y("restore_failed",r.stderr.trim()||`${a?"psql":"pg_restore"} ended with ${r.code}`)}var $m="\u2022\u2022\u2022";async function zR(e,t,n){let s=async l=>{let d=await _n(e,"psql",[n.url,"-v","ON_ERROR_STOP=1","-X","-At","-F"," ","-c",l],n);if(d.code!==0)throw new y("redact_failed",d.stderr.trim()||`psql ended with ${d.code}`);return d.stdout.split(`
|
|
686
686
|
`).filter(p=>p!=="").map(p=>p.split(" "))},a=l=>`"${l.replace(/"/g,'""')}"`,r=l=>`'${l.replace(/'/g,"''")}'`,i=await s("SELECT c.table_schema, c.table_name, c.column_name, EXISTS (SELECT 1 FROM information_schema.columns l WHERE l.table_schema = c.table_schema AND l.table_name = c.table_name AND l.column_name = c.column_name || '_lookup') FROM information_schema.columns c JOIN information_schema.tables t ON t.table_schema = c.table_schema AND t.table_name = c.table_name AND t.table_type = 'BASE TABLE' WHERE c.data_type = 'text' AND c.table_schema NOT IN ('pg_catalog', 'information_schema', 'palgres', 'palgres_search', 'palbase') AND c.table_schema NOT LIKE 'palgres\\_%' ORDER BY 1, 2, 3"),o=[];if(i.length>0){let l=await s(i.map(([d,p,c])=>`SELECT ${r(`${d} ${p} ${c}`)} WHERE EXISTS (SELECT 1 FROM ${a(d)}.${a(p)} WHERE ${a(c)} LIKE 'pbe1.%')`).join(" UNION ALL "));for(let[d,p,c]of l){let h=i.find(T=>T[0]===d&&T[1]===p&&T[2]===c)?.[3]==="t",m=d==="public"?`${p}.${c}`:`${d}.${p}.${c}`,{value:w}=await f(e,t,"POST","/secrets/fields/placeholder",{address:m}),[[v]]=await s(`WITH done AS (UPDATE ${a(d)}.${a(p)} SET ${a(c)} = ${r(w)}${h?`, ${a(`${c}_lookup`)} = NULL`:""} WHERE ${a(c)} LIKE 'pbe1.%' RETURNING 1) SELECT count(*) FROM done`);o.push({address:m,rows:Number(v)})}}return await s("DO $$ BEGIN IF to_regclass('palbase.idempotency_keys') IS NOT NULL THEN DELETE FROM palbase.idempotency_keys WHERE response_body LIKE 'pbe1.%'; END IF; END $$"),o}var xm={name:"db:copy",summary:"copy a database's data from one environment of the project to another",usage:"--from <env> --to <env> [--db <name>] [--to-db <name>]",details:["The target is overwritten with the source: what it held of the same tables goes (pg_restore --clean).",`An encrypted field (.encrypted(), palbase/server's fields) is copied as ${$m}, sealed with the target's keys: one environment's values never land readable in another.`],flags:{from:{type:"string",value:"env",description:"the environment copied from (slug)"},to:{type:"string",value:"env",description:"the environment copied into (slug)"},db:{type:"string",value:"name",description:"the source's database (default: its only one)"},"to-db":{type:"string",value:"name",description:"the target's database (default: the same name)"}},scope:"environment",async run(e){let t=e.flags.from,n=e.flags.to;if(!t||!n)throw g("db:copy needs --from <env> and --to <env>");if(t===n)throw g("--from and --to are two environments");let s=await Rt(e),a=s.find(w=>w.slug===t),r=s.find(w=>w.slug===n);if(!a||!r)throw new y("no_such_environment",`the project has no environment ${JSON.stringify(a?n:t)}`);let i=ve(a),o=ve(r),l=await Ys(e,i,e.flags.db),d=e.flags["to-db"]??l;await k(e,o,`overwrite the database ${d} with ${i.env_slug}'s ${l}`);let p=await Lt(e,i,l,"owner",!1),c=await Lt(e,o,d,"owner",!1),h=await qR(Sm(GR(),"palbase-copy-"));try{let w=Sm(h,"copy.dump"),v=await _n(e,"pg_dump",["--format=custom","--no-owner","--no-acl","--file",w,p.url],p);if(v.code!==0)throw new y("pg_dump_failed",v.stderr.trim()||`pg_dump ended with ${v.code}`);await Om(e,c,w,!0)}finally{await KR(h,{recursive:!0,force:!0})}let m=await zR(e,o,c);e.out.result({from:{env:i.env_slug,database:l},to:{env:o.env_slug,database:d},redacted:m},()=>{e.out.line(`Copied ${i.env_slug}/${l} into ${o.env_slug}/${d}.`);for(let w of m)e.out.line(` ${w.address}: ${w.rows} encrypted value(s) copied as ${$m}`)})}};import{lstat as FR,mkdir as JR,readFile as WR,rename as VR,rm as HR,writeFile as XR}from"node:fs/promises";import{dirname as Im,resolve as YR}from"node:path";var Mm="// palbase:stack:begin",Lm="// palbase:stack:end",ZR=/^[A-Za-z_$][A-Za-z0-9_$]*$/,Er=e=>ZR.test(e)?e:JSON.stringify(e),kn=e=>[...new Set(e)].sort();function Cr(e,t){return t.length===0?[` interface ${e} {}`]:[` interface ${e} {`,...t.map(n=>` ${n}`)," }"]}function jo(e){let t=[...e.buckets].sort((n,s)=>n.name<s.name?-1:n.name>s.name?1:0);return[Mm,'declare module "palbase/backend/stack" {',...Cr("Secrets",kn(e.secrets).map(n=>`${Er(n)}: true;`)),"",...Cr("Flags",kn(e.flags).map(n=>`${Er(n)}: true;`)),"",...Cr("Buckets",t.map(n=>{let s=kn(n.variants);return`${Er(n.name)}: { variants: ${s.length===0?"never":s.map(a=>JSON.stringify(a)).join(" | ")} };`})),"",...Cr("Roles",kn(e.roles).map(n=>`${Er(n)}: true;`)),"}",Lm].join(`
|
|
687
687
|
`)}function os(e,t,n={begin:Mm,end:Lm,said:"palbase types:pull writes the block between the markers: the names this environment holds, for palbase/backend/stack."}){if(e===void 0)return`// ${n.said}
|
package/dist/refuse/ai.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/ai is for servers: it speaks with the project secret key, which never goes into a browser or a mobile app \u2014 call your backend, and let it ask the model");
|
package/dist/refuse/backend.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/backend is a server framework: it runs on your backend, never in a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs)");
|
package/dist/refuse/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
throw new Error("palbase/server is for servers: its secret key never goes into a browser or a mobile app \u2014 apps use palbase/web (or the native SDKs) with the publishable key");
|
package/dist/server/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{a as e,b as f,c as g,d as h,e as i,f as j,g as k,h as l,i as m,j as n,k as o,l as p,m as q,n as r,o as s,p as t,q as u,r as v,s as w,t as x,u as y}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as e,b as f,c as g,d as h,e as i,f as j,g as k,h as l,i as m,j as n,k as o,l as p,m as q,n as r,o as s,p as t,q as u,r as v,s as w,t as x,u as y}from"../chunks/UMCUTNWL.js";import{a as c,b as d}from"../chunks/ABRUIWQ3.js";import"../chunks/B33QXIR5.js";import"../chunks/X2BWW2WC.js";import{m as b}from"../chunks/WAMYRYDY.js";import"../chunks/ZOF56QTG.js";import{b as a}from"../chunks/7ZSVOQFN.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";export{o as AuthUnavailable,b as EVENT_TYPES,c as FieldError,d as Fields,a as PalbaseError,t as ReservationSettled,n as TokenError,q as TokenVerifier,f as Transit,e as TransitRefusal,g as TransitRequest,i as WebhookSignatureError,h as createServer,s as isEntitled,y as loadSecrets,v as pages,x as platformOwn,w as processOwn,r as requestAddress,p as sessionStanding,l as signatureHeader,k as verifySignature,j as verifyWebhook,m as verifyWebhookRequest,u as withReservation};
|
package/dist/server/testing.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{a,b,c,d,e}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a,b,c,d,e}from"../chunks/53ZQBGJV.js";import"../chunks/ABRUIWQ3.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";export{b as TestApiError,e as api,c as createTestApi,a as testFields,d as testRun};
|
package/dist/web/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{a as M,b as j,c as q,d as G,e as N,f as U,g as D,h as H,i as J,j as B,k as F,l as K,m as W,n as X,o as Y,p as Z,q as ee}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as M,b as j,c as q,d as G,e as N,f as U,g as D,h as H,i as J,j as B,k as F,l as K,m as W,n as X,o as Y,p as Z,q as ee}from"../chunks/LDZ7OKNS.js";import{a as _,b as Q,f as z}from"../chunks/ZT4AKS6D.js";import"../chunks/QCZJK4GZ.js";import"../chunks/JWLK6SLN.js";import"../chunks/NRWY25JZ.js";import{b as E,c as T,d as x,f as O,g as A,j as R,k as $,l as V,m as v,o as S}from"../chunks/B33QXIR5.js";import"../chunks/2DBSGJ7Z.js";import"../chunks/WAMYRYDY.js";import"../chunks/ZOF56QTG.js";import{b as L}from"../chunks/7ZSVOQFN.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";var te="oai-events";async function ne(e){if(typeof e?.start!="function")throw new TypeError("connectVoice: start(sdp) is the round trip to the app's backend, which starts the voice (chats.voice.start) and answers { id, sdp }");let r=e.rtc??se(),t=e.signal;t?.throwIfAborted();let f=e.audio??ae(),l=e.microphone===void 0,c=e.microphone??await r.getUserMedia({audio:!0});if(t?.aborted){if(l)for(let n of c.getTracks())n.stop();throw t.reason}let o=new r.RTCPeerConnection,s=!1,u=()=>{if(!s){if(s=!0,m.close(),o.close(),l)for(let n of c.getTracks())n.stop();f.srcObject!==null&&(f.srcObject=null)}};o.addEventListener("track",n=>{f.srcObject=n.streams[0]??new MediaStream([n.track]),f.play?.()?.catch?.(()=>{})}),o.addEventListener("connectionstatechange",()=>e.onState?.(o.connectionState));for(let n of c.getAudioTracks())o.addTrack(n,c);let m=o.createDataChannel(te);m.addEventListener("message",n=>{let p=oe(n.data);p!==void 0&&e.onError?.(p)});let d=()=>u();t?.addEventListener("abort",d,{once:!0});try{await o.setLocalDescription(await o.createOffer()),t?.throwIfAborted(),await re(o,e.iceTimeoutMs??1e4,t);let n=o.localDescription?.sdp;if(!n)throw new Error("connectVoice: the peer connection made no offer");let p=await e.start(n);if(t?.throwIfAborted(),typeof p?.id!="string"||p.id===""||typeof p.sdp!="string"||p.sdp==="")throw new TypeError("connectVoice: start answered no voice \u2014 it is { id, sdp }, chats.voice.start's answer as the backend got it");return await o.setRemoteDescription({type:"answer",sdp:p.sdp}),t?.removeEventListener("abort",d),{id:p.id,peer:o,audio:f,microphone:c,get muted(){return c.getAudioTracks().every(h=>!h.enabled)},mute(h){for(let w of c.getAudioTracks())w.enabled=!h},close:u}}catch(n){throw t?.removeEventListener("abort",d),u(),t?.aborted?t.reason:n}}function re(e,r,t){return e.iceGatheringState==="complete"?Promise.resolve():t?.aborted?Promise.reject(t.reason):new Promise((f,l)=>{let c=()=>{clearTimeout(u),e.removeEventListener("icegatheringstatechange",o),t?.removeEventListener("abort",s)},o=()=>{e.iceGatheringState==="complete"&&(c(),f())},s=()=>{c(),l(t?.reason)},u=setTimeout(()=>{c(),l(new Error(`connectVoice: the network candidates were not gathered in ${r} ms`))},r);e.addEventListener("icegatheringstatechange",o),t?.addEventListener("abort",s,{once:!0})})}function oe(e){if(typeof e=="string")try{let r=JSON.parse(e);return r.type!=="error"?void 0:typeof r.error?.message=="string"?r.error.message:typeof r.error?.code=="string"?r.error.code:"the voice failed"}catch{return}}function se(){let e=globalThis;if(typeof e.RTCPeerConnection!="function"||typeof e.navigator?.mediaDevices?.getUserMedia!="function")throw new TypeError("connectVoice: this runtime has no WebRTC (RTCPeerConnection, navigator.mediaDevices): a chat's voice is a browser's");let r=e.navigator.mediaDevices;return{RTCPeerConnection:e.RTCPeerConnection,getUserMedia:t=>r.getUserMedia(t)}}function ae(){let e=globalThis.document;if(!e)throw new TypeError("connectVoice: give audio \u2014 the element the voice plays in \u2014 where there is no document");let r=e.createElement("audio");return r.autoplay=!0,r}var i=e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0;function ie(e,r,t){let f=i(i(i(e)?.components)?.schemas)??{},l=(d,n)=>{let p=new Set,h=(C,g,y)=>{let a=i(C);if(!a)return;if(typeof a.$ref=="string"){if(y.has(a.$ref)||!a.$ref.startsWith("#/components/schemas/"))return;h(f[a.$ref.slice(21)],g,new Set(y).add(a.$ref));return}if(a[E]===!0){p.add(g);return}for(let b of["anyOf","oneOf","allOf"]){let k=a[b];if(Array.isArray(k))for(let I of k)h(I,g,y)}let P=i(a.properties);if(P)for(let[b,k]of Object.entries(P))h(k,`${g}/${v(b)}`,y);i(a.items)&&h(a.items,`${g}/*`,y);for(let b of["additionalProperties","patternProperties","prefixItems"])if(a[b]!==void 0&&w(a[b],new Set(y)))throw new Error(`${t}: an encrypted field is a named property \u2014 not every key of a record, nor a tuple's place`)},w=(C,g)=>{if(Array.isArray(C))return C.some(a=>w(a,g));let y=i(C);return y?y[E]===!0?!0:typeof y.$ref=="string"&&!g.has(y.$ref)&&y.$ref.startsWith("#/components/schemas/")?(g.add(y.$ref),w(f[y.$ref.slice(21)],g)):Object.values(y).some(a=>typeof a=="object"&&a!==null&&w(a,g)):!1};return h(d,n,new Set),[...p]},c=d=>i(i(i(d)?.["application/json"])?.schema),o=[];o.push(...l(c(i(r.requestBody)?.content),"/body"));for(let d of Array.isArray(r.parameters)?r.parameters:[]){let n=i(d);if(!n)continue;let p=l(n.schema,`/query/${v(String(n.name))}`);if(p.length!==0){if(n.in!=="query")throw new Error(`${t}: ${String(n.in)} parameter ${String(n.name)} is marked encrypted \u2014 a body's or a query's field is`);if(p.some(h=>h.split("/").length!==3))throw new Error(`${t}: an encrypted query field is one of the query's own names`);o.push(...p)}}let s=i(r.responses)??{},u=Object.keys(s).filter(d=>/^2\d\d$/.test(d)).sort((d,n)=>d==="200"?-1:n==="200"?1:d.localeCompare(n)),m=u.length>0?l(c(i(s[u[0]])?.content),"/response"):[];if(o.length+m.length!==0){if(r["x-palbase-sse"]!==void 0&&m.length>0)throw new Error(`${t}: a streamed answer carries no encrypted field`);if(r["x-palbase-upload"]!==void 0)throw new Error(`${t}: an upload goes through storage, which seals nothing \u2014 it carries no encrypted field`);return{request:o,response:m}}}async function ce(e){let r=`${e.method.toUpperCase()} ${e.path}`,t=i(i(i(i(e.contract)?.paths)?.[e.path])?.[e.method.toLowerCase()]),f=t?ie(e.contract,t,r):void 0;if(!f)return{body:e.body,query:e.query,open:async s=>s};let{key:l,header:c}=await A(e.key.kid,x(e.key.publicKey),O(e.projectId,e.method,e.path,e.params??[])),o=(s,u)=>s==null?s:S(s,u,f.request,(m,d)=>R(l,m,d));return{header:c,body:await o(e.body,"/body"),query:await o(e.query,"/query"),open:s=>s===void 0?Promise.resolve(s):S(s,"/response",f.response,async(u,m)=>{if(!$(m))throw new T("unopenable",`${r}: ${u} came plain where the contract says it is encrypted`);return V(l,u,m)})}}export{D as Analytics,_ as BackendError,G as Channel,H as Consent,Z as Flags,z as GatewayError,F as InApp,J as Inbox,U as Installation,W as Notify,L as PalbaseError,X as Purchases,N as RealtimeSocket,B as SESSION_START,M as SessionChangedError,K as WebPush,ne as connectVoice,ee as createClient,ce as encryptedCall,Q as isBackendError,q as localStore,j as memoryStore,Y as redemptionToken};
|
package/dist/web/message.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{a as i}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as i}from"../chunks/JWLK6SLN.js";import{a as e,b as s,c as t,d as p,e as o,f as a,h as r,j as n,k as y,p as M,q as l,t as g}from"../chunks/NRWY25JZ.js";import"../chunks/22JG5QKQ.js";export{n as MESSAGE_COMPONENTS,a as MESSAGE_ICONS,r as MESSAGE_SCHEMA,s as assetId,y as countdownValues,e as fontFamily,o as htmlDocument,t as prepareAssets,i as presentMessage,g as renderMessage,M as resolveMessage,l as resolveMessageWithPaths,p as unzip};
|
package/dist/web/palbe.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{c as e,d as r,i as t}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{c as e,d as r,i as t}from"../chunks/ZT4AKS6D.js";import"../chunks/B33QXIR5.js";import"../chunks/2DBSGJ7Z.js";import"../chunks/ZOF56QTG.js";import"../chunks/7ZSVOQFN.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
|
package/dist/web/paywall.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{a as f,b as d,c as m,d as u,e as A,f as c,g as R}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as f,b as d,c as m,d as u,e as A,f as c,g as R}from"../chunks/QCZJK4GZ.js";import{a as e,b as a,c as t,d as l,e as r,f as o,g as p,i as y,k as s,l as P,n,o as i,s as w}from"../chunks/NRWY25JZ.js";import"../chunks/7ZSVOQFN.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";export{y as PAYWALL_COMPONENTS,o as PAYWALL_ICONS,p as PAYWALL_SCHEMA,c as Paywall,a as assetId,f as attributesHeader,s as countdownValues,R as defaultPaywall,e as fontFamily,u as formatPeriod,m as formatPrice,r as htmlDocument,A as packageValues,P as packagesOf,d as parseDuration,t as prepareAssets,w as renderPaywall,n as resolvePaywall,i as resolvePaywallWithPaths,l as unzip};
|
package/dist/web/push-sw.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
2
|
"use strict";(()=>{function f(e,s){if(e)try{let i=new URL(e,s);if(i.protocol==="https:"||i.protocol==="http:"&&(i.hostname==="localhost"||i.hostname==="127.0.0.1"))return i.href}catch{}}function g(e){let s=new URL(e.location.href).searchParams,i=s.get("url")??"",l=s.get("key")??"",r=(n,t)=>!n||!i?Promise.resolve():e.fetch(`${i.replace(/\/$/,"")}/notify/receipts`,{method:"POST",headers:{"content-type":"application/json",apikey:l},body:JSON.stringify({receipts:[{receipt:n,status:t}]}),keepalive:!0}).catch(()=>{}),a=async(n,t)=>{for(let o of await e.clients.matchAll({type:"window",includeUncontrolled:!0}))o.postMessage({type:"palbase.push",event:n,url:t.url,data:t.data})};e.addEventListener("push",(n=>{let t={};try{t=n.data?.json()??{}}catch{}let o={url:t.url,receipt:t.receipt,data:t.data};n.waitUntil(e.registration.showNotification(t.title??"",{body:t.body,image:t.image,tag:t.tag,data:o}).then(()=>Promise.all([r(t.receipt,"delivered"),a("received",o)])))})),e.addEventListener("notificationclick",(n=>{n.notification.close();let t=n.notification.data??{},o=f(t.url,e.location.origin),c=async()=>{if(!o)return;let d=(await e.clients.matchAll({type:"window",includeUncontrolled:!0})).find(u=>u.url===o);d?await d.focus():await e.clients.openWindow(o)};n.waitUntil(Promise.all([r(t.receipt,"opened"),c(),a("opened",t)]))})),e.addEventListener("notificationclose",(n=>{n.waitUntil(r(n.notification.data?.receipt,"dismissed"))}))}typeof self<"u"&&typeof self.registration=="object"&&!("document"in self)&&g(self);})();
|
package/dist/web/ssr.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import{q as f}from"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{q as f}from"../chunks/LDZ7OKNS.js";import"../chunks/ZT4AKS6D.js";import"../chunks/QCZJK4GZ.js";import"../chunks/JWLK6SLN.js";import"../chunks/NRWY25JZ.js";import"../chunks/B33QXIR5.js";import"../chunks/2DBSGJ7Z.js";import"../chunks/WAMYRYDY.js";import"../chunks/ZOF56QTG.js";import"../chunks/7ZSVOQFN.js";import"../chunks/DLQT5KPC.js";import"../chunks/22JG5QKQ.js";var C=Object.freeze({"Cache-Control":"private, no-cache, no-store, must-revalidate, max-age=0",Expires:"0",Pragma:"no-cache"}),x={path:"/",sameSite:"lax",secure:!0,httpOnly:!1,maxAge:400*24*60*60},u=3180,k=5*6e4;function d(t){let e=/^pb_([a-z0-9]+)_c/.exec(t)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");return`pb-${e}-session`}var y=t=>{let e=new TextEncoder().encode(JSON.stringify(t)),o="";for(let s of e)o+=String.fromCharCode(s);return btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},b=t=>{try{let e=atob(t.replace(/-/g,"+").replace(/_/g,"/")),o=JSON.parse(new TextDecoder().decode(Uint8Array.from(e,s=>s.charCodeAt(0))));return typeof o.accessToken!="string"||typeof o.refreshToken!="string"||typeof o.expiresAt!="number"||typeof o.userId!="string"?null:o}catch{return null}};function m(t,e,o={},s=!1){let c={...x,...o},g=async()=>new Map((await e.getAll()).map(n=>[n.name,n.value])),S=n=>n===t||n.startsWith(`${t}.`)&&/^\d+$/.test(n.slice(t.length+1)),h=async n=>{if(!e.setAll)return;let i=n===null?[]:n.length<=u?[[t,n]]:Array.from({length:Math.ceil(n.length/u)},(r,l)=>[`${t}.${l}`,n.slice(l*u,(l+1)*u)]),p=new Set(i.map(([r])=>r)),a=i.map(([r,l])=>({name:r,value:l,options:c}));for(let r of(await g()).keys())S(r)&&!p.has(r)&&a.push({name:r,value:"",options:{...c,maxAge:0}});a.length>0&&await e.setAll(a,{...C})};return{async load(){let n=await g(),i=n.get(t);if(i===void 0){let p="";for(let a=0;n.has(`${t}.${a}`);a++)p+=n.get(`${t}.${a}`);i=p}return i?b(i):null},save:n=>h(y(n)),clear:()=>h(null),shared:s}}function A(t){let{cookies:e,cookieOptions:o,...s}=t,c=t.refresh??(e.setAll?"before":"never");return f({...s,refresh:c,storage:m(d(t.publishableKey),e,o)})}function O(){let t=()=>{let e=globalThis.document;if(!e)throw new Error("documentCookies: there is no document here \u2014 a server gives its request's cookies to createServerClient");return e};return{getAll:()=>t().cookie.split(";").map(e=>e.trim()).filter(e=>e.includes("=")).map(e=>{let o=e.indexOf("=");return{name:e.slice(0,o),value:e.slice(o+1)}}),setAll(e){for(let o of e){let s=o.options,c=[`Path=${s.path??"/"}`,s.domain?`Domain=${s.domain}`:"",s.maxAge!==void 0?`Max-Age=${s.maxAge}`:"",s.expires?`Expires=${s.expires.toUTCString()}`:"",s.sameSite?`SameSite=${s.sameSite.charAt(0).toUpperCase()}${s.sameSite.slice(1)}`:"",s.secure?"Secure":""].filter(Boolean);t().cookie=[`${o.name}=${o.value}`,...c].join("; ")}}}}function $(t){let{cookieOptions:e,...o}=t,s=globalThis.location?.protocol==="https:";return f({...o,storage:m(d(t.publishableKey),O(),{secure:s,...e},!0)})}async function v(t){let e=await t.auth.currentSession();if(!e||(e.expiresAt-Date.now()<=k&&await t.auth.refreshSession().catch(()=>{}),!await t.auth.currentSession()))return null;try{return(await t.auth.api.verifyTokenUser()).data}catch(o){if(o.status===401)return null;throw o}}export{C as NO_STORE_HEADERS,x as SESSION_COOKIE_OPTIONS,m as cookieSessionStore,$ as createBrowserClient,A as createServerClient,O as documentCookies,v as keepSession,d as sessionCookieName};
|
package/dist/web/vite.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! palbase 0.13.
|
|
2
|
-
import"../chunks/
|
|
1
|
+
/*! palbase 0.13.2 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import"../chunks/22JG5QKQ.js";import{execFile as $}from"node:child_process";import{existsSync as y,mkdtempSync as k,readFileSync as S,rmSync as x,writeFileSync as P}from"node:fs";import{createRequire as O}from"node:module";import{tmpdir as W}from"node:os";import{dirname as g,join as o,relative as u,resolve as v,sep as d}from"node:path";var E=/\.(?:ts|js|mts|mjs)$/;function F(n){if(!/^[a-z][a-z0-9-]*$/.test(n.app))throw new TypeError(`palbase({ app }): ${JSON.stringify(n.app)} is an app's slug (palbase apps:list)`);let c=process.cwd(),p="",i="",f=()=>v(c,n.dir??"palbase"),m=()=>{let e=n.environments[p];if(!e)throw new Error(`palbase: the mode "${p}" is not built against any environment \u2014 say which in vite.config: palbase({ environments: { ${JSON.stringify(p)}: '<environment slug>' } })`);return e};return{name:"palbase",enforce:"pre",config(e,s){p=s.mode,i=s.command??"";let r=e.build?.rollupOptions?.onwarn;return{build:{rollupOptions:{onwarn(t,a){let l=String(t.exporter??t.id??"");if(t.code==="MISSING_EXPORT"&&l.includes(`${d}environments${d}`))throw new Error(`palbase: ${t.message} \u2014 ${m()}'s backend has no such route (palbase apps:sync brings what it has)`);r?r(t,a):a(t)}}}}},configResolved(e){c=e.root,p=e.mode,i=e.command??i},async buildStart(){i!=="build"||n.typecheck===!1||await j(c,m(),n.tsconfig)},resolveId(e,s){if(!s)return null;let r=f();if(e==="palbase"||e.startsWith("palbase/")){let w=u(r,s);return w.startsWith("..")||w===""?null:this.resolve(e,o(c,"index.html"),{skipSelf:!0})}if(!(e.startsWith(".")||e.startsWith("/")))return null;let t=v(g(s),e);if(E.test(t)||(t+=".ts"),g(t)!==r&&g(t)!==o(r,"palbe"))return null;let a=u(r,t),l=`${n.app}.ts`;if(a!==l&&!a.startsWith(`palbe${d}`))return null;let h=m(),b=o(r,"environments",h,a===l?l:o("palbe",a.slice(`palbe${d}`.length)));if(!y(b))throw new Error(`palbase: ${u(c,b)} is not there \u2014 palbase apps:sync writes it (is ${n.app} set in ${h}, and has ${h} that machine?)`);return b}}}async function j(n,c,p){let i=p?v(n,p):["tsconfig.app.json","tsconfig.json"].map(e=>o(n,e)).find(y);if(!i)return;if(!y(i))throw new Error(`palbase({ tsconfig }): ${u(n,i)} is not there`);let f;try{let e=O(o(n,"package.json")).resolve("typescript/package.json"),s=JSON.parse(S(e,"utf8")).bin?.tsc;if(!s)throw new Error("no tsc");f=o(g(e),s)}catch{throw new Error("palbase: the build type-checks the app against its environment with the app's TypeScript, and the app has none (npm i -D typescript) \u2014 or say palbase({ typecheck: false })")}let m=k(o(W(),"palbase-typecheck-"));try{let e=o(m,"tsconfig.json");P(e,JSON.stringify({extends:i,compilerOptions:{noEmit:!0,composite:!1,incremental:!1,moduleSuffixes:[`.${c}`,""]}}));let s=await new Promise(r=>$(process.execPath,[f,"-p",e,"--pretty","false"],{cwd:n,maxBuffer:16<<20},(t,a,l)=>r({code:t?typeof t.code=="number"?t.code:1:0,text:`${a}${l}`.trim()})));if(s.code!==0)throw new Error(`palbase: the app does not type-check against ${c}, the environment this build is made for \u2014 a route its backend does not have, or a call that does not fit it:
|
|
3
3
|
${s.text}`)}finally{x(m,{recursive:!0,force:!0})}}export{F as palbase};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "palbase",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "Palbase for JavaScript: the web client (palbase/web), the server SDK (palbase/server), the backend framework (palbase/backend), AI (palbase/ai) and the CLI (npx palbase).",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://palbase.studio",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"dependencies": {
|
|
136
136
|
"@types/node": "26.6.4",
|
|
137
137
|
"bun-types": "1.4.2",
|
|
138
|
-
"palgres": "0.13.
|
|
138
|
+
"palgres": "0.13.2",
|
|
139
139
|
"reflect-metadata": "^0.2.2",
|
|
140
140
|
"typescript": "~6.0.3",
|
|
141
141
|
"zod": "^4.6.5"
|