@econ-v1/app-sdk 7.5.33 → 7.5.35

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/app-log.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export declare const ERROR_REPORT_INTERVAL_MS = 60000;
2
+ export declare const APP_LOG_MAX_BYTES: number;
3
+ export declare const APP_LOG_TAIL_BYTES: number;
2
4
  export interface AppLogWriter {
3
5
  write(level: string, message: string): void;
4
6
  }
@@ -7,5 +9,9 @@ export interface AppLogWriterOptions {
7
9
  reportError?: (line: string) => void;
8
10
  /** Clock for the report rate limit. Defaults to `Date.now`. */
9
11
  now?: () => number;
12
+ /** Hard bound checked before each write. */
13
+ maxBytes?: number;
14
+ /** Newest bytes retained when the bound is crossed. */
15
+ tailBytes?: number;
10
16
  }
11
17
  export declare function createAppLogWriter(logDir: string | undefined, options?: AppLogWriterOptions): AppLogWriter;
@@ -1,2 +1,2 @@
1
- var se=Object.defineProperty;var ae=(e)=>e;function pe(e,t){this[e]=ae.bind(null,t)}var ce=(e,t)=>{for(var r in t)se(e,r,{get:t[r],enumerable:!0,configurable:!0,set:pe.bind(t,r)})};import{Database as ve}from"burger:sqlite";var q={};ce(q,{incrementCounter:()=>T,initAppTelemetry:()=>M,injectTraceContext:()=>ue,telemetryActive:()=>P,traceIncomingCapability:()=>le});async function M(e){}function P(){return!1}function T(e,t=1,r){}function ue(e){return e}async function le(e,t,r){return r()}import{connect as de,dataDir as me,exit as O,logDir as fe,memoryUsage as ye}from"burger:host";var N=!0,U=256;function L(){return{socket:void 0,logDir:fe,dataDir:me}}var H=L();function B(){return H.socket}function K(e,t,r=O){r(e)}function g(e){O(e)}function G(){}var ge=/the app channel is (not open|closed)/;function Q(e){let t=de(),r=!0,n=!1;function i(o){if(n)return;try{t.send(o)}catch(s){if(s instanceof Error&&ge.test(s.message)){n=!0;return}throw s}}return t.onFrame((o)=>{if(!r)return;e.onFrame(o).catch((s)=>e.onFrameError(s))}),t.onClose((o)=>{if(n=!0,o)e.onError(o);else e.onClose()}),queueMicrotask(()=>e.onConnected("burger:host")),{send(o){i(o)},sendAndFlush(o){return i(o),Promise.resolve()},stopAccepting(){r=!1},end(){n=!0,t.close()}}}function V(){let e;return{run(t,r){let n=e;e=t;try{return r()}finally{e=n}},getStore(){return e}}}function Z(){let e=ye();return{heap_used_kb:Math.round(e.heap_used_kb),heap_total_kb:Math.round(e.heap_total_kb),external_kb:Math.round(e.external_kb),heap_capacity_kb:Math.round(e.heap_capacity_kb)}}function W(){throw Error("heap snapshots are not available in the Burger runtime")}async function Y(e,t=W,r=W){let n=t();return{size_bytes:await r(e,n)}}import*as p from"burger:fs";import{join as _e}from"burger:path";var he=60000;function J(e,t={}){if(!e)return{write:()=>{}};let r=_e(e,"app.log"),n=t.reportError??((u)=>console.error(u)),i=t.now??Date.now,o=typeof p.openSync==="function"&&typeof p.writeSync==="function"&&typeof p.closeSync==="function",s=null,a=!1,y=null,x=0;function z(){if(a)return;p.mkdirSync(e,{recursive:!0}),a=!0}function ie(u){let R=i();if(y!==null&&R-y<he){x+=1;return}let C=u instanceof Error?u.message:String(u),k=x>0?`; ${x} earlier failure(s) not reported`:"";n(`[node-app-sdk] app.log write failed (${r}): ${C}${k}`),y=R,x=0}return{write(u,R){let C=`${new Date().toISOString()} [${u.toUpperCase().padEnd(5)}] ${R}
2
- `;try{if(!o){z(),p.appendFileSync(r,C);return}if(s===null)z(),s=p.openSync(r,"a");p.writeSync(s,C)}catch(k){if(s!==null){try{p.closeSync(s)}catch{}s=null}ie(k)}}}}var{injectTraceContext:xe,traceIncomingCapability:Re}=q,Ce=M,We=P,Oe=T,Ie=U;function Ue(e,t={}){let r=t.cacheSizeKb??Ie;if(!Number.isInteger(r)||r<=0)throw RangeError("cacheSizeKb must be a positive integer");let n=new ve(e);try{return n.exec(`PRAGMA cache_size = -${r}`),n}catch(i){throw n.close(),i}}var Be=L,Ke=B,Ge=K,Ae=J(H.logDir),c=null,te=V(),_=new Map,l={trace:(e)=>b("trace",e),debug:(e)=>b("debug",e),info:(e)=>b("info",e),warn:(e)=>b("warn",e),error:(e)=>b("error",e),holdLease:()=>{let e=!1;return I(),()=>{if(e)return;e=!0,A()}}};function b(e,t){if(Ae.write(e,t),c)c({type:"log",level:e,message:t});else console[e==="trace"?"debug":e](t)}function Qe(e,t){if(!c)return Promise.reject(Error("Not connected to host"));let r=t??30000,n=e.timeout_ms===void 0?{...e,timeout_ms:r}:e,i={...n,trace_context:xe({...n.trace_context??{}})},o=te.getStore();if(o?.active&&o.id!==void 0)i.invocation_context_id=o.id;return new Promise((s,a)=>{_.set(e.id,{resolve:s,reject:a}),c({type:"invoke_capability",id:e.id,request:i}),setTimeout(()=>{if(_.has(e.id))_.delete(e.id),a(Error(`Capability invocation timed out after ${r}ms: ${e.capability}`))},r)})}function Ve(e,t){if(!c)throw Error("Not connected to host");c({type:"publish_event",event_name:e,data:t})}var d=0,h,m=null,v=!1,S,ne=()=>g(0),F=ne,D,re=(e)=>(c?.(e),Promise.resolve()),j=re;function X(e){if(h=e,e===void 0)E()}function E(){if(m)clearTimeout(m),m=null}function we(){if(v)return;if(h===void 0)return;if(d!==0)return;E();let e=Math.max(0,h*1000),t=setTimeout(()=>{m=null,Se()},e);t.unref?.(),m=t}function I(){d++,E()}function A(){if(d=Math.max(0,d-1),d===0)we()}async function Se(){if(v)return;if(v=!0,D?.(),S)await S.shutdown();await j({type:"lease_exit"}),F()}function Ze(){E(),d=0,h=void 0,v=!1,S=void 0,F=ne,D=void 0,j=re}function Ye(e){F=e}function Je(){return{inFlight:d,rememberedSecs:h,timerArmed:m!==null,draining:v}}var Ee=30000;function ke(){let e=process.env.NODE_APP_MEMORY_SAMPLE_INTERVAL_MS,t=e?Number.parseInt(e,10):NaN;return Number.isFinite(t)&&t>=1000?t:Ee}var f=null,Me=Z;function ee(e){e({type:"app_memory",...Me()})}function Pe(e){if(f)return;ee(e),f=setInterval(()=>ee(e),ke()),f.unref?.()}function w(){if(f)clearInterval(f),f=null}var Te=Y;async function qe(e,t,r=Te){try{let n=await r(e.path);t({type:"heap_snapshot_response",id:e.id,success:!0,size_bytes:n.size_bytes})}catch{t({type:"heap_snapshot_response",id:e.id,success:!1,error:"heap_snapshot_failed"})}}function Ne(e,t){let r=t.indexOf("?"),n=r>=0?t.slice(0,r):t,i=e.split("/"),o=n.split("/"),s=0,a=0;while(s<i.length){if(i[s]==="**")return!0;if(a>=o.length)return!1;if(i[s]!=="*"&&i[s]!==o[a])return!1;s++,a++}return a===o.length}class Le{_routes=[];route(e,t,r,n){this._routes.push({method:e,path:t,policy:r,handler:n})}async init(e){}async shutdown(){}async handleRequest(e){if(this._routes.length>0)return this._dispatchRoute(e);return{status:501,headers:{},body:{error:"Not implemented"}}}async _dispatchRoute(e){let t=e.method.toUpperCase(),r=e.path;for(let n of this._routes){if(!(n.method==="*"||n.method.toUpperCase()===t))continue;if(!Ne(n.path,r))continue;let o=n.policy.requiredPermissions??[],s=e.caller?.granted_permissions??[],a=o.filter((y)=>!s.includes(y));if(a.length>0)return l.warn(`SDK scope denied: [${a.join(", ")}] missing for ${t} ${r}`),{status:403,headers:{},body:{error:`Missing permissions: ${a.join(", ")}`}};return n.handler(e)}return this.notFound()}async handleEvent(e){}providedCapabilities(){return[]}async handleCapability(e){return{id:e.id,success:!1,payload:{error:"Capability handling not implemented"}}}json(e,t=200){return{status:t,headers:{"Content-Type":"application/json"},body:e}}error(e,t=500){return{status:t,headers:{"Content-Type":"application/json"},body:{error:e}}}notFound(){return this.error("Not found",404)}}function Xe(e){G(),Ce(e.metadata?.name??"node-app");let t=Q({onConnected:(n)=>{l.debug(`Connected to host via ${n}`)},onFrame:(n)=>oe(e,n,r),onFrameError:(n)=>{l.error(`Failed to parse IPC message: ${n}`)},onError:(n)=>{console.error(`[node-app-sdk] Socket error: ${n.message}`),g(1)},onClose:()=>{w(),g(0),l.debug("Socket closed, shutting down")}});function r(n){t.send(n)}c=r,D=()=>{t.stopAccepting()},j=(n)=>t.sendAndFlush(n),process.on("SIGTERM",async()=>{if(!N)return;w(),await e.shutdown(),t.end(),process.exit(0)}),process.on("SIGINT",async()=>{if(!N)return;w(),await e.shutdown(),t.end(),process.exit(0)})}async function oe(e,t,r){switch(S=e,t.type){case"init":{let n=t.config;await e.init(n),r({type:"ready",metadata:e.metadata}),Pe(r);break}case"request":{let{id:n,request:i}=t;I();try{let o=await e.handleRequest(i);r({type:"response",id:n,response:o})}catch(o){r({type:"response",id:n,response:{status:500,headers:{},body:{error:`Internal app error: ${o}`}}})}finally{A()}break}case"event":{let{event:n,lease_secs:i}=t;X(i),I();try{await e.handleEvent(n)}catch(o){l.error(`Event handler error: ${o}`)}finally{A()}break}case"capability_request":{let{id:n,request:i}=t;X(i.lease_secs),I();let o={id:i.invocation_context_id,active:!0};try{let s=await te.run(o,async()=>{try{return await Re(i.capability,i.trace_context,()=>e.handleCapability(i))}finally{o.active=!1}});r({type:"capability_response",id:n,response:s})}catch(s){r({type:"capability_response",id:n,response:{id:i.id,success:!1,payload:{error:`Capability handler error: ${s}`}}})}finally{A()}break}case"invoke_capability_result":{let{id:n,response:i}=t,o=_.get(n);if(o)_.delete(n),o.resolve(i);break}case"shutdown":{l.info("Received shutdown signal from host"),w(),await e.shutdown(),g(0);break}case"heap_snapshot_request":{await qe(t,r);break}default:l.warn(`Unknown IPC message type: ${t.type}`)}}async function et(e,t,r){c=r,await oe(e,t,c)}export{Le as NodeApp,Te as _captureHeapSnapshotTo,qe as _handleHeapSnapshotRequest,Be as _resolveCtx,Me as _sampleMemory,Ge as _testExitWorker,et as _testHandleMessage,Je as _testLeaseState,Ze as _testResetLeaseState,Ke as _testRunNodeAppPath,Ye as _testSetLeaseExitFn,l as host,Oe as incrementCounter,Ce as initAppTelemetry,Qe as invokeCapability,Ue as openDatabase,Ve as publishEvent,Xe as runNodeApp,We as telemetryActive};
1
+ var ue=Object.defineProperty;var le=(e)=>e;function de(e,t){this[e]=le.bind(null,t)}var fe=(e,t)=>{for(var r in t)ue(e,r,{get:t[r],enumerable:!0,configurable:!0,set:de.bind(t,r)})};import{Database as Se}from"burger:sqlite";var N={};fe(N,{incrementCounter:()=>q,initAppTelemetry:()=>T,injectTraceContext:()=>me,telemetryActive:()=>L,traceIncomingCapability:()=>ye});async function T(e){}function L(){return!1}function q(e,t=1,r){}function me(e){return e}async function ye(e,t,r){return r()}import{connect as ge,dataDir as be,exit as G,logDir as _e,memoryUsage as he}from"burger:host";var H=!0,Y=256;function F(){return{socket:void 0,logDir:_e,dataDir:be}}var B=F();function Q(){return B.socket}function V(e,t,r=G){r(e)}function b(e){G(e)}function Z(){}var ve=/the app channel is (not open|closed)/;function X(e){let t=ge(),r=!0,n=!1;function i(o){if(n)return;try{t.send(o)}catch(a){if(a instanceof Error&&ve.test(a.message)){n=!0;return}throw a}}return t.onFrame((o)=>{if(!r)return;e.onFrame(o).catch((a)=>e.onFrameError(a))}),t.onClose((o)=>{if(n=!0,o)e.onError(o);else e.onClose()}),queueMicrotask(()=>e.onConnected("burger:host")),{send(o){i(o)},sendAndFlush(o){return i(o),Promise.resolve()},stopAccepting(){r=!1},end(){n=!0,t.close()}}}function J(){let e;return{run(t,r){let n=e;e=t;try{return r()}finally{e=n}},getStore(){return e}}}function ee(){let e=he();return{heap_used_kb:Math.round(e.heap_used_kb),heap_total_kb:Math.round(e.heap_total_kb),external_kb:Math.round(e.external_kb),heap_capacity_kb:Math.round(e.heap_capacity_kb)}}function K(){throw Error("heap snapshots are not available in the Burger runtime")}async function te(e,t=K,r=K){let n=t();return{size_bytes:await r(e,n)}}import*as s from"burger:fs";import{join as Re}from"burger:path";var Ce=60000,Ie=52428800,Ae=10485760;function ne(e,t={}){if(!e)return{write:()=>{}};let r=Re(e,"app.log"),n=t.reportError??((l)=>console.error(l)),i=t.now??Date.now,o=t.maxBytes??Ie,a=Math.min(t.tailBytes??Ae,o),p=typeof s.openSync==="function"&&typeof s.writeSync==="function"&&typeof s.closeSync==="function"&&typeof s.fstatSync==="function"&&typeof s.readSync==="function"&&typeof s.ftruncateSync==="function",c=null,O=!1,M=null,R=0;function W(){if(O)return;s.mkdirSync(e,{recursive:!0}),O=!0}function ce(l){let C=i();if(M!==null&&C-M<Ce){R+=1;return}let I=l instanceof Error?l.message:String(l),d=R>0?`; ${R} earlier failure(s) not reported`:"";n(`[node-app-sdk] app.log write failed (${r}): ${I}${d}`),M=C,R=0}return{write(l,C){let I=`${new Date().toISOString()} [${l.toUpperCase().padEnd(5)}] ${C}
2
+ `;try{if(!p){W(),s.appendFileSync(r,I);return}if(c===null)W(),c=s.openSync(r,"a+");let d=s.fstatSync(c).size;if(d>o){let P=Math.min(d,a),U=Buffer.alloc(P);s.readSync(c,U,0,P,d-P),s.ftruncateSync(c,0),s.writeSync(c,U)}s.writeSync(c,I)}catch(d){if(c!==null){try{s.closeSync(c)}catch{}c=null}ce(d)}}}}var{injectTraceContext:we,traceIncomingCapability:Ee}=N,ke=T,Ye=L,Qe=q,Me=Y;function Ve(e,t={}){let r=t.cacheSizeKb??Me;if(!Number.isInteger(r)||r<=0)throw RangeError("cacheSizeKb must be a positive integer");let n=new Se(e);try{return n.exec(`PRAGMA cache_size = -${r}`),n}catch(i){throw n.close(),i}}var Ze=F,Xe=Q,Je=V,Pe=ne(B.logDir),u=null,ie=J(),h=new Map,f={trace:(e)=>_("trace",e),debug:(e)=>_("debug",e),info:(e)=>_("info",e),warn:(e)=>_("warn",e),error:(e)=>_("error",e),holdLease:()=>{let e=!1;return A(),()=>{if(e)return;e=!0,S()}}};function _(e,t){if(Pe.write(e,t),u)u({type:"log",level:e,message:t});else console[e==="trace"?"debug":e](t)}function et(e,t){if(!u)return Promise.reject(Error("Not connected to host"));let r=t??30000,n=e.timeout_ms===void 0?{...e,timeout_ms:r}:e,i={...n,trace_context:we({...n.trace_context??{}})},o=ie.getStore();if(o?.active&&o.id!==void 0)i.invocation_context_id=o.id;return new Promise((a,p)=>{h.set(e.id,{resolve:a,reject:p}),u({type:"invoke_capability",id:e.id,request:i}),setTimeout(()=>{if(h.has(e.id))h.delete(e.id),p(Error(`Capability invocation timed out after ${r}ms: ${e.capability}`))},r)})}function tt(e,t){if(!u)throw Error("Not connected to host");u({type:"publish_event",event_name:e,data:t})}var m=0,v,y=null,x=!1,E,se=()=>b(0),z=se,D,ae=(e)=>(u?.(e),Promise.resolve()),j=ae;function re(e){if(v=e,e===void 0)k()}function k(){if(y)clearTimeout(y),y=null}function Te(){if(x)return;if(v===void 0)return;if(m!==0)return;k();let e=Math.max(0,v*1000),t=setTimeout(()=>{y=null,Le()},e);t.unref?.(),y=t}function A(){m++,k()}function S(){if(m=Math.max(0,m-1),m===0)Te()}async function Le(){if(x)return;if(x=!0,D?.(),E)await E.shutdown();await j({type:"lease_exit"}),z()}function nt(){k(),m=0,v=void 0,x=!1,E=void 0,z=se,D=void 0,j=ae}function rt(e){z=e}function ot(){return{inFlight:m,rememberedSecs:v,timerArmed:y!==null,draining:x}}var qe=30000;function Ne(){let e=process.env.NODE_APP_MEMORY_SAMPLE_INTERVAL_MS,t=e?Number.parseInt(e,10):NaN;return Number.isFinite(t)&&t>=1000?t:qe}var g=null,He=ee;function oe(e){e({type:"app_memory",...He()})}function Fe(e){if(g)return;oe(e),g=setInterval(()=>oe(e),Ne()),g.unref?.()}function w(){if(g)clearInterval(g),g=null}var $e=te;async function Be(e,t,r=$e){try{let n=await r(e.path);t({type:"heap_snapshot_response",id:e.id,success:!0,size_bytes:n.size_bytes})}catch{t({type:"heap_snapshot_response",id:e.id,success:!1,error:"heap_snapshot_failed"})}}function ze(e,t){let r=t.indexOf("?"),n=r>=0?t.slice(0,r):t,i=e.split("/"),o=n.split("/"),a=0,p=0;while(a<i.length){if(i[a]==="**")return!0;if(p>=o.length)return!1;if(i[a]!=="*"&&i[a]!==o[p])return!1;a++,p++}return p===o.length}class De{_routes=[];route(e,t,r,n){this._routes.push({method:e,path:t,policy:r,handler:n})}async init(e){}async shutdown(){}async handleRequest(e){if(this._routes.length>0)return this._dispatchRoute(e);return{status:501,headers:{},body:{error:"Not implemented"}}}async _dispatchRoute(e){let t=e.method.toUpperCase(),r=e.path;for(let n of this._routes){if(!(n.method==="*"||n.method.toUpperCase()===t))continue;if(!ze(n.path,r))continue;let o=n.policy.requiredPermissions??[],a=e.caller?.granted_permissions??[],p=o.filter((c)=>!a.includes(c));if(p.length>0)return f.warn(`SDK scope denied: [${p.join(", ")}] missing for ${t} ${r}`),{status:403,headers:{},body:{error:`Missing permissions: ${p.join(", ")}`}};return n.handler(e)}return this.notFound()}async handleEvent(e){}providedCapabilities(){return[]}async handleCapability(e){return{id:e.id,success:!1,payload:{error:"Capability handling not implemented"}}}json(e,t=200){return{status:t,headers:{"Content-Type":"application/json"},body:e}}error(e,t=500){return{status:t,headers:{"Content-Type":"application/json"},body:{error:e}}}notFound(){return this.error("Not found",404)}}function it(e){Z(),ke(e.metadata?.name??"node-app");let t=X({onConnected:(n)=>{f.debug(`Connected to host via ${n}`)},onFrame:(n)=>pe(e,n,r),onFrameError:(n)=>{f.error(`Failed to parse IPC message: ${n}`)},onError:(n)=>{console.error(`[node-app-sdk] Socket error: ${n.message}`),b(1)},onClose:()=>{w(),b(0),f.debug("Socket closed, shutting down")}});function r(n){t.send(n)}u=r,D=()=>{t.stopAccepting()},j=(n)=>t.sendAndFlush(n),process.on("SIGTERM",async()=>{if(!H)return;w(),await e.shutdown(),t.end(),process.exit(0)}),process.on("SIGINT",async()=>{if(!H)return;w(),await e.shutdown(),t.end(),process.exit(0)})}async function pe(e,t,r){switch(E=e,t.type){case"init":{let n=t.config;await e.init(n),r({type:"ready",metadata:e.metadata}),Fe(r);break}case"request":{let{id:n,request:i}=t;A();try{let o=await e.handleRequest(i);r({type:"response",id:n,response:o})}catch(o){r({type:"response",id:n,response:{status:500,headers:{},body:{error:`Internal app error: ${o}`}}})}finally{S()}break}case"event":{let{event:n,lease_secs:i}=t;re(i),A();try{await e.handleEvent(n)}catch(o){f.error(`Event handler error: ${o}`)}finally{S()}break}case"capability_request":{let{id:n,request:i}=t;re(i.lease_secs),A();let o={id:i.invocation_context_id,active:!0};try{let a=await ie.run(o,async()=>{try{return await Ee(i.capability,i.trace_context,()=>e.handleCapability(i))}finally{o.active=!1}});r({type:"capability_response",id:n,response:a})}catch(a){r({type:"capability_response",id:n,response:{id:i.id,success:!1,payload:{error:`Capability handler error: ${a}`}}})}finally{S()}break}case"invoke_capability_result":{let{id:n,response:i}=t,o=h.get(n);if(o)h.delete(n),o.resolve(i);break}case"shutdown":{f.info("Received shutdown signal from host"),w(),await e.shutdown(),b(0);break}case"heap_snapshot_request":{await Be(t,r);break}default:f.warn(`Unknown IPC message type: ${t.type}`)}}async function st(e,t,r){u=r,await pe(e,t,u)}export{De as NodeApp,$e as _captureHeapSnapshotTo,Be as _handleHeapSnapshotRequest,Ze as _resolveCtx,He as _sampleMemory,Je as _testExitWorker,st as _testHandleMessage,ot as _testLeaseState,nt as _testResetLeaseState,Xe as _testRunNodeAppPath,rt as _testSetLeaseExitFn,f as host,Qe as incrementCounter,ke as initAppTelemetry,et as invokeCapability,Ve as openDatabase,tt as publishEvent,it as runNodeApp,Ye as telemetryActive};