palbase 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +2 -2
- package/dist/ai/index.js +17 -0
- package/dist/backend/engine.js +2 -0
- package/dist/backend/env.js +1 -0
- package/dist/backend/index.js +12 -0
- package/dist/backend/stack.js +1 -0
- package/dist/backend/test.js +2 -0
- package/dist/chunks/5W6XJM46.js +13 -0
- package/dist/chunks/6OPBXB7Z.js +2 -0
- package/dist/chunks/7LOMYBLN.js +20 -0
- package/dist/chunks/AN5LCF5K.js +55 -0
- package/dist/chunks/ECUYQ73P.js +2 -0
- package/dist/chunks/HDX6YUAB.js +2 -0
- package/dist/chunks/HVC2C35F.js +2 -0
- package/dist/chunks/I3JNX6MZ.js +4 -0
- package/dist/chunks/JEJ5CFTK.js +2 -0
- package/dist/chunks/K3C2IEDS.js +2 -0
- package/dist/chunks/KRBVYYME.js +2 -0
- package/dist/chunks/NIJHTHNF.js +2 -0
- package/dist/chunks/TL4H6V3P.js +2 -0
- package/dist/chunks/UTRQWCMD.js +6 -0
- package/dist/chunks/ZFPDYRRY.js +2 -0
- package/dist/cli.js +815 -0
- package/dist/refuse/ai.js +2 -0
- package/dist/refuse/backend.js +2 -0
- package/dist/refuse/server.js +2 -0
- package/dist/server/index.js +2 -0
- package/dist/server/testing.js +2 -0
- package/dist/web/index.js +2 -0
- package/dist/web/palbe.js +2 -0
- package/dist/web/paywall.js +2 -0
- package/dist/web/vite.js +3 -0
- package/package.json +111 -4
- package/types/ai/src/ai.d.ts +178 -0
- package/types/ai/src/index.d.ts +5 -0
- package/types/ai/src/partial.d.ts +1 -0
- package/types/ai/src/schema.d.ts +47 -0
- package/types/backend/src/bootstrap.d.ts +72 -0
- package/types/backend/src/cache.d.ts +32 -0
- package/types/backend/src/container.d.ts +49 -0
- package/types/backend/src/database.d.ts +148 -0
- package/types/backend/src/db-env.d.ts +4 -0
- package/types/backend/src/decorators.d.ts +293 -0
- package/types/backend/src/engine-db.d.ts +24 -0
- package/types/backend/src/engine-exports.d.ts +3 -0
- package/types/backend/src/engine.d.ts +124 -0
- package/types/backend/src/env.d.ts +27 -0
- package/types/backend/src/errors.d.ts +70 -0
- package/types/backend/src/i18n.d.ts +21 -0
- package/types/backend/src/index.d.ts +23 -0
- package/types/backend/src/openapi.d.ts +73 -0
- package/types/backend/src/platform-calls.d.ts +41 -0
- package/types/backend/src/requests.d.ts +81 -0
- package/types/backend/src/rooms.d.ts +168 -0
- package/types/backend/src/router.d.ts +22 -0
- package/types/backend/src/runtime.d.ts +56 -0
- package/types/backend/src/services.d.ts +262 -0
- package/types/backend/src/stack.d.ts +20 -0
- package/types/backend/src/strings-files.d.ts +3 -0
- package/types/backend/src/testing/index.d.ts +3 -0
- package/types/backend/src/testing/unit.d.ts +66 -0
- package/types/backend/src/upload.d.ts +125 -0
- package/types/backend/src/webhooks.d.ts +113 -0
- package/types/internal/src/event.d.ts +9 -0
- package/types/internal/src/modules/ai.d.ts +678 -0
- package/types/internal/src/modules/analytics.d.ts +1414 -0
- package/types/internal/src/modules/auth.d.ts +5660 -0
- package/types/internal/src/modules/cache.d.ts +158 -0
- package/types/internal/src/modules/events.d.ts +19 -0
- package/types/internal/src/modules/flags.d.ts +957 -0
- package/types/internal/src/modules/index.d.ts +13 -0
- package/types/internal/src/modules/machines.d.ts +1584 -0
- package/types/internal/src/modules/notify.d.ts +1450 -0
- package/types/internal/src/modules/purchases.d.ts +4113 -0
- package/types/internal/src/modules/realtime.d.ts +326 -0
- package/types/internal/src/modules/secrets.d.ts +275 -0
- package/types/internal/src/modules/storage.d.ts +691 -0
- package/types/internal/src/modules/stores.d.ts +1516 -0
- package/types/internal/src/retry.d.ts +14 -0
- package/types/internal/src/transport.d.ts +106 -0
- package/types/server/src/auth/dpop.d.ts +47 -0
- package/types/server/src/auth/jwt.d.ts +115 -0
- package/types/server/src/index.d.ts +9 -0
- package/types/server/src/pages.d.ts +4 -0
- package/types/server/src/purchases.d.ts +51 -0
- package/types/server/src/secrets-env.d.ts +22 -0
- package/types/server/src/server.d.ts +40 -0
- package/types/server/src/testing.d.ts +91 -0
- package/types/server/src/webhooks.d.ts +72 -0
- package/types/web/src/analytics.d.ts +87 -0
- package/types/web/src/auth.d.ts +155 -0
- package/types/web/src/backend-error.d.ts +38 -0
- package/types/web/src/backend-names.d.ts +25 -0
- package/types/web/src/backends.d.ts +84 -0
- package/types/web/src/client.d.ts +51 -0
- package/types/web/src/index.d.ts +13 -0
- package/types/web/src/palbe.d.ts +2 -0
- package/types/web/src/paywall/icons.d.ts +5 -0
- package/types/web/src/paywall/index.d.ts +5 -0
- package/types/web/src/paywall/placement.d.ts +85 -0
- package/types/web/src/paywall/prices.d.ts +40 -0
- package/types/web/src/paywall/render.d.ts +54 -0
- package/types/web/src/paywall/resolve.d.ts +149 -0
- package/types/web/src/purchases.d.ts +86 -0
- package/types/web/src/rooms.d.ts +61 -0
- package/types/web/src/session.d.ts +91 -0
- package/types/web/src/socket.d.ts +87 -0
- package/types/web/src/vite.d.ts +49 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! palbase 0.2.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as c,b as d,c as e,d as f,e as g,f as h,g as i,h as j,i as k,j as l,k as m,l as n,m as o,n as p,o as q,p as r,q as s,r as t}from"../chunks/ZFPDYRRY.js";import"../chunks/KRBVYYME.js";import{m as b}from"../chunks/HVC2C35F.js";import"../chunks/JEJ5CFTK.js";import{b as a}from"../chunks/ECUYQ73P.js";import"../chunks/HDX6YUAB.js";import"../chunks/TL4H6V3P.js";export{j as AuthUnavailable,b as EVENT_TYPES,a as PalbaseError,o as ReservationSettled,i as TokenError,l as TokenVerifier,d as WebhookSignatureError,c as createServer,n as isEntitled,t as loadSecrets,q as pages,s as platformOwn,r as processOwn,m as requestAddress,k as sessionStanding,g as signatureHeader,f as verifySignature,e as verifyWebhook,h as verifyWebhookRequest,p as withReservation};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! palbase 0.2.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as Z,b as ee,e as te,f as F,g as B}from"../chunks/5W6XJM46.js";import{o as $}from"../chunks/AN5LCF5K.js";import{b as M,c as y,h as D}from"../chunks/HVC2C35F.js";import{a as q,b as P}from"../chunks/JEJ5CFTK.js";import{b as S,d as k}from"../chunks/ECUYQ73P.js";import"../chunks/HDX6YUAB.js";import"../chunks/TL4H6V3P.js";var T=class{api;open;session;credentials;mfa;passkey;magicLink;phone;password;email;sessions;constructor(e,t,s,i){this.api=y.client(e),this.open=y.client(t),this.session=s,this.credentials=i;let r=this.api,a=this.open;this.mfa={challenge:async(o,c,l)=>this.signedIn((await a.mfaChallenge({body:{mfa_token:o,type:c,code:l}})).data),recovery:async(o,c)=>this.signedIn((await a.mfaRecovery({body:{mfa_token:o,code:c}})).data),sendSmsCode:async o=>{await a.mfaSmsChallenge({body:{mfa_token:o}})},sendEmailCode:async o=>{await a.mfaEmailChallenge({body:{mfa_token:o}})},enrollTotp:async()=>{let o=(await r.mfaEnroll({body:{type:"totp"}})).data;return{enrollmentId:o.enrollment_id,secret:o.secret,otpUrl:o.otp_url,qrCode:o.qr_code,recoveryCodes:o.recovery_codes}},verifyTotp:async o=>{await r.mfaVerifyEnrollment({body:{code:o}})},enrollSms:async o=>(await r.mfaSmsEnroll({body:{phone:o}})).data,verifySms:async o=>{await r.mfaSmsVerifyEnrollment({body:{code:o}})},enrollEmail:async()=>{await r.mfaEmailEnroll()},factors:async()=>(await r.mfaListFactors()).data,removeFactor:async(o,c)=>{await r.mfaRemoveFactor({path:{id:o},body:{current_password:c}})},regenerateRecoveryCodes:async()=>(await r.mfaRegenerateRecoveryCodes()).data},this.passkey={register:async o=>{let c=(await r.webauthnRegisterBegin({body:{name:o}})).data,l=await this.authenticator().create({publicKey:H(c.options.publicKey)});return(await r.webauthnRegisterFinish({body:J(l)})).data},signIn:async(o={})=>{let c=(await a.webauthnLoginBegin({body:o.userId?{user_id:o.userId}:{}})).data,l=await this.authenticator().get({publicKey:G(c.options.publicKey)}),u=await a.webauthnLoginFinish({query:o.userId?{user_id:o.userId}:void 0,body:W(l)});return this.signedIn(u.data)},signUp:async(o,c)=>{let l=(await a.webauthnSignupBegin({body:{identifier:o,user_name:c}})).data,u=await this.authenticator().create({publicKey:H(l.options.publicKey)});await a.webauthnSignupFinish({query:{user_id:l.user_id},body:J(u)});let d=(await a.webauthnLoginBegin({body:{user_id:l.user_id}})).data,w=await this.authenticator().get({publicKey:G(d.options.publicKey)});return this.signedIn((await a.webauthnLoginFinish({query:{user_id:l.user_id},body:W(w)})).data)},list:async()=>(await r.webauthnListCredentials()).data,remove:async o=>{await r.webauthnDeleteCredential({path:{id:o}})}},this.magicLink={send:async o=>{await a.magicLinkRequest({body:{email:o}})},verify:async o=>this.signedIn((await a.magicLinkVerify({body:{token:o}})).data)},this.phone={sendCode:async o=>(await a.requestPhoneOtp({body:{phone:o,channel:"sms"}})).data,verifyCode:async(o,c)=>this.signInResult((await a.verifyPhoneOtp({body:{phone:o,token:c}})).data)},this.password={requestReset:async o=>{await a.passwordResetRequest({body:{email:o}})},confirmReset:async(o,c)=>{await a.passwordResetConfirm({body:{token:o,new_password:c}})},change:async o=>(await r.passwordChange({body:o})).data,set:async o=>(await r.setPassword({body:o})).data},this.email={verify:async o=>{await a.verifyEmail({body:o})},resendVerification:async o=>(await a.resendVerification({body:{email:o}})).data},this.sessions={list:async()=>(await r.listSessions()).data,revoke:async o=>{await r.revokeSession({path:{id:o}})},revokeAll:async()=>{await r.revokeAllSessions()}}}onAuthStateChange(e){return this.session.onChange(e)}currentSession(){return this.session.session()}async signUp(e){let t=(await this.open.signup({body:e})).data;return t.access_token&&t.refresh_token&&t.expires_in!==void 0&&await this.session.set({access_token:t.access_token,refresh_token:t.refresh_token,expires_in:t.expires_in},"SIGNED_IN",t.user),t}async signIn(e,t){return this.signInResult((await this.open.login({body:{email:e,password:t}})).data)}async signOut(){try{await this.session.session()&&await this.api.logout()}finally{await this.session.clear("SIGNED_OUT")}}async getUser(){let e=this.session.snapshot(),t=(await this.api.getMe()).data;return await this.session.setUser(t,e),t}async refreshSession(){return this.session.refresh()}async deleteAccount(e){await this.api.deleteAccount(e===void 0?void 0:{body:{password:e}}),await this.session.clear("SIGNED_OUT")}async signInResult(e){return"mfa_required"in e&&e.mfa_required?{mfaRequired:{mfaToken:e.mfa_token,factors:e.factors}}:{user:await this.signedIn(e)}}async setSession(e){return this.signedIn(e)}async signedIn(e){let t=await this.session.set({access_token:e.access_token,refresh_token:e.refresh_token,expires_in:e.expires_in},"SIGNED_IN",e.user);if(e.user)return e.user;let s=(await this.api.verifyTokenUser()).data;return await this.session.setUser(s,t),s}authenticator(){if(!this.credentials)throw new Error("passkeys need navigator.credentials (or createClient({ webauthn }))");return this.credentials}},R=n=>{let e=atob(n.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(n.length/4)*4,"=")),t=new Uint8Array(e.length);for(let s=0;s<e.length;s++)t[s]=e.charCodeAt(s);return t.buffer},f=n=>{if(!n)return;let e=n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength),t="";for(let s of e)t+=String.fromCharCode(s);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")},V=n=>Array.isArray(n)?n.map(e=>({...e,id:R(String(e.id))})):void 0;function H(n){let e=n.user;return{...n,challenge:R(String(n.challenge)),user:{...e,id:R(String(e.id))},excludeCredentials:V(n.excludeCredentials)}}function G(n){return{...n,challenge:R(String(n.challenge)),allowCredentials:V(n.allowCredentials)}}function J(n){let e=n,t=e.response;return{id:e.id,rawId:f(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:f(t.clientDataJSON),attestationObject:f(t.attestationObject),transports:t.getTransports?.()}}}function W(n){let e=n,t=e.response;return{id:e.id,rawId:f(e.rawId),type:"public-key",authenticatorAttachment:e.authenticatorAttachment??void 0,clientExtensionResults:e.getClientExtensionResults?.()??{},response:{clientDataJSON:f(t.clientDataJSON),authenticatorData:f(t.authenticatorData),signature:f(t.signature),userHandle:f(t.userHandle)}}}var p=class extends Error{code="session_changed";constructor(e){super(e),this.name="SessionChangedError"}};function N(){let n=null;return{load:()=>n,save:e=>{n=e},clear:()=>{n=null},shared:!1}}function L(n){let e=null,t=!0,s=()=>{try{return globalThis.localStorage}catch{return}};return{shared:!0,load(){try{let i=s()?.getItem(n);return i==null?t?null:e:JSON.parse(i)}catch{return e}},save(i){e=i;try{let r=s();if(!r)throw new Error("no storage");r.setItem(n,JSON.stringify(i)),t=!0}catch{t=!1}},clear(){e=null,t=!0;try{s()?.removeItem(n)}catch{}},watch(i){let r=globalThis;if(typeof r.addEventListener!="function")return()=>{};let a=o=>{(o.key===n||o.key===null)&&i()};return r.addEventListener("storage",a),()=>r.removeEventListener?.("storage",a)}}}function se(n){try{let e=n.split(".")[1]??"",t=atob(e.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(e.length/4)*4,"=")),s=JSON.parse(t).sub;return typeof s=="string"?s:""}catch{return""}}var ne=6e4,ie=15e3;function re(n,e,t){let s=n?globalThis.navigator?.locks:void 0;return s?s.request(e,t):t()}var E=class{current=null;loaded;inflight=null;listeners=new Set;store;refresher;isRejected;now;lockName;refreshTimeoutMs;constructor(e,t,s,i={}){this.store=e,this.refresher=t,this.isRejected=s,this.now=i.now??Date.now,this.lockName=i.lockName??"palbase.session.refresh",this.refreshTimeoutMs=i.refreshTimeoutMs??ie,this.loaded=Promise.resolve(e.load()).then(r=>{this.current=r}),e.watch?.(()=>{this.reconcile()})}async session(){return await this.loaded,this.current}snapshot(){return this.current}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async set(e,t,s){await this.loaded;let i=t==="TOKEN_REFRESHED"?this.current:null,r={accessToken:e.access_token,refreshToken:e.refresh_token,expiresAt:this.now()+e.expires_in*1e3,userId:s?.id??i?.userId??se(e.access_token),user:s??i?.user};return this.current=r,await this.store.save(r),this.emit(t,r),r}async setUser(e,t){await this.loaded,!(!this.current||!t||this.current.userId!==t.userId)&&(this.current={...this.current,user:e},await this.store.save(this.current),this.emit("USER_UPDATED",this.current))}async clear(e){await this.loaded;let t=this.current;this.current=null,this.inflight=null;let s=await this.store.load();(!s||!t||s.userId===t.userId)&&await this.store.clear(),t&&this.emit(e,null)}async accessToken(){await this.loaded;let e=this.current;if(!e)return;let t=e.expiresAt-this.now();return t>ne?e.accessToken:t>0?(this.refresh().catch(()=>{}),e.accessToken):(await this.refresh()).accessToken}refresh(){if(this.inflight)return this.inflight;let e=re(this.store.shared===!0,this.lockName,async()=>{await this.loaded;let t=this.current;if(!t)throw new p("no session to refresh");let s=await this.adoptStored(t);if(s)return s;try{let i=await this.withTimeout(this.refresher(t.refreshToken));if(this.current?.refreshToken!==t.refreshToken)throw new p("the session changed while it was refreshed");return await this.set(i,"TOKEN_REFRESHED")}catch(i){throw this.isRejected(i)&&this.current?.refreshToken===t.refreshToken&&await this.clear("SESSION_EXPIRED"),i}});return this.inflight=e,e.finally(()=>{this.inflight===e&&(this.inflight=null)}).catch(()=>{}),e}async adoptStored(e){let t=await this.store.load();if(!t)throw this.current=null,this.emit("SIGNED_OUT",null),new p("signed out in another tab");if(t.userId!==e.userId)throw this.current=t,this.emit("SIGNED_OUT",null),this.emit("SIGNED_IN",t),new p("another user signed in in another tab");if(t.refreshToken!==e.refreshToken&&t.expiresAt>=e.expiresAt)return this.current=t,this.emit("TOKEN_REFRESHED",t),t}async reconcile(){await this.loaded;let e=this.current,t=await this.store.load();if(!e){t&&(this.current=t,this.emit("SIGNED_IN",t));return}await this.adoptStored(e).catch(()=>{})}withTimeout(e){let t,s=new Promise((i,r)=>{t=setTimeout(()=>r(new Error(`the refresh did not answer within ${this.refreshTimeoutMs/1e3} s`)),this.refreshTimeoutMs)});return Promise.race([e,s]).finally(()=>clearTimeout(t))}emit(e,t){for(let s of this.listeners)try{s(e,t)}catch{}}};var _=class{state="closed";refusal;joinRef=null;listeners=new Map;closers=new Set;joinWaiters=[];name;socket;constructor(e,t){this.name=e,this.socket=t}get topic(){return`realtime:${this.name}`}join(){if(this.state==="joined")return Promise.resolve();let e=new Promise((t,s)=>this.joinWaiters.push({resolve:t,reject:s}));return this.state!=="joining"&&this.socket.join(this),e}leave(){this.socket.leave(this)}push(e,t){return this.socket.request(this,e,t)}on(e,t){let s=this.listeners.get(e);return s||this.listeners.set(e,s=new Set),s.add(t),()=>s.delete(t)}onClosed(e){return this.closers.add(e),()=>this.closers.delete(e)}deliver(e,t){for(let s of this.listeners.get(e)??[])try{s(t)}catch{}}settled(e,t){this.state=e?"joined":"refused",this.refusal=e?void 0:t;let s=this.joinWaiters.splice(0);for(let i of s)e?i.resolve():i.reject(new Error(`join ${this.name} refused: ${JSON.stringify(t)}`))}closed(e){this.state="closed",this.joinRef=null;let t=this.joinWaiters.splice(0);for(let s of t)s.reject(new Error(`join ${this.name}: ${e}`));for(let s of[...this.closers])try{s()}catch{}}},m=class{ws=null;opening=null;ref=0;channels=new Map;replies=new Map;heartbeat=null;heartbeatRef=null;reconnectTimer=null;attempts=0;closedByUs=!1;reconnects=0;opts;constructor(e){this.opts=e}channel(e){let t=this.channels.get(e);return t||this.channels.set(e,t=new _(e,this)),t}disconnect(){this.closedByUs=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.stopHeartbeat();let e=this.ws;this.ws=null,this.opening=null,e?.close(1e3);for(let[,t]of this.replies)t("error",{reason:"socket closed"});this.replies.clear();for(let t of this.channels.values())t.closed("the socket was closed")}async tokenChanged(){if(!this.ws||this.ws.readyState!==1)return;let e=await this.opts.accessToken();if(e)for(let t of this.channels.values())t.state==="joined"&&this.push(t.joinRef,t.topic,"access_token",{access_token:e})}join(e){e.state="joining",this.open().then(()=>this.sendJoin(e)).catch(t=>e.settled(!1,{reason:t instanceof Error?t.message:String(t)}))}leave(e){e.state==="joined"&&this.ws?.readyState===1&&this.push(e.joinRef,e.topic,"phx_leave",{}),e.state="closed",this.channels.delete(e.name)}async request(e,t,s){let i=this.ws;if(this.channels.get(e.name)!==e||e.state!=="joined"||i?.readyState!==1)return{status:"error",response:{reason:"not joined"}};let r=this.nextRef(),a=JSON.stringify([e.joinRef,r,e.topic,t,s]),o=this.awaitReply(r);return i.send(a),o}open(){if(this.ws?.readyState===1)return Promise.resolve();if(this.opening)return this.opening;this.closedByUs=!1;let e=this.opts.webSocket??globalThis.WebSocket,t=`${this.opts.baseUrl.replace(/^http/,"ws")}/realtime/v1/websocket?vsn=2.0.0&apikey=${encodeURIComponent(this.opts.publishableKey)}`,s=new Promise((i,r)=>{let a=new e(t);this.ws=a,a.onopen=()=>{this.attempts=0,this.startHeartbeat(),i()},a.onmessage=o=>this.receive(String(o.data)),a.onerror=()=>r(new Error("the realtime socket could not be opened")),a.onclose=()=>this.dropped(a)});return this.opening=s,s.finally(()=>{this.opening===s&&(this.opening=null)}).catch(()=>{}),s}dropped(e){if(this.ws!==e)return;this.ws=null,this.stopHeartbeat();for(let[,i]of this.replies)i("error",{reason:"socket closed"});this.replies.clear();for(let i of this.channels.values())i.state==="joined"&&(i.state="joining");if(this.closedByUs||![...this.channels.values()].some(i=>i.state==="joining"))return;let t=this.opts.backoff??[500,1e3,2e3,5e3,1e4,3e4],s=t[Math.min(this.attempts,t.length-1)]*(.8+Math.random()*.4);this.attempts++,this.reconnectTimer=I(setTimeout(()=>{this.reconnectTimer=null,this.reconnects++;let i=[...this.channels.values()].filter(r=>r.state==="joining");this.open().then(()=>Promise.all(i.map(r=>this.sendJoin(r)))).catch(()=>{})},s))}async sendJoin(e){let t=await this.opts.accessToken(),s=this.nextRef();e.joinRef=s;let i=this.awaitReply(s);this.push(s,e.topic,"phx_join",{access_token:t,config:{broadcast:{self:!1}}},s);let{status:r,response:a}=await i;if(this.channels.get(e.name)!==e||e.state!=="joining"){r==="ok"&&this.ws?.readyState===1&&this.push(s,e.topic,"phx_leave",{});return}e.settled(r==="ok",a)}awaitReply(e){return new Promise(t=>{let s=I(setTimeout(()=>{this.replies.delete(e),t({status:"timeout",response:{reason:"no reply"}})},this.opts.replyTimeoutMs??1e4));this.replies.set(e,(i,r)=>{clearTimeout(s),this.replies.delete(e),t({status:i,response:r})})})}receive(e){let t;try{t=JSON.parse(e)}catch{return}if(!Array.isArray(t)||t.length!==5||typeof t[2]!="string"||typeof t[3]!="string")return;let[,s,i,r,a]=t,o=typeof a=="object"&&a!==null?a:{};if(r==="phx_reply"&&typeof s=="string"){if(s===this.heartbeatRef){this.heartbeatRef=null;return}this.replies.get(s)?.(String(o.status),o.response??{});return}let c=[...this.channels.values()].find(l=>l.topic===i);if(c){if(r==="phx_close"){c.state="closed";return}if(r==="phx_error"){c.state="joining",I(setTimeout(()=>this.channels.get(c.name)===c&&c.state==="joining"&&this.ws?.readyState===1&&void this.sendJoin(c),1e3));return}c.deliver(r,o)}}push(e,t,s,i,r=this.nextRef()){this.ws?.send(JSON.stringify([e,r,t,s,i]))}nextRef(){return String(++this.ref)}startHeartbeat(){this.stopHeartbeat(),this.heartbeat=I(setInterval(()=>{if(this.heartbeatRef!==null){this.heartbeatRef=null,this.ws?.close(4e3);return}this.heartbeatRef=this.nextRef(),this.push(null,"phoenix","heartbeat",{},this.heartbeatRef)},this.opts.heartbeatMs??25e3))}stopHeartbeat(){this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null,this.heartbeatRef=null}};function I(n){return n.unref?.(),n}var ae=30*6e4,X=1e3,le=100,ce=60*1024,C=()=>globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;function x(){try{return globalThis.localStorage}catch{return}}var g=class{api;closingApi;flushMs;flushAt;now;anonKey;sessionKey;events=[];samples=[];timer;memoryAnon;memorySession;appVersion;stopAuto;session;identifyPending=!1;constructor(e,t,s,i={}){this.session=t,this.api=M.client(e),this.closingApi=M.client({send:r=>e.send({...r,keepalive:!0})}),this.flushMs=i.flushMs??5e3,this.flushAt=i.flushAt??20,this.now=i.now??Date.now,this.anonKey=`palbase.analytics.anonymous.${s}`,this.sessionKey=`palbase.analytics.session.${s}`,t.onChange(r=>{r==="SIGNED_IN"?(this.identifyPending=!0,this.soon()):r==="SIGNED_OUT"&&(this.identifyPending=!1,this.reset())})}capture(e,t){let s=this.now();this.hold({event:e,distinct_id:this.distinctId(),properties:t,timestamp:s,session_id:this.sessionId(s),...this.appVersion?{app_version:this.appVersion}:{}})}page(e={}){let t=globalThis.location,s=globalThis.document,i=e.url??(t?`${t.origin}${t.pathname}`:"");if(!i)return;let r=e.referrer??pe(s?.referrer);this.capture("$pageview",{...e.properties,url:i,...e.title??s?.title?{title:e.title??s?.title}:{},...r?{referrer:r}:{}})}async identify(e){this.identifyPending=!1;let t=this.session.snapshot()?.userId;t&&(await this.flush(),await this.sendIdentify(this.api,t,e))}async sendIdentify(e,t,s){try{await e.identify({body:{distinct_id:t,anonymous_id:this.anonymousId(),traits:s,timestamp:this.now(),sent_at:this.now()}})}catch{}}reset(){this.memoryAnon=void 0,this.memorySession=void 0;try{x()?.removeItem(this.anonKey),x()?.removeItem(this.sessionKey)}catch{}}async flush(e=!1){this.timer&&clearTimeout(this.timer),this.timer=void 0;let t=e?this.closingApi:this.api,s=this.now(),i=this.session.snapshot()?.userId;for(this.identifyPending&&i&&(this.identifyPending=!1,await this.sendIdentify(t,i));this.events.length>0;){let r=this.take(this.events,e);try{await t.batch({body:{events:r.map(a=>({...a,sent_at:s}))}})}catch{}}for(;this.samples.length>0;){let r=this.take(this.samples,e);try{await t.sendPerf({body:{items:r}})}catch{}}}start(e={}){this.stopAuto?.(),this.appVersion=e.appVersion;let t=globalThis;if(typeof t.addEventListener!="function"||typeof globalThis.document>"u")return()=>{};let s=[];e.pageViews!==!1&&s.push(this.watchPages(t)),e.webVitals!==!1&&s.push(de((a,o)=>this.sample("web_vital",a,o))),e.network!==!1&&s.push(this.watchFetch(t));let i=()=>{document.visibilityState==="hidden"&&this.flush(!0)},r=()=>{this.flush(!0)};return document.addEventListener("visibilitychange",i),t.addEventListener("pagehide",r),s.push(()=>{document.removeEventListener("visibilitychange",i),t.removeEventListener("pagehide",r)}),this.stopAuto=()=>{for(let a of s.splice(0))a();this.stopAuto=void 0},this.stopAuto}hold(e){this.events.length>=X&&this.events.shift(),this.events.push(e),this.soon()}sample(e,t,s,i={}){this.samples.length>=X&&this.samples.shift(),this.samples.push({row_id:C(),trace_type:e,name:t,value:Math.max(0,s),timestamp:this.now(),distinct_id:this.distinctId(),...i}),this.soon()}soon(){if(this.events.length+this.samples.length>=this.flushAt){this.flush();return}this.timer||(this.timer=setTimeout(()=>{this.flush()},this.flushMs),this.timer.unref?.())}take(e,t){let s=e.splice(0,le);if(!t)return s;for(;s.length>1&&JSON.stringify(s).length>ce;)e.unshift(s.pop());return s}distinctId(){return this.session.snapshot()?.userId??this.anonymousId()}anonymousId(){let e=x();try{let t=e?.getItem(this.anonKey);if(t)return t;let s=`anon_${C()}`;if(e?.setItem(this.anonKey,s),e?.getItem(this.anonKey)===s)return s}catch{}return this.memoryAnon??=`anon_${C()}`,this.memoryAnon}sessionId(e){let t=x(),s=this.memorySession;try{let r=t?.getItem(this.sessionKey);r&&(s=JSON.parse(r))}catch{}let i=s&&e-s.last<ae?{id:s.id,last:e}:{id:`ses_${C()}`,last:e};this.memorySession=i;try{t?.setItem(this.sessionKey,JSON.stringify(i))}catch{}return i.id}watchPages(e){let t="",s=()=>{let o=`${e.location.origin}${e.location.pathname}`;o!==t&&(t=o,setTimeout(()=>this.page({url:o}),0))},i=e.history,r=i.pushState.bind(i),a=i.replaceState.bind(i);return i.pushState=(...o)=>{r(...o),s()},i.replaceState=(...o)=>{a(...o),s()},e.addEventListener("popstate",s),s(),()=>{i.pushState=r,i.replaceState=a,e.removeEventListener("popstate",s)}}watchFetch(e){let t=e.fetch;if(typeof t!="function")return()=>{};let s=async(i,r)=>{let a=performance.now(),o=i instanceof Request?i:void 0,c=(r?.method??o?.method??"GET").toUpperCase(),l;try{l=new URL(o?.url??String(i),e.location.href)}catch{l=void 0}let u=!!l&&l.pathname.startsWith("/analytics/")||fe(r?.headers??o?.headers);try{let d=await t(i,r);return l&&!u&&this.sample("network",`${c} ${l.origin}${l.pathname}`,performance.now()-a,{attrs:{status:String(d.status)},...d.headers.get("x-request-id")?{request_id:d.headers.get("x-request-id")}:{}}),d}catch(d){throw l&&!u&&this.sample("network",`${c} ${l.origin}${l.pathname}`,performance.now()-a,{attrs:{status:"0"}}),d}};return e.fetch=s,()=>{e.fetch===s&&(e.fetch=t)}}},ue=n=>n.entryType==="layout-shift"&&"value"in n&&"hadRecentInput"in n,he=n=>n.entryType==="event"||n.entryType==="first-input";function A(n,e){if(!(typeof PerformanceObserver>"u"))try{let t=new PerformanceObserver(s=>e(s.getEntries()));return t.observe({type:n,buffered:!0}),t}catch{return}}function de(n){if(typeof document>"u"||typeof performance>"u"||typeof performance.getEntriesByType!="function")return()=>{};let e=0,t=0,s=0,i=[A("largest-contentful-paint",l=>{for(let u of l)e=Math.max(e,u.startTime)}),A("layout-shift",l=>{for(let u of l)ue(u)&&!u.hadRecentInput&&(t+=u.value)}),A("event",l=>{for(let u of l)he(u)&&(s=Math.max(s,u.duration))}),A("paint",l=>{for(let u of l)u.name==="first-contentful-paint"&&n("FCP",u.startTime)})],r=performance.getEntriesByType("navigation")[0];r&&r.responseStart>0&&n("TTFB",r.responseStart);let a=!1,o=()=>{a||(a=!0,e>0&&n("LCP",e),n("CLS",t),s>0&&n("INP",s))},c=()=>{document.visibilityState==="hidden"&&o()};return document.addEventListener("visibilitychange",c),()=>{o(),document.removeEventListener("visibilitychange",c);for(let l of i)l?.disconnect()}}function fe(n){if(!n)return!1;try{return new Headers(n).has("next-router-prefetch")}catch{return!1}}function pe(n){if(!n)return"";try{let e=new URL(n);return`${e.origin}${e.pathname}`}catch{return n.split(/[?#]/,1)[0]??""}}var v=class{api;session;socket;ref;listeners=new Set;watch;following;last;constructor(e,t,s,i){this.api=D.client(e),this.session=t,this.socket=s,this.ref=i}async me(){let e=this.session.snapshot()?.userId,t=(await this.api.getMyCustomerInfo()).data;return this.watch&&this.watch.userId===e&&this.offer(this.watch,t),t}async offerings(e="web"){return(await this.api.getOfferings({query:{channel:e}})).data}async paywall(e,t={}){return $(this.api,this.ref,e,s=>this.checkout(s),t.signal)}async checkout(e){let t={product:e.product,plan:e.plan,success_url:e.successUrl,cancel_url:e.cancelUrl};return(await this.api.createCheckout({body:t})).data.url}async portal(e){return(await this.api.createPortalSession({body:{return_url:e}})).data.url}async mergeGrant(){return(await this.api.createMergeGrant()).data}async merge(e){let t=this.session.snapshot()?.userId,s=(await this.api.mergeGuest({body:{grant:typeof e=="string"?e:e.grant}})).data;return this.watch&&this.watch.userId===t&&this.offer(this.watch,s),s}onCustomerInfo(e){if(this.listeners.add(e),this.listeners.size===1)this.start();else if(this.last!==void 0){let t=this.last;queueMicrotask(()=>this.listeners.has(e)&&Y(e,t))}return()=>{this.listeners.delete(e)&&this.listeners.size===0&&this.stop()}}start(){this.following=this.session.onChange((e,t)=>{(e==="SIGNED_IN"||e==="SIGNED_OUT"||e==="SESSION_EXPIRED")&&this.follow(t)}),this.session.session().then(e=>{this.following&&!this.watch&&this.last===void 0&&this.follow(e)})}stop(){this.following?.(),this.following=void 0,this.unfollow(),this.last=void 0}follow(e){if(this.unfollow(),!e){this.tell(null);return}let t=this.socket.channel(`purchases:${this.ref}:${e.userId}`),s={userId:e.userId,channel:t,off:()=>{},revision:-1,reading:!1,wanted:Number.NEGATIVE_INFINITY},i=[t.on("broadcast",r=>{r.event==="changed"&&this.changed(s,U(r.payload))}),t.on("state_snapshot",r=>this.held(s,U(z(r.entries)))),t.on("state_diff",r=>this.held(s,U(z(r.set))))];s.off=()=>i.forEach(r=>r()),this.watch=s,t.join().catch(()=>{}),this.read(s)}unfollow(){let e=this.watch;e&&(this.watch=void 0,e.off(),e.channel.leave())}changed(e,t){this.watch!==e||t!==void 0&&t<=e.revision||(e.reading?e.wanted=Math.max(e.wanted,t??Number.POSITIVE_INFINITY):this.read(e))}held(e,t){t!==void 0&&this.changed(e,t)}async read(e){e.reading=!0;try{for(;;){e.wanted=Number.NEGATIVE_INFINITY;try{let t=(await this.api.getMyCustomerInfo()).data;if(this.watch!==e)return;this.offer(e,t)}catch{}if(this.watch!==e||e.wanted<=e.revision)return}}finally{e.reading=!1}}offer(e,t){this.watch!==e||t.revision<=e.revision||(e.revision=t.revision,this.tell(t))}tell(e){if(!(this.last===null&&e===null)){this.last=e;for(let t of[...this.listeners])Y(t,e)}}};function Y(n,e){try{n(e)}catch{}}function z(n){let e=typeof n=="object"&&n!==null?n.revision:void 0;return typeof e=="object"&&e!==null?e.v:void 0}function U(n){let e=typeof n=="object"&&n!==null?n.revision:void 0;return typeof e=="number"&&Number.isFinite(e)?e:void 0}var ye=/^pb_[a-z0-9]+_s/,me=new Set(["invalid_token","token_expired","session_expired","session_revoked","missing_token"]),ge=new Set(["invalid_token","token_reuse","token_expired","session_revoked","session_expired","session_device_changed"]);function ve(n){if(ye.test(n.publishableKey)||"secretKey"in n)throw new TypeError("a secret key never goes into a client app: palbase/web takes the publishable key (pb_<ref>_c\u2026); servers use palbase/server");let e=/^pb_([a-z0-9]+)_c/.exec(n.publishableKey)?.[1];if(e===void 0)throw new TypeError("publishableKey is the project publishable key (pb_<ref>_c\u2026)");let t=new URL(n.url).origin,s=n.storage??(we()?L(`palbase.session.${t}`):N()),i=n.retry??q,r=P(k({baseUrl:n.url,credentials:{publishableKey:n.publishableKey},fetch:n.fetch}),i),a=y.client(r),o=new E(s,async h=>(await a.refreshToken({body:{refresh_token:h}})).data,h=>h instanceof S&&h.status===401&&ge.has(h.code),{lockName:`palbase.session.refresh.${t}`}),c=k({baseUrl:n.url,credentials:{publishableKey:n.publishableKey,accessToken:()=>o.accessToken()},fetch:n.fetch,xmlHttpRequest:n.xmlHttpRequest??(n.fetch===void 0?globalThis.XMLHttpRequest:void 0)}),l=P(j(c,o),i),u=new m({baseUrl:n.url,publishableKey:n.publishableKey,accessToken:()=>o.accessToken(),webSocket:n.webSocket});o.onChange(h=>{h==="SIGNED_OUT"||h==="SESSION_EXPIRED"||h==="SIGNED_IN"?u.disconnect():h==="TOKEN_REFRESHED"&&u.tokenChanged()});let d=new g(j(c,o),o,t);n.analytics&&d.start(n.analytics===!0?{}:n.analytics);let w=new Map,Q=h=>{let O=new URL(h).origin,b=w.get(O);return b||(b=P(j(k({baseUrl:O,credentials:{accessToken:()=>o.accessToken()},fetch:n.fetch}),o),i),w.set(O,b)),b},K=Object.assign(Object.create(F),{auth:new T(l,r,o,n.webauthn??globalThis.navigator?.credentials),socket:u,transport:l,analytics:d,purchases:new v(l,o,u,e)});return B(K,t,Q,l,u),K}function we(){try{return typeof globalThis.localStorage<"u"}catch{return!1}}function j(n,e){return{async send(t){let s=await e.session();try{return await n.send(t)}catch(i){let r=t.auth.some(a=>a.includes("userJWT"));if(!(i instanceof S)||i.status!==401||!me.has(i.code)||!r||!s)throw i;try{e.snapshot()?.refreshToken===s.refreshToken&&await e.refresh()}catch{throw i}if(e.snapshot()?.userId!==s.userId)throw i;return n.send(t)}}}}export{g as Analytics,Z as BackendError,_ as Channel,S as PalbaseError,v as Purchases,m as RealtimeSocket,te as RoomError,p as SessionChangedError,ve as createClient,ee as isBackendError,L as localStore,N as memoryStore};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! palbase 0.2.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{c as e,d as r,h as t}from"../chunks/5W6XJM46.js";import"../chunks/JEJ5CFTK.js";import"../chunks/ECUYQ73P.js";import"../chunks/HDX6YUAB.js";import"../chunks/TL4H6V3P.js";export{e as RESERVED_CLIENT_NAMES,t as __registerBackend,r as isClientName};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! palbase 0.2.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import{a as e,b as a,c as l,d as p,e as t,f as o,g as y,h as r,i as P,j as s,k as n,l as i,m as w,n as f}from"../chunks/AN5LCF5K.js";import"../chunks/ECUYQ73P.js";import"../chunks/HDX6YUAB.js";import"../chunks/TL4H6V3P.js";export{y as PAYWALL_COMPONENTS,t as PAYWALL_ICONS,o as PAYWALL_SCHEMA,w as Paywall,f as defaultPaywall,l as formatPeriod,a as formatPrice,r as initialPackage,p as packageValues,P as packagesOf,e as parseDuration,s as paywallLanguage,i as renderPaywall,n as resolvePaywall};
|
package/dist/web/vite.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/*! palbase 0.2.0 — Palbase SDK License (see LICENSE) */
|
|
2
|
+
import"../chunks/TL4H6V3P.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
|
+
${s.text}`)}finally{x(m,{recursive:!0,force:!0})}}export{F as palbase};
|
package/package.json
CHANGED
|
@@ -1,6 +1,113 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "palbase",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
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
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"homepage": "https://palbase.studio",
|
|
7
|
+
"author": "Palbase",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=26"
|
|
11
|
+
},
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"bin": {
|
|
14
|
+
"palbase": "./dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
"./web": {
|
|
18
|
+
"types": "./types/web/src/index.d.ts",
|
|
19
|
+
"default": "./dist/web/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./web/palbe": {
|
|
22
|
+
"types": "./types/web/src/palbe.d.ts",
|
|
23
|
+
"default": "./dist/web/palbe.js"
|
|
24
|
+
},
|
|
25
|
+
"./web/paywall": {
|
|
26
|
+
"types": "./types/web/src/paywall/index.d.ts",
|
|
27
|
+
"default": "./dist/web/paywall.js"
|
|
28
|
+
},
|
|
29
|
+
"./web/vite": {
|
|
30
|
+
"types": "./types/web/src/vite.d.ts",
|
|
31
|
+
"default": "./dist/web/vite.js"
|
|
32
|
+
},
|
|
33
|
+
"./server": {
|
|
34
|
+
"types": "./types/server/src/index.d.ts",
|
|
35
|
+
"node": "./dist/server/index.js",
|
|
36
|
+
"bun": "./dist/server/index.js",
|
|
37
|
+
"deno": "./dist/server/index.js",
|
|
38
|
+
"workerd": "./dist/server/index.js",
|
|
39
|
+
"edge-light": "./dist/server/index.js",
|
|
40
|
+
"react-native": "./dist/refuse/server.js",
|
|
41
|
+
"browser": "./dist/refuse/server.js",
|
|
42
|
+
"worker": "./dist/server/index.js",
|
|
43
|
+
"default": "./dist/server/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./ai": {
|
|
46
|
+
"types": "./types/ai/src/index.d.ts",
|
|
47
|
+
"node": "./dist/ai/index.js",
|
|
48
|
+
"bun": "./dist/ai/index.js",
|
|
49
|
+
"deno": "./dist/ai/index.js",
|
|
50
|
+
"workerd": "./dist/ai/index.js",
|
|
51
|
+
"edge-light": "./dist/ai/index.js",
|
|
52
|
+
"react-native": "./dist/refuse/ai.js",
|
|
53
|
+
"browser": "./dist/refuse/ai.js",
|
|
54
|
+
"worker": "./dist/ai/index.js",
|
|
55
|
+
"default": "./dist/ai/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./backend": {
|
|
58
|
+
"types": "./types/backend/src/index.d.ts",
|
|
59
|
+
"react-native": "./dist/refuse/backend.js",
|
|
60
|
+
"browser": "./dist/refuse/backend.js",
|
|
61
|
+
"default": "./dist/backend/index.js"
|
|
62
|
+
},
|
|
63
|
+
"./backend/env": {
|
|
64
|
+
"types": "./types/backend/src/db-env.d.ts",
|
|
65
|
+
"react-native": "./dist/refuse/backend.js",
|
|
66
|
+
"browser": "./dist/refuse/backend.js",
|
|
67
|
+
"default": "./dist/backend/env.js"
|
|
68
|
+
},
|
|
69
|
+
"./backend/engine": {
|
|
70
|
+
"types": "./types/backend/src/engine-exports.d.ts",
|
|
71
|
+
"react-native": "./dist/refuse/backend.js",
|
|
72
|
+
"browser": "./dist/refuse/backend.js",
|
|
73
|
+
"default": "./dist/backend/engine.js"
|
|
74
|
+
},
|
|
75
|
+
"./backend/stack": {
|
|
76
|
+
"types": "./types/backend/src/stack.d.ts",
|
|
77
|
+
"react-native": "./dist/refuse/backend.js",
|
|
78
|
+
"browser": "./dist/refuse/backend.js",
|
|
79
|
+
"default": "./dist/backend/stack.js"
|
|
80
|
+
},
|
|
81
|
+
"./backend/test": {
|
|
82
|
+
"types": "./types/backend/src/testing/index.d.ts",
|
|
83
|
+
"react-native": "./dist/refuse/backend.js",
|
|
84
|
+
"browser": "./dist/refuse/backend.js",
|
|
85
|
+
"default": "./dist/backend/test.js"
|
|
86
|
+
},
|
|
87
|
+
"./server/testing": {
|
|
88
|
+
"types": "./types/server/src/testing.d.ts",
|
|
89
|
+
"node": "./dist/server/testing.js",
|
|
90
|
+
"bun": "./dist/server/testing.js",
|
|
91
|
+
"deno": "./dist/server/testing.js",
|
|
92
|
+
"workerd": "./dist/server/testing.js",
|
|
93
|
+
"edge-light": "./dist/server/testing.js",
|
|
94
|
+
"react-native": "./dist/refuse/server.js",
|
|
95
|
+
"browser": "./dist/refuse/server.js",
|
|
96
|
+
"worker": "./dist/server/testing.js",
|
|
97
|
+
"default": "./dist/server/testing.js"
|
|
98
|
+
},
|
|
99
|
+
"./package.json": "./package.json"
|
|
100
|
+
},
|
|
101
|
+
"files": [
|
|
102
|
+
"dist",
|
|
103
|
+
"types",
|
|
104
|
+
"LICENSE",
|
|
105
|
+
"README.md"
|
|
106
|
+
],
|
|
107
|
+
"dependencies": {
|
|
108
|
+
"palgres": "0.2.0",
|
|
109
|
+
"reflect-metadata": "0.2.2",
|
|
110
|
+
"typescript": "6.0.3",
|
|
111
|
+
"zod": "4.6.5"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { type Fetch } from '../../internal/src/transport.js';
|
|
2
|
+
import { type RetryPolicy } from '../../internal/src/retry.js';
|
|
3
|
+
import * as modules from '../../internal/src/modules/index.js';
|
|
4
|
+
import { type Infer, type PreparedSchema, type StandardSchema } from './schema.js';
|
|
5
|
+
type Module = ReturnType<typeof modules.ai.client>;
|
|
6
|
+
export type Response = Awaited<ReturnType<Module['getResponse']>>['data'];
|
|
7
|
+
export type Usage = Awaited<ReturnType<Module['listUsage']>>['data']['usage'][number];
|
|
8
|
+
export interface AIOptions {
|
|
9
|
+
/** The project's address (https://<ref>.<domain>); default PALBASE_URL. */
|
|
10
|
+
url?: string;
|
|
11
|
+
/** The project's secret key (pb_<ref>_s…); default PALBASE_SECRET_KEY. */
|
|
12
|
+
secretKey?: string;
|
|
13
|
+
fetch?: Fetch;
|
|
14
|
+
retry?: RetryPolicy;
|
|
15
|
+
/** How long a stream that was cut is followed again before the caller is told (default 2 minutes). */
|
|
16
|
+
resumeFor?: number;
|
|
17
|
+
/**
|
|
18
|
+
* A server client whose ai module the calls go through, in place of url and
|
|
19
|
+
* secretKey — a backend's `Palbase`: the address, key and retries are that
|
|
20
|
+
* client's. Read at each call, so it may be given before it is bound.
|
|
21
|
+
*/
|
|
22
|
+
server?: {
|
|
23
|
+
readonly ai: Module;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** A role, or a catalogue model as provider:model (ai.models()). */
|
|
27
|
+
export type Model = 'fast' | 'default' | 'strong' | (string & {});
|
|
28
|
+
export interface Message {
|
|
29
|
+
role: 'user' | 'assistant';
|
|
30
|
+
content: string;
|
|
31
|
+
}
|
|
32
|
+
export interface Ask {
|
|
33
|
+
/** The question; or `messages`, the conversation so far. */
|
|
34
|
+
prompt?: string;
|
|
35
|
+
messages?: Message[];
|
|
36
|
+
instructions?: string;
|
|
37
|
+
model?: Model;
|
|
38
|
+
/** The caller's own labels: returned with the response and its event. */
|
|
39
|
+
metadata?: Record<string, string>;
|
|
40
|
+
signal?: AbortSignal;
|
|
41
|
+
}
|
|
42
|
+
export interface Generate<S extends StandardSchema> extends Ask {
|
|
43
|
+
schema: S | Schema<S>;
|
|
44
|
+
}
|
|
45
|
+
/** A schema checked against what the provider holds a model to: ai.schema(name, zod). */
|
|
46
|
+
export interface Schema<S extends StandardSchema> {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly schema: S;
|
|
49
|
+
readonly prepared: PreparedSchema<Infer<S>>;
|
|
50
|
+
}
|
|
51
|
+
/** A response started in the background: its end is ai.response.completed (or failed). */
|
|
52
|
+
export interface Job {
|
|
53
|
+
id: string;
|
|
54
|
+
status: string;
|
|
55
|
+
}
|
|
56
|
+
/** A stream of an answer as the model writes it. */
|
|
57
|
+
export interface TextStream {
|
|
58
|
+
/** The response's id, once it is admitted. */
|
|
59
|
+
readonly id: Promise<string>;
|
|
60
|
+
/** Each fragment as it arrives. */
|
|
61
|
+
readonly textStream: AsyncIterable<string>;
|
|
62
|
+
/** The whole answer at the end. */
|
|
63
|
+
readonly text: Promise<string>;
|
|
64
|
+
/** The response at its end. */
|
|
65
|
+
readonly response: Promise<Response>;
|
|
66
|
+
/**
|
|
67
|
+
* The stream as an HTTP answer a backend route returns to a browser:
|
|
68
|
+
* server-sent events `data: {"text": "<fragment>"}` and a last
|
|
69
|
+
* `event: done` with the answer.
|
|
70
|
+
*/
|
|
71
|
+
toResponse(init?: ResponseInit): globalThis.Response;
|
|
72
|
+
}
|
|
73
|
+
/** A stream of a schema's answer. */
|
|
74
|
+
export interface ObjectStream<T> extends Omit<TextStream, 'toResponse'> {
|
|
75
|
+
/** The document as far as the model has written it, each time it grows. */
|
|
76
|
+
readonly partialObjectStream: AsyncIterable<DeepPartial<T>>;
|
|
77
|
+
/** The document at the end, checked against the schema. */
|
|
78
|
+
readonly object: Promise<T>;
|
|
79
|
+
toResponse(init?: ResponseInit): globalThis.Response;
|
|
80
|
+
}
|
|
81
|
+
export type DeepPartial<T> = T extends object ? {
|
|
82
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
83
|
+
} : T;
|
|
84
|
+
export interface Embed {
|
|
85
|
+
model?: 'default' | (string & {});
|
|
86
|
+
/** A shorter vector than the model's own. */
|
|
87
|
+
dimensions?: number;
|
|
88
|
+
signal?: AbortSignal;
|
|
89
|
+
}
|
|
90
|
+
export interface Picture {
|
|
91
|
+
mediaType: string;
|
|
92
|
+
bytes: Uint8Array;
|
|
93
|
+
}
|
|
94
|
+
export interface ImageRequest {
|
|
95
|
+
prompt: string;
|
|
96
|
+
model?: 'default' | 'strong' | (string & {});
|
|
97
|
+
size?: string;
|
|
98
|
+
quality?: 'auto' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
99
|
+
background?: 'auto' | 'transparent' | 'opaque';
|
|
100
|
+
format?: 'png' | 'jpeg' | 'webp';
|
|
101
|
+
count?: number;
|
|
102
|
+
/** Pictures to work from: with them the request is an edit. */
|
|
103
|
+
references?: Array<Uint8Array | Blob | Picture>;
|
|
104
|
+
/** Marks the part of the first reference to change (a PNG with alpha). */
|
|
105
|
+
mask?: Uint8Array | Blob;
|
|
106
|
+
signal?: AbortSignal;
|
|
107
|
+
}
|
|
108
|
+
export interface Images {
|
|
109
|
+
id: string;
|
|
110
|
+
model: string;
|
|
111
|
+
pictures: Picture[];
|
|
112
|
+
costNanoUSD: number;
|
|
113
|
+
/** Writes a picture (the first by default) into the project's storage: `bucket` is a storage client's bucket, or anything with upload(path, body, options). */
|
|
114
|
+
save(bucket: Uploader, path: string, index?: number): Promise<unknown>;
|
|
115
|
+
}
|
|
116
|
+
export interface Uploader {
|
|
117
|
+
upload(path: string, body: Uint8Array | Blob, options?: {
|
|
118
|
+
contentType?: string;
|
|
119
|
+
}): Promise<unknown>;
|
|
120
|
+
}
|
|
121
|
+
export interface AI {
|
|
122
|
+
/** The answer to a question, as text. */
|
|
123
|
+
ask(prompt: string, options?: Omit<Ask, 'prompt'>): Promise<string>;
|
|
124
|
+
ask(request: Ask): Promise<string>;
|
|
125
|
+
/** A document of the schema's shape, checked against it. With background: true, the response's id at once. */
|
|
126
|
+
generate<S extends StandardSchema>(request: Generate<S> & {
|
|
127
|
+
background?: false;
|
|
128
|
+
}): Promise<Infer<S>>;
|
|
129
|
+
generate<S extends StandardSchema>(request: Generate<S> & {
|
|
130
|
+
background: true;
|
|
131
|
+
}): Promise<Job>;
|
|
132
|
+
/** The answer as the model writes it: text, or with a schema the document as far as it has got. */
|
|
133
|
+
stream(request: Ask): TextStream;
|
|
134
|
+
stream<S extends StandardSchema>(request: Generate<S>): ObjectStream<Infer<S>>;
|
|
135
|
+
/** Starts a text answer in the background: its end is the event ai.response.completed. */
|
|
136
|
+
start(request: Ask): Promise<Job>;
|
|
137
|
+
/** A schema checked now against what the provider holds a model to: throws AISchemaError naming the field it cannot. */
|
|
138
|
+
schema<S extends StandardSchema>(name: string, schema: S): Schema<S>;
|
|
139
|
+
/** A response, by its id (a job's result). */
|
|
140
|
+
response(id: string, options?: {
|
|
141
|
+
signal?: AbortSignal;
|
|
142
|
+
}): Promise<Response>;
|
|
143
|
+
/** The document of a schema's response started in the background, checked. */
|
|
144
|
+
result<S extends StandardSchema>(id: string, schema: S | Schema<S>): Promise<Infer<S>>;
|
|
145
|
+
cancel(id: string): Promise<Response>;
|
|
146
|
+
/** One vector per text, in order. */
|
|
147
|
+
embed(texts: string[], options?: Embed): Promise<number[][]>;
|
|
148
|
+
embed(text: string, options?: Embed): Promise<number[]>;
|
|
149
|
+
/** Pictures for a prompt: waits for the job (it takes the provider up to minutes). */
|
|
150
|
+
image(request: ImageRequest): Promise<Images>;
|
|
151
|
+
models(): Promise<Awaited<ReturnType<Module['listModels']>>['data']>;
|
|
152
|
+
/** Uses of models and their cost, newest first. */
|
|
153
|
+
usage(options?: {
|
|
154
|
+
kind?: 'text' | 'embedding' | 'image';
|
|
155
|
+
limit?: number;
|
|
156
|
+
cursor?: string;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
usage: Usage[];
|
|
159
|
+
nextCursor?: string;
|
|
160
|
+
}>;
|
|
161
|
+
/** Calls go out with the project's own provider key from now on. */
|
|
162
|
+
connectProvider(provider: string, key: string): Promise<{
|
|
163
|
+
name: string;
|
|
164
|
+
verified: boolean;
|
|
165
|
+
}>;
|
|
166
|
+
disconnectProvider(provider: string): Promise<void>;
|
|
167
|
+
/** The generated client of the ai module, for what the methods above do not say. */
|
|
168
|
+
readonly module: Module;
|
|
169
|
+
}
|
|
170
|
+
/** The response did not complete: its code and why. */
|
|
171
|
+
export declare class AIResponseError extends Error {
|
|
172
|
+
readonly code: string;
|
|
173
|
+
readonly response: Response;
|
|
174
|
+
constructor(response: Response);
|
|
175
|
+
}
|
|
176
|
+
/** The ai of the project, for a server. */
|
|
177
|
+
export declare function createAI(options?: AIOptions): AI;
|
|
178
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createAI, AIResponseError } from './ai.js';
|
|
2
|
+
export type { AI, AIOptions, Ask, DeepPartial, Embed, Generate, ImageRequest, Images, Job, Message, Model, ObjectStream, Picture, Response, Schema, TextStream, Uploader, Usage, } from './ai.js';
|
|
3
|
+
export { AISchemaError, prepare } from './schema.js';
|
|
4
|
+
export type { Infer, StandardSchema } from './schema.js';
|
|
5
|
+
export { partial } from './partial.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function partial(text: string): unknown;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Standard Schema v1 with its JSON Schema side (https://standardschema.dev). */
|
|
2
|
+
export interface StandardSchema<Output = unknown> {
|
|
3
|
+
readonly '~standard': {
|
|
4
|
+
readonly version: 1;
|
|
5
|
+
readonly vendor: string;
|
|
6
|
+
readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;
|
|
7
|
+
readonly types?: {
|
|
8
|
+
readonly input: unknown;
|
|
9
|
+
readonly output: Output;
|
|
10
|
+
};
|
|
11
|
+
readonly jsonSchema?: {
|
|
12
|
+
readonly output: (options: {
|
|
13
|
+
target: string;
|
|
14
|
+
libraryOptions?: Record<string, unknown>;
|
|
15
|
+
}) => Record<string, unknown>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export type StandardResult<Output> = {
|
|
20
|
+
readonly value: Output;
|
|
21
|
+
readonly issues?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
readonly issues: ReadonlyArray<{
|
|
24
|
+
readonly message: string;
|
|
25
|
+
readonly path?: ReadonlyArray<PropertyKey | {
|
|
26
|
+
readonly key: PropertyKey;
|
|
27
|
+
}>;
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
export type Infer<S> = S extends StandardSchema<infer O> ? O : never;
|
|
31
|
+
/** A schema the provider cannot hold a model to, and where. */
|
|
32
|
+
export declare class AISchemaError extends Error {
|
|
33
|
+
readonly path: string;
|
|
34
|
+
constructor(path: string, message: string);
|
|
35
|
+
}
|
|
36
|
+
/** A schema checked and turned into the provider's: what generate() sends. */
|
|
37
|
+
export interface PreparedSchema<Output> {
|
|
38
|
+
name: string;
|
|
39
|
+
json: Record<string, unknown>;
|
|
40
|
+
check: (value: unknown) => Promise<Output>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* prepare checks a schema against what the provider holds a model to and
|
|
44
|
+
* returns the provider's form of it. It throws AISchemaError naming the first
|
|
45
|
+
* field the provider cannot hold.
|
|
46
|
+
*/
|
|
47
|
+
export declare function prepare<S extends StandardSchema>(schema: S, name?: string): PreparedSchema<Infer<S>>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type PalbaseServer } from '../../server/src/index.js';
|
|
2
|
+
import { type AuthSpec, type RateLimitConfig } from './decorators.js';
|
|
3
|
+
import { type AppTokens, type CorsOptions } from './engine.js';
|
|
4
|
+
import { type DatabaseConfig } from './database.js';
|
|
5
|
+
import { type PalbaseConnection } from './env.js';
|
|
6
|
+
export interface AppConfig {
|
|
7
|
+
/** The project this backend belongs to; each value from the environment unless given. */
|
|
8
|
+
palbase?: PalbaseConnection;
|
|
9
|
+
/** Every route's auth unless it or its controller says otherwise (default: a signed-in user). */
|
|
10
|
+
auth?: AuthSpec;
|
|
11
|
+
/**
|
|
12
|
+
* The app's own API tokens (a CI's, an agent's): a bearer that is no JWT and
|
|
13
|
+
* that accepts takes (its shape and a tag only the app signs — no database)
|
|
14
|
+
* is given to resolve, in a transaction of its own (Database is it, as in an
|
|
15
|
+
* @On handler); it answers who the token stands for (its claims are the
|
|
16
|
+
* request's), or null to refuse it.
|
|
17
|
+
*/
|
|
18
|
+
tokens?: AppTokens;
|
|
19
|
+
/** Every route's limit unless it says otherwise (default 300 a minute per caller); false for none. */
|
|
20
|
+
rateLimit?: RateLimitConfig | false;
|
|
21
|
+
/** Bytes a request body may be (default 1 MiB). */
|
|
22
|
+
bodyLimit?: number;
|
|
23
|
+
/** Off unless given: a backend browsers call names their origins. */
|
|
24
|
+
cors?: CorsOptions;
|
|
25
|
+
/** The app's database: its schemas (db/*.ts), and its address unless PALBASE_DB_URL says. */
|
|
26
|
+
db?: DatabaseConfig;
|
|
27
|
+
/** The port served on (default $PORT, else 8080; 0 for a free one). */
|
|
28
|
+
port?: number;
|
|
29
|
+
/** The address served on (default 0.0.0.0). */
|
|
30
|
+
host?: string;
|
|
31
|
+
/** Boot attempts when onStart() fails (default 5), the first wait (default 1000 ms, doubling). */
|
|
32
|
+
boot?: {
|
|
33
|
+
attempts?: number;
|
|
34
|
+
backoffMs?: number;
|
|
35
|
+
};
|
|
36
|
+
/** Exit 1 on an uncaught error or unhandled rejection (default true; a test harness that handles its own turns it off). */
|
|
37
|
+
exitOnFatal?: boolean;
|
|
38
|
+
/** process.env unless given. */
|
|
39
|
+
env?: Record<string, string | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Each answered request as a log line (method, path, status, time; ten a
|
|
42
|
+
* second at most, the rest counted) and as a trace in the project's
|
|
43
|
+
* analytics, which Studio's Overview and Network read (default true).
|
|
44
|
+
*/
|
|
45
|
+
requestTelemetry?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface PalbaseApplication {
|
|
48
|
+
/** "<METHOD> <path>" of every route. */
|
|
49
|
+
readonly routes: readonly string[];
|
|
50
|
+
/** The project's modules, with the app's secret key (also reachable as Palbase). */
|
|
51
|
+
readonly palbase: PalbaseServer;
|
|
52
|
+
/** The port it serves on. */
|
|
53
|
+
readonly port: number;
|
|
54
|
+
/** One request, without the network — for tests. */
|
|
55
|
+
handle(request: Request, info?: {
|
|
56
|
+
remoteAddress?: string;
|
|
57
|
+
}): Promise<Response>;
|
|
58
|
+
/** Stops taking connections, finishes the requests in flight (20 s at most), runs onShutdown(), sends the request traces still held (2 s at most). */
|
|
59
|
+
close(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
export declare const PalbaseFactory: {
|
|
62
|
+
create(root: Function | Function[], config?: AppConfig): Promise<PalbaseApplication>;
|
|
63
|
+
};
|
|
64
|
+
/** The run that wrote the contract has nothing to serve: process.exit ended it (where it is stubbed, this does). */
|
|
65
|
+
export declare class ContractRunEnded extends Error {
|
|
66
|
+
constructor();
|
|
67
|
+
}
|
|
68
|
+
/** The run that migrated has nothing to serve: process.exit ended it (where it is stubbed, this does). */
|
|
69
|
+
export declare class MigrationRunEnded extends Error {
|
|
70
|
+
readonly code: number;
|
|
71
|
+
constructor(code: number);
|
|
72
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** The longest an entry lasts: thirty days, the cache module's own bound. */
|
|
2
|
+
export declare const CACHE_MAX_TTL: number;
|
|
3
|
+
export interface CacheClient {
|
|
4
|
+
/** Read a value; null when there is none (or the cache could not be reached). */
|
|
5
|
+
get<T = unknown>(key: string): Promise<T | null>;
|
|
6
|
+
/** Write a JSON value for ttl seconds — thirty days without one, and at most. */
|
|
7
|
+
set(key: string, value: unknown, ttl?: number): Promise<void>;
|
|
8
|
+
/** Delete a key. Throws when the cache could not be reached: the value would outlive the delete. */
|
|
9
|
+
del(key: string): Promise<void>;
|
|
10
|
+
/** Add one to the key's count, atomically across every replica, and answer the new count. */
|
|
11
|
+
incr(key: string): Promise<number>;
|
|
12
|
+
/**
|
|
13
|
+
* Read through: on a hit the value, on a miss fn's, kept for ttl seconds.
|
|
14
|
+
* Concurrent misses on one key in this process share one fn; fn's own
|
|
15
|
+
* error goes to every caller and nothing is kept.
|
|
16
|
+
*/
|
|
17
|
+
getOrSet<T>(key: string, ttl: number, fn: () => Promise<T> | T): Promise<T>;
|
|
18
|
+
}
|
|
19
|
+
/** The project's cache (the platform's cache module, with the app's secret key). */
|
|
20
|
+
export declare const Cache: CacheClient;
|
|
21
|
+
export interface MemoryCacheOptions {
|
|
22
|
+
/** Bound on entries held. On overflow the soonest-to-expire are dropped. */
|
|
23
|
+
maxEntries?: number;
|
|
24
|
+
/** Injectable clock, for tests. */
|
|
25
|
+
now?: () => number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A cache in this process's memory, with Cache's behaviour: for a test, or a
|
|
29
|
+
* script with no project. Values are kept as their JSON, as the platform's
|
|
30
|
+
* are; getOrSet is single-flight.
|
|
31
|
+
*/
|
|
32
|
+
export declare function makeMemoryCache(opts?: MemoryCacheOptions): CacheClient;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
export type DiErrorKind = 'unowned class' | 'duplicate ownership' | 'undeclared provider' | 'unknown export' | 'unknown import' | 'metadata missing' | 'unresolvable dependency' | 'missing import' | 'private dependency' | 'dependency cycle' | 'nest lifecycle name';
|
|
3
|
+
export declare class DiError extends Error {
|
|
4
|
+
readonly kind: DiErrorKind;
|
|
5
|
+
readonly path: string[];
|
|
6
|
+
constructor(kind: DiErrorKind, path: string[], at: string, detail: string, solutions: string[]);
|
|
7
|
+
}
|
|
8
|
+
type Ctor = abstract new (...args: never[]) => object;
|
|
9
|
+
interface Owned {
|
|
10
|
+
cls: Ctor;
|
|
11
|
+
module: Function;
|
|
12
|
+
}
|
|
13
|
+
export declare class Container {
|
|
14
|
+
private readonly owner;
|
|
15
|
+
private readonly defs;
|
|
16
|
+
private readonly instances;
|
|
17
|
+
/** Construction order: dependencies before their dependents. */
|
|
18
|
+
readonly order: object[];
|
|
19
|
+
readonly controllers: {
|
|
20
|
+
cls: Ctor;
|
|
21
|
+
module: Function;
|
|
22
|
+
}[];
|
|
23
|
+
/** The providers whose @On take the platform's events. */
|
|
24
|
+
readonly eventProviders: Ctor[];
|
|
25
|
+
/** The providers that are @Webhook classes: their @On take a third party's. */
|
|
26
|
+
readonly webhooks: Ctor[];
|
|
27
|
+
/** The providers that are @Job classes: the platform runs them on their schedules. */
|
|
28
|
+
readonly jobProviders: Ctor[];
|
|
29
|
+
/** The providers that are @Room classes. */
|
|
30
|
+
readonly rooms: Ctor[];
|
|
31
|
+
constructor(modules: Function[]);
|
|
32
|
+
private collect;
|
|
33
|
+
private validate;
|
|
34
|
+
/** The built instance of a class (resolving its dependencies). */
|
|
35
|
+
get<T extends object>(cls: abstract new (...args: never[]) => T): T;
|
|
36
|
+
private resolve;
|
|
37
|
+
/**
|
|
38
|
+
* The built instance `consumer` asks for by type outside its constructor —
|
|
39
|
+
* a route's @Resolve, by its controller — under a constructor's rules.
|
|
40
|
+
*/
|
|
41
|
+
dependencyOf<T extends object>(consumer: abstract new (...args: never[]) => object, dep: abstract new (...args: never[]) => T, at: string): T;
|
|
42
|
+
private reachable;
|
|
43
|
+
private target;
|
|
44
|
+
/** onStart() of every instance, in construction order; a throw stops the boot after the started ones are shut down. */
|
|
45
|
+
start(): Promise<void>;
|
|
46
|
+
/** onShutdown() in reverse construction order, every one tried. */
|
|
47
|
+
shutdown(of?: object[]): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
export type { Owned };
|