@lunora/server 1.0.0-alpha.222 → 1.0.0-alpha.223
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/index.mjs +1 -1
- package/dist/packem_shared/{defineLiveStream-RmfLZq1a.mjs → defineLiveStream-5DXpg7Jy.mjs} +1 -1
- package/dist/packem_shared/httpAction-DplHzcUa.mjs +6 -0
- package/dist/packem_shared/{serveStorageObject-aqBFrLyo.mjs → serveStorageObject-B9GbK4qd.mjs} +1 -1
- package/package.json +4 -4
- package/dist/packem_shared/httpAction-D2S7bQzl.mjs +0 -6
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ACTION_CACHE_DEFAULT_TTL_MS as t,ACTION_CACHE_TABLE as n,actionCacheExtension as i,cacheKeyFor as f,defineActionCache as a}from"./packem_shared/ACTION_CACHE_DEFAULT_TTL_MS-mmP-6BcT.mjs";import{initLunora as d}from"./packem_shared/initLunora-B-7Xs3Qq.mjs";import{isPerDispatchMiddleware as p,tagPerDispatchMiddleware as x}from"./packem_shared/isPerDispatchMiddleware-DDQPatSm.mjs";import{createSecrets as l}from"./packem_shared/createSecrets-D6rLB42U.mjs";import{beginDeferredDeletes as S,flushDeferredDeletes as u,withDeferredDeletes as h}from"./packem_shared/beginDeferredDeletes-DhwFBbvs.mjs";import{beginDeferredSchedules as T,withDeferredSchedules as g}from"./packem_shared/beginDeferredSchedules-C7QLYr6C.mjs";import{DOCUMENT_HISTORY_REDACTED_FIELDS as A,DOCUMENT_HISTORY_TABLE as I,defineDocumentHistory as L,documentHistoryExtension as _}from"./packem_shared/DOCUMENT_HISTORY_REDACTED_FIELDS-B5Zp-7SI.mjs";import{LunoraEnvError as M,defineEnv as P,redactSecrets as b}from"./packem_shared/LunoraEnvError-bkdMu_-N.mjs";import{bindOrm as F,bindTableFacade as O}from"./packem_shared/bindOrm-9fbLRbOb.mjs";import{httpAction as H,httpRoute as N,httpRouter as k,isSafeHeaderValue as w,lastEventId as U,sseEvent as B}from"./packem_shared/httpAction-
|
|
1
|
+
import{ACTION_CACHE_DEFAULT_TTL_MS as t,ACTION_CACHE_TABLE as n,actionCacheExtension as i,cacheKeyFor as f,defineActionCache as a}from"./packem_shared/ACTION_CACHE_DEFAULT_TTL_MS-mmP-6BcT.mjs";import{initLunora as d}from"./packem_shared/initLunora-B-7Xs3Qq.mjs";import{isPerDispatchMiddleware as p,tagPerDispatchMiddleware as x}from"./packem_shared/isPerDispatchMiddleware-DDQPatSm.mjs";import{createSecrets as l}from"./packem_shared/createSecrets-D6rLB42U.mjs";import{beginDeferredDeletes as S,flushDeferredDeletes as u,withDeferredDeletes as h}from"./packem_shared/beginDeferredDeletes-DhwFBbvs.mjs";import{beginDeferredSchedules as T,withDeferredSchedules as g}from"./packem_shared/beginDeferredSchedules-C7QLYr6C.mjs";import{DOCUMENT_HISTORY_REDACTED_FIELDS as A,DOCUMENT_HISTORY_TABLE as I,defineDocumentHistory as L,documentHistoryExtension as _}from"./packem_shared/DOCUMENT_HISTORY_REDACTED_FIELDS-B5Zp-7SI.mjs";import{LunoraEnvError as M,defineEnv as P,redactSecrets as b}from"./packem_shared/LunoraEnvError-bkdMu_-N.mjs";import{bindOrm as F,bindTableFacade as O}from"./packem_shared/bindOrm-9fbLRbOb.mjs";import{httpAction as H,httpRoute as N,httpRouter as k,isSafeHeaderValue as w,lastEventId as U,sseEvent as B}from"./packem_shared/httpAction-DplHzcUa.mjs";import{serveStorageObject as W}from"./packem_shared/serveStorageObject-B9GbK4qd.mjs";import{defineIdentity as Y}from"./packem_shared/defineIdentity-DwkNKwYa.mjs";import{default as J}from"./packem_shared/defineIdentityGuard-Bt8N65Zs.mjs";import{onConnect as Q,onDisconnect as X,onShardInit as q}from"./packem_shared/onConnect-BLRoOpv2.mjs";import{DEFAULT_LIMIT as Z,DEFAULT_MAX_LIMIT as $,clampLimit as ee,defineListArgs as re}from"./packem_shared/DEFAULT_LIMIT-pT_tV8R0.mjs";import{defineLiveStream as te}from"./packem_shared/defineLiveStream-5DXpg7Jy.mjs";import{defineMigration as ie}from"./packem_shared/defineMigration-CXOS0Bvq.mjs";import{defineModule as ae}from"./packem_shared/defineModule-OecXWM3U.mjs";import{defineMutator as de}from"./packem_shared/defineMutator-B4ipDtDR.mjs";import{platformAdmin as pe}from"./packem_shared/platformAdmin-kczXQme8.mjs";import{c as ce,d as le,a as Ee,b as Se,e as ue,f as he,g as De,h as Te,i as ge,j as Re,k as Ae,m as Ie}from"./packem_shared/plugin-Bm9wIpiI.mjs";import{PRESENCE_DEFAULT_TTL_MS as _e,PRESENCE_TABLE as Ce,definePresence as Me,presenceExtension as Pe}from"./packem_shared/PRESENCE_DEFAULT_TTL_MS-DFpy5J8G.mjs";import{protectPublic as ye}from"./packem_shared/protectPublic-Bi5_95aP.mjs";import{onQueryChange as Oe}from"./packem_shared/onQueryChange-iuLzmyPs.mjs";import{defineRoom as He}from"./packem_shared/defineRoom-CoGi-xwm.mjs";import{createServices as ke}from"./packem_shared/createServices-IJvoqi0e.mjs";import{defineShape as Ue}from"./packem_shared/defineShape-CwKm5KLp.mjs";import{defineWebSocket as Ve}from"./packem_shared/defineWebSocket-BHoy6_ox.mjs";import{onWhisper as je}from"./packem_shared/onWhisper-CfDbFLQh.mjs";import{LunoraError as Ge}from"@lunora/errors";import{cronJobs as Ke}from"@lunora/scheduler";import{ValidationError as Xe,v as qe}from"@lunora/values";import{allowAll as Ze,deny as $e,isDeny as er,toWhereInput as rr}from"./packem_shared/allowAll-DkRAgItV.mjs";import{asBucketStorage as tr}from"./packem_shared/asBucketStorage-DoGYOjq3.mjs";import{assertShapesDeclareReadPolicies as ir,buildRlsReadRegistry as fr,composeShapeReadWhere as ar}from"./packem_shared/assertShapesDeclareReadPolicies-Bg4Ter7Q.mjs";import{buildMaskRegistry as dr}from"./packem_shared/buildMaskRegistry-DpWMtalG.mjs";import{createPolicyDsl as pr,definePermission as xr,definePolicies as cr,definePolicy as lr,defineRole as Er}from"./packem_shared/createPolicyDsl-BZa6SqLJ.mjs";import{defineStorageRule as ur,defineStorageRules as hr}from"./packem_shared/defineStorageRule-Dv4nJE0H.mjs";import{mask as Tr}from"./packem_shared/mask-D-jRCAhy.mjs";import{r as Rr}from"./packem_shared/middleware-3ySZVrpt.mjs";import{storageRules as Ir}from"./packem_shared/storageRules-CBLioxF7.mjs";const e="0.0.0";export{t as ACTION_CACHE_DEFAULT_TTL_MS,n as ACTION_CACHE_TABLE,Z as DEFAULT_LIMIT,$ as DEFAULT_MAX_LIMIT,A as DOCUMENT_HISTORY_REDACTED_FIELDS,I as DOCUMENT_HISTORY_TABLE,M as LunoraEnvError,Ge as LunoraError,_e as PRESENCE_DEFAULT_TTL_MS,Ce as PRESENCE_TABLE,e as VERSION,Xe as ValidationError,i as actionCacheExtension,Ze as allowAll,tr as asBucketStorage,ir as assertShapesDeclareReadPolicies,S as beginDeferredDeletes,T as beginDeferredSchedules,F as bindOrm,O as bindTableFacade,dr as buildMaskRegistry,fr as buildRlsReadRegistry,f as cacheKeyFor,ee as clampLimit,ce as composePluginMiddleware,ar as composeShapeReadWhere,pr as createPolicyDsl,l as createSecrets,ke as createServices,Ke as cronJobs,a as defineActionCache,le as defineAggregateIndex,Ee as defineComponent,L as defineDocumentHistory,P as defineEnv,Y as defineIdentity,J as defineIdentityGuard,re as defineListArgs,te as defineLiveStream,ie as defineMigration,ae as defineModule,de as defineMutator,xr as definePermission,Se as definePlugin,cr as definePolicies,lr as definePolicy,Me as definePresence,ue as defineRankIndex,Er as defineRole,He as defineRoom,he as defineSchema,De as defineSchemaExtension,Ue as defineShape,ur as defineStorageRule,hr as defineStorageRules,Te as defineTable,ge as defineVectorIndex,Ve as defineWebSocket,$e as deny,_ as documentHistoryExtension,u as flushDeferredDeletes,H as httpAction,N as httpRoute,k as httpRouter,Re as indexFieldsFromSchema,d as initLunora,Ae as installPlugins,er as isDeny,p as isPerDispatchMiddleware,w as isSafeHeaderValue,U as lastEventId,Tr as mask,Ie as mergeSchemaExtension,Q as onConnect,X as onDisconnect,Oe as onQueryChange,q as onShardInit,je as onWhisper,pe as platformAdmin,Pe as presenceExtension,ye as protectPublic,b as redactSecrets,Rr as rls,W as serveStorageObject,B as sseEvent,Ir as storageRules,x as tagPerDispatchMiddleware,rr as toWhereInput,qe as v,h as withDeferredDeletes,g as withDeferredSchedules};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as T,isLunoraError as $}from"@lunora/errors";import{isStringValidator as S,parseValidatorMap as b}from"@lunora/values";import{httpAction as m}from"./httpAction-
|
|
1
|
+
import{LunoraError as T,isLunoraError as $}from"@lunora/errors";import{isStringValidator as S,parseValidatorMap as b}from"@lunora/values";import{httpAction as m}from"./httpAction-DplHzcUa.mjs";const L="/_lunora/live/connect",R="/_lunora/live/control",I="room:",P="__lunora_socket__:",k=256,C=e=>`/live/${e}/connect`,j=e=>`/live/${e}/control`,A=/^[A-Za-z]\w*$/u,E=e=>A.test(e),N=e=>`${e}:`.startsWith(I)||`${e}:`.startsWith(P),D=(e,r,n)=>[e,...r.map(a=>{const s=n[a];if(typeof s!="string")throw new TypeError(`live topic "${e}" needs a string key.${a}`);return encodeURIComponent(s)})].join(":"),g=(e,r)=>{if(e.length>k)return;const[n,...a]=e.split(":");if(n===void 0||!Object.hasOwn(r,n))return;const s=r[n];if(a.length!==s.length)return;const d={};try{for(const[l,p]of s.entries())d[p]=decodeURIComponent(a[l]);return D(n,s,d)===e?{key:d,name:n}:void 0}catch{return}},B=async e=>{try{const r=await e.json();return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:void 0}catch{return}},w=e=>Response.json({code:"FORBIDDEN_TOPIC",error:`subscribe to "${e}" was denied`},{status:403}),h=e=>Response.json({code:"BAD_REQUEST",error:e},{status:400}),K=(e,r)=>{for(const[n,a]of Object.entries(r)){if(!E(n))throw new TypeError(`defineLiveStream("${e}"): topic name "${n}" must be a plain identifier (letters, digits and "_", starting with a letter)`);if(N(n))throw new TypeError(`defineLiveStream("${e}"): topic name "${n}" would encode into a reserved topic prefix`);for(const[s,d]of Object.entries(a.key??{})){if(!E(s))throw new TypeError(`defineLiveStream("${e}"): key field "${n}.${s}" must be a plain identifier`);if(!S(d))throw new TypeError(`defineLiveStream("${e}"): key field "${n}.${s}" must be a string validator (v.string(), v.id(), v.literal(…))`)}}},U=(e,r)=>new T("BAD_REQUEST",`publish to "${e}" was refused: ${r instanceof Error?r.message:String(r)}`,{status:400}),H=e=>{K(e.id,e.topics);const r=C(e.id),n=j(e.id),a=Object.fromEntries(Object.entries(e.topics).map(([o,i])=>[o,Object.keys(i.key??{})])),s=o=>{const i=g(o,a),t=i===void 0?void 0:e.topics[i.name];if(!(i===void 0||t===void 0))try{return{declaration:t,key:b(t.key??{},i.key,"key"),name:i.name}}catch{return}},d=(o,i)=>{const t=s(o);if(t===void 0)throw new T("BAD_REQUEST",`"${o}" is not a topic declared by live stream "${e.id}"`,{status:400});const{declaration:c}=t;try{return b({payload:c.payload},{payload:i},"topic").payload}catch(u){throw U(o,u)}},l=async(o,i)=>{const t=s(i);if(t===void 0)return!1;if(!e.onSubscribe)return e.allowAnonymousControl===!0&&o.auth.userId===null;try{return await e.onSubscribe({ctx:o,key:t.key,raw:i,topic:t.name})===!0}catch(c){return console.error("[lunora] live subscribe authorization threw; denying:",c),!1}},p=m(async(o,i)=>{const t=new URL(i.url).searchParams.get("shard")??void 0;return o.fetchShard(t,L,{method:"GET"})}),_=m(async(o,i)=>{const t=await B(i);if(!t)return h("Expected a JSON object body");const{action:c}=t,u=typeof t.topic=="string"?t.topic:void 0;if(u===void 0||u.length===0)return h("topic is required");if(c!=="subscribe"&&c!=="unsubscribe")return h("action must be subscribe or unsubscribe");const y=typeof t.shardKey=="string"?t.shardKey:void 0,O=y===void 0?o:{...o,...o.forShard(y)};if(c==="subscribe"&&!await l(O,u))return w(u);const f=o.fetchShard(y,R,{body:JSON.stringify({...t,stream:e.id}),method:"POST"});if(c!=="subscribe")return f;try{return await f}catch(v){if($(v)&&v.code==="FORBIDDEN_SHARD")return w(u);throw v}});return{connect:p,connectPath:r,control:_,controlPath:n,id:e.id,topics:e.topics,validatePublish:d}};export{H as defineLiveStream};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{LunoraError as b,toErrorBody as S,isLunoraError as k}from"@lunora/errors";import{parseValidatorMap as w,ValidationError as L}from"@lunora/values";import{encodeWire as q}from"@lunora/wire";import{Hono as C}from"hono";import{a as R}from"./apply-output-C5wZ5EAL.mjs";const W=e=>async r=>e(r.get("lunora"),r.req.raw),G=()=>{const e=new C;return e.use("*",async(r,o)=>{const n=r.env.__lunoraCtx;if(!n)throw new b("INTERNAL_SERVER_ERROR","HttpActionCtx was not injected — mount httpRouter() on createWorker(), which supplies it per request.");r.set("lunora",n),await o()}),e},O=e=>e.kind==="optional"?e._meta?.inner??e:e,g=(e,r)=>{switch(e){case"bigint":try{return BigInt(r)}catch{return r}case"boolean":return r==="true"||r==="1"?!0:r==="false"||r==="0"?!1:r;case"number":return r===""?Number.NaN:Number(r);default:return r}},x=(e,r,o)=>{const n=O(e);if(n.kind==="array"){const a=r.req.queries(o);if(a===void 0)return;const i=n._meta?.inner;return a.map(d=>g(i?.kind??"string",d))}const t=r.req.query(o);return t===void 0?void 0:g(n.kind,t)},T=(e,r)=>{const o={};for(const n of Object.keys(e)){const t=e[n];t&&(o[n]=x(t,r,n))}return w(e,o,"searchParams")},N=(e,r)=>{const o=r.req.param(),n={};for(const t of Object.keys(e)){const a=e[t];if(!a)continue;const i=o[t];n[t]=i===void 0?void 0:g(O(a).kind,i)}return w(e,n,"params")},H=async(e,r)=>{let o;try{o=await r.req.json()}catch{throw new b("BAD_REQUEST","Invalid JSON body")}if(typeof o!="object"||o===null||Array.isArray(o))throw new b("BAD_REQUEST","Expected a JSON object body");return w(e,o,"body")},A=e=>{if(e instanceof L)return Response.json({code:"BAD_REQUEST",error:e.message},{status:400});if(k(e)){const{body:r,redacted:o,status:n}=S(e,{fallbackCode:"INTERNAL_SERVER_ERROR",redactedMessage:"Internal error"});return o&&console.error("[lunora] http action error (redacted on the wire):",e),Response.json({code:r.code,error:r.message,...r.why===void 0?{}:{why:r.why}},{status:n})}throw e},j=(e,r)=>{const{method:o}=r.req;if(!(o===e.method||e.method==="GET"&&o==="HEAD"))return Response.json({code:"METHOD_NOT_ALLOWED",error:`${o} is not allowed on this route (declared as ${e.method})`},{headers:{allow:e.method},status:405})},I=(e,r)=>async o=>{const n=j(e,o);if(n)return n;try{const t=o.get("lunora"),a=Object.keys(e.searchParams).length>0?T(e.searchParams,o):{},i=Object.keys(e.params).length>0?N(e.params,o):{},d=Object.keys(e.body).length>0?await H(e.body,o):{},h=await r({body:d,ctx:t,params:i,searchParams:a}),s=e.output?R(e.output,h):h,c={};e.cacheControl&&(c["cache-control"]=e.cacheControl),e.cacheTag&&(c["cache-tag"]=e.cacheTag),e.vary&&(c.vary=e.vary);const y=Object.keys(c).length>0;return s===void 0?new Response(null,{headers:y?c:void 0,status:204}):Response.json(s,{headers:y?c:void 0})}catch(t){return A(t)}},v={"cache-control":"no-cache, no-transform","content-type":"text/event-stream; charset=utf-8","x-accel-buffering":"no"},z=e=>{const r=e.headers.get("last-event-id");if(r!==null)return r===""?void 0:r;const o=new URL(e.url).searchParams.get("lastEventId");return o===null||o===""?void 0:o},P=Symbol.for("@lunora/server/sse-event"),K=e=>({[P]:!0,data:e.data,id:e.id}),D=e=>typeof e=="object"&&e!==null&&e[P]===!0,B=e=>!(e.includes("\r")||e.includes(`
|
|
2
|
+
`)||e.includes("\0")),E=(e,r,o)=>{const n=JSON.stringify(r===void 0?q(e):e);if(o!==void 0&&!B(o))throw new b("INTERNAL","sseEvent id must not contain CR, LF or NUL");const t=o===void 0?"":`id: ${o}
|
|
3
|
+
`,a=r?`event: ${r}
|
|
4
|
+
`:"";return`${t}${a}data: ${n}
|
|
5
|
+
|
|
6
|
+
`},V=(e,r)=>{if(D(r)){const o=e?R(e,r.data):r.data;return E(o,void 0,r.id)}return E(e?R(e,r):r)},$=(e,r)=>(async o=>{const n=j(e,o);if(n)return n;let t,a;try{t=Object.keys(e.searchParams).length>0?T(e.searchParams,o):{},a=Object.keys(e.params).length>0?N(e.params,o):{}}catch(m){return A(m)}const i=o.get("lunora"),d=o.req.raw,h=new TextEncoder,s=new AbortController;if(d.signal.aborted)return s.abort(),new Response("",{headers:v});const c=()=>{s.abort()};d.signal.addEventListener("abort",c,{once:!0});const y=new ReadableStream({cancel(){d.signal.removeEventListener("abort",c),s.abort()},async start(m){try{const f=r({ctx:i,params:a,request:d,searchParams:t,signal:s.signal});for await(const p of f){if(s.signal.aborted)break;m.enqueue(h.encode(V(e.output,p)))}s.signal.aborted||m.enqueue(h.encode(E({},"complete")))}catch(f){const{body:p,redacted:_}=S(f,{fallbackCode:"INTERNAL_SERVER_ERROR",redactedMessage:"Internal error"});_&&console.error("[lunora] unhandled stream handler error:",f),s.signal.aborted||m.enqueue(h.encode(E({code:p.code,message:p.message,...p.why===void 0?{}:{why:p.why}},"error")))}finally{d.signal.removeEventListener("abort",c);try{m.close()}catch{}}}});return new Response(y,{headers:v})}),u=e=>({body:r=>u({...e,body:{...e.body,...r}}),cacheControl:r=>u({...e,cacheControl:r}),cacheTag:r=>u({...e,cacheTag:r}),handler:r=>I(e,r),output:r=>u({...e,output:r}),params:r=>u({...e,params:{...e.params,...r}}),searchParams:r=>u({...e,searchParams:{...e.searchParams,...r}}),stream:r=>$(e,r),vary:r=>u({...e,vary:r})}),l=e=>r=>u({body:{},method:e,params:{},path:r,searchParams:{}}),X={delete:l("DELETE"),get:l("GET"),head:l("HEAD"),options:l("OPTIONS"),patch:l("PATCH"),post:l("POST"),put:l("PUT")};export{W as httpAction,X as httpRoute,G as httpRouter,B as isSafeHeaderValue,z as lastEventId,K as sseEvent};
|
package/dist/packem_shared/{serveStorageObject-aqBFrLyo.mjs → serveStorageObject-B9GbK4qd.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isSafeHeaderValue as b}from"./httpAction-
|
|
1
|
+
import{isSafeHeaderValue as b}from"./httpAction-DplHzcUa.mjs";const N=/^bytes=(\d*)-(\d*)$/,g=t=>t.startsWith('"')||t.startsWith('W/"')?t:`"${t}"`,R=/(?:W\/)?"[^"]*"/g,p=t=>t.startsWith("W/")?t.slice(2):t,S=(t,e)=>{if(t.trim()==="*")return!0;const n=p(g(e));return(t.match(R)??[]).some(s=>p(s)===n)},m=(t,e)=>{if(t===null)return{kind:"full"};const n=N.exec(t.trim());if(!n)return{kind:"full"};const s=n[1]??"",a=n[2]??"";if(s===""&&a==="")return{kind:"full"};let r,o;if(s===""){const u=Number(a);if(u===0)return{kind:"unsatisfiable"};r=Math.max(0,e-u),o=e-1}else r=Number(s),o=a===""?e-1:Math.min(Number(a),e-1);return r>o||r>=e?{kind:"unsatisfiable"}:{end:o,kind:"partial",start:r}},v=new Set(["audio/mpeg","audio/ogg","audio/wav","image/apng","image/avif","image/gif","image/jpeg","image/png","image/webp","video/mp4","video/webm"]),w=(t,e)=>{const n=t.httpMetadata?.contentType,s=n!==void 0&&b(n)?n:"application/octet-stream",a={"accept-ranges":"bytes","cache-control":e,"content-type":s,etag:g(t.etag),"x-content-type-options":"nosniff"};return v.has(s.split(";")[0]?.trim().toLowerCase()??"")||(a["content-disposition"]="attachment"),t.sha256Base64!==void 0&&(a["repr-digest"]=`sha-256=:${t.sha256Base64}:`),a},y=t=>m(t,0).kind==="full",h=async(t,e,n)=>{const s=await t.storage.download(e);return s?new Response(s.body,{headers:{...w(s,n),"content-length":String(s.size)},status:200}):new Response("Not Found",{status:404})},T=async(t,e,n)=>{try{return await t({key:e,request:n})===!0}catch{return!1}},W=async(t,e,n,s,a="no-store")=>{if(!await T(s,e,n))return new Response("Forbidden",{status:403});const r=n.headers.get("if-none-match");let o;if(r!==null){const d=await t.storage.head(e);if(!d)return new Response("Not Found",{status:404});if(S(r,d.etag))return new Response(void 0,{headers:{"cache-control":a,etag:g(d.etag)},status:304});o=d}const u=n.headers.get("range");if(y(u))return h(t,e,a);const c=o??await t.storage.head(e);if(!c)return new Response("Not Found",{status:404});const i=m(u,c.size);if(i.kind==="unsatisfiable")return new Response("Range Not Satisfiable",{headers:{"accept-ranges":"bytes","content-range":`bytes */${String(c.size)}`,"content-type":"text/plain; charset=utf-8",etag:g(c.etag)},status:416});if(i.kind==="full")return h(t,e,a);const f=i.end-i.start+1,l=await t.storage.download(e,{range:{length:f,offset:i.start}});return l?new Response(l.body,{headers:{...w(c,a),"content-length":String(f),"content-range":`bytes ${String(i.start)}-${String(i.end)}/${String(c.size)}`},status:206}):new Response("Not Found",{status:404})};export{W as serveStorageObject};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/server",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.223",
|
|
4
4
|
"description": "Server primitives for Lunora: defineSchema, defineTable, query, mutation, and action",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"backend",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
74
|
-
"@lunora/scheduler": "1.0.0-alpha.
|
|
75
|
-
"@lunora/shard-engine": "1.0.0-alpha.
|
|
76
|
-
"@lunora/values": "1.0.0-alpha.
|
|
74
|
+
"@lunora/scheduler": "1.0.0-alpha.140",
|
|
75
|
+
"@lunora/shard-engine": "1.0.0-alpha.145",
|
|
76
|
+
"@lunora/values": "1.0.0-alpha.75",
|
|
77
77
|
"@lunora/wire": "1.0.0-alpha.1",
|
|
78
78
|
"drizzle-orm": "^0.45.3",
|
|
79
79
|
"hono": "^4.13.13"
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{LunoraError as b,toErrorBody as S,isLunoraError as k}from"@lunora/errors";import{parseValidatorMap as v,ValidationError as L}from"@lunora/values";import{encodeWire as q}from"@lunora/wire";import{Hono as C}from"hono";import{a as R}from"./apply-output-C5wZ5EAL.mjs";const W=e=>async r=>e(r.get("lunora"),r.req.raw),G=()=>{const e=new C;return e.use("*",async(r,o)=>{const n=r.env.__lunoraCtx;if(!n)throw new b("INTERNAL_SERVER_ERROR","HttpActionCtx was not injected — mount httpRouter() on createWorker(), which supplies it per request.");r.set("lunora",n),await o()}),e},O=e=>e.kind==="optional"?e._meta?.inner??e:e,g=(e,r)=>{switch(e){case"bigint":try{return BigInt(r)}catch{return r}case"boolean":return r==="true"||r==="1"?!0:r==="false"||r==="0"?!1:r;case"number":return r===""?Number.NaN:Number(r);default:return r}},x=(e,r,o)=>{const n=O(e);if(n.kind==="array"){const a=r.req.queries(o);if(a===void 0)return;const i=n._meta?.inner;return a.map(d=>g(i?.kind??"string",d))}const t=r.req.query(o);return t===void 0?void 0:g(n.kind,t)},T=(e,r)=>{const o={};for(const n of Object.keys(e)){const t=e[n];t&&(o[n]=x(t,r,n))}return v(e,o,"searchParams")},N=(e,r)=>{const o=r.req.param(),n={};for(const t of Object.keys(e)){const a=e[t];if(!a)continue;const i=o[t];n[t]=i===void 0?void 0:g(O(a).kind,i)}return v(e,n,"params")},H=async(e,r)=>{let o;try{o=await r.req.json()}catch{throw new b("BAD_REQUEST","Invalid JSON body")}if(typeof o!="object"||o===null||Array.isArray(o))throw new b("BAD_REQUEST","Expected a JSON object body");return v(e,o,"body")},A=e=>{if(e instanceof L)return Response.json({code:"BAD_REQUEST",error:e.message},{status:400});if(k(e)){const{body:r,redacted:o,status:n}=S(e,{fallbackCode:"INTERNAL_SERVER_ERROR",redactedMessage:"Internal error"});return o&&console.error("[lunora] http action error (redacted on the wire):",e),Response.json({code:r.code,error:r.message},{status:n})}throw e},j=(e,r)=>{const{method:o}=r.req;if(!(o===e.method||e.method==="GET"&&o==="HEAD"))return Response.json({code:"METHOD_NOT_ALLOWED",error:`${o} is not allowed on this route (declared as ${e.method})`},{headers:{allow:e.method},status:405})},I=(e,r)=>async o=>{const n=j(e,o);if(n)return n;try{const t=o.get("lunora"),a=Object.keys(e.searchParams).length>0?T(e.searchParams,o):{},i=Object.keys(e.params).length>0?N(e.params,o):{},d=Object.keys(e.body).length>0?await H(e.body,o):{},h=await r({body:d,ctx:t,params:i,searchParams:a}),s=e.output?R(e.output,h):h,c={};e.cacheControl&&(c["cache-control"]=e.cacheControl),e.cacheTag&&(c["cache-tag"]=e.cacheTag),e.vary&&(c.vary=e.vary);const p=Object.keys(c).length>0;return s===void 0?new Response(null,{headers:p?c:void 0,status:204}):Response.json(s,{headers:p?c:void 0})}catch(t){return A(t)}},w={"cache-control":"no-cache, no-transform","content-type":"text/event-stream; charset=utf-8","x-accel-buffering":"no"},z=e=>{const r=e.headers.get("last-event-id");if(r!==null)return r===""?void 0:r;const o=new URL(e.url).searchParams.get("lastEventId");return o===null||o===""?void 0:o},P=Symbol.for("@lunora/server/sse-event"),K=e=>({[P]:!0,data:e.data,id:e.id}),D=e=>typeof e=="object"&&e!==null&&e[P]===!0,B=e=>!(e.includes("\r")||e.includes(`
|
|
2
|
-
`)||e.includes("\0")),E=(e,r,o)=>{const n=JSON.stringify(r===void 0?q(e):e);if(o!==void 0&&!B(o))throw new b("INTERNAL","sseEvent id must not contain CR, LF or NUL");const t=o===void 0?"":`id: ${o}
|
|
3
|
-
`,a=r?`event: ${r}
|
|
4
|
-
`:"";return`${t}${a}data: ${n}
|
|
5
|
-
|
|
6
|
-
`},V=(e,r)=>{if(D(r)){const o=e?R(e,r.data):r.data;return E(o,void 0,r.id)}return E(e?R(e,r):r)},$=(e,r)=>(async o=>{const n=j(e,o);if(n)return n;let t,a;try{t=Object.keys(e.searchParams).length>0?T(e.searchParams,o):{},a=Object.keys(e.params).length>0?N(e.params,o):{}}catch(m){return A(m)}const i=o.get("lunora"),d=o.req.raw,h=new TextEncoder,s=new AbortController;if(d.signal.aborted)return s.abort(),new Response("",{headers:w});const c=()=>{s.abort()};d.signal.addEventListener("abort",c,{once:!0});const p=new ReadableStream({cancel(){d.signal.removeEventListener("abort",c),s.abort()},async start(m){try{const f=r({ctx:i,params:a,request:d,searchParams:t,signal:s.signal});for await(const y of f){if(s.signal.aborted)break;m.enqueue(h.encode(V(e.output,y)))}s.signal.aborted||m.enqueue(h.encode(E({},"complete")))}catch(f){const{body:y,redacted:_}=S(f,{fallbackCode:"INTERNAL_SERVER_ERROR",redactedMessage:"Internal error"});_&&console.error("[lunora] unhandled stream handler error:",f),s.signal.aborted||m.enqueue(h.encode(E({code:y.code,message:y.message},"error")))}finally{d.signal.removeEventListener("abort",c);try{m.close()}catch{}}}});return new Response(p,{headers:w})}),u=e=>({body:r=>u({...e,body:{...e.body,...r}}),cacheControl:r=>u({...e,cacheControl:r}),cacheTag:r=>u({...e,cacheTag:r}),handler:r=>I(e,r),output:r=>u({...e,output:r}),params:r=>u({...e,params:{...e.params,...r}}),searchParams:r=>u({...e,searchParams:{...e.searchParams,...r}}),stream:r=>$(e,r),vary:r=>u({...e,vary:r})}),l=e=>r=>u({body:{},method:e,params:{},path:r,searchParams:{}}),X={delete:l("DELETE"),get:l("GET"),head:l("HEAD"),options:l("OPTIONS"),patch:l("PATCH"),post:l("POST"),put:l("PUT")};export{W as httpAction,X as httpRoute,G as httpRouter,B as isSafeHeaderValue,z as lastEventId,K as sseEvent};
|