@lunora/runtime 1.0.0-alpha.177 → 1.0.0-alpha.178

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.d.mts CHANGED
@@ -895,6 +895,11 @@ declare const applyJurisdiction: (namespace: ShardNamespaceLike, jurisdiction?:
895
895
  * advisory and only the *creating* resolution can honour it, so it is safe to
896
896
  * pass on every call and never safe to depend on: callers must behave
897
897
  * identically when the shard turns out to live somewhere else entirely.
898
+ *
899
+ * A key carrying {@link LUNORA_ROLE_PREFIX} is refused with a 400 (the platform
900
+ * contract refuses it too): in an app that merges its Durable Object classes,
901
+ * those names belong to the scheduler and the shard registry. Every caller's key
902
+ * is checked — the framework's own role names reach here unprefixed.
898
903
  */
899
904
  declare const resolveShard: (namespace: ShardNamespaceInput, shardKey: string, locationHint?: RegionHint) => ResolvedShard;
900
905
  /**
package/dist/index.d.ts CHANGED
@@ -895,6 +895,11 @@ declare const applyJurisdiction: (namespace: ShardNamespaceLike, jurisdiction?:
895
895
  * advisory and only the *creating* resolution can honour it, so it is safe to
896
896
  * pass on every call and never safe to depend on: callers must behave
897
897
  * identically when the shard turns out to live somewhere else entirely.
898
+ *
899
+ * A key carrying {@link LUNORA_ROLE_PREFIX} is refused with a 400 (the platform
900
+ * contract refuses it too): in an app that merges its Durable Object classes,
901
+ * those names belong to the scheduler and the shard registry. Every caller's key
902
+ * is checked — the framework's own role names reach here unprefixed.
898
903
  */
899
904
  declare const resolveShard: (namespace: ShardNamespaceInput, shardKey: string, locationHint?: RegionHint) => ResolvedShard;
900
905
  /**
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{declareAppJurisdiction as t}from"./packem_shared/declareAppJurisdiction-DEba2p42.mjs";import{BACKUP_KEY_PREFIX as s,backupManifestKey as i,backupObjectKey as n,backupObjectKeyOfManifest as p,isBackupManifestEntry as c,isBackupManifestKey as m,normalizeBackupPrefix as f}from"./packem_shared/BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toAirbyteMessages as R,toFivetranResponse as x}from"./packem_shared/toAirbyteMessages-2d_iJXPf.mjs";import{composeWorker as l,createLunoraHandler as d,createWorker as u,defineRpcEnvelope as _,resolveLunoraOptions as k,withFrameworkWorker as y}from"./packem_shared/composeWorker-D4DrmOnY.mjs";import{createCrossShardRelationCapabilities as O}from"./packem_shared/createCrossShardRelationCapabilities-BiXSW10v.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as A,SHARD_REGISTRY_DO_NAME as L,createDynamicShardRegistry as T}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BSKqUsWS.mjs";import{LunoraError as H,toErrorResponse as P}from"./packem_shared/LunoraError-DksAgIpa.mjs";import{c as v,a as I,d as D,r as M,b as F,s as N,w as G}from"./packem_shared/export-tap-CAyZ2TWC.mjs";import{HEALTH_PATH as U,HEALTH_READY_PATH as B,buildHealthRoutes as Y,d1Probe as w,durableObjectProbe as z,presenceProbe as X}from"./packem_shared/HEALTH_PATH-D0i8LhwT.mjs";import{LOG_ARCHIVE_PATH as V,resolveLogArchiveFromEnv as W}from"./packem_shared/LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{memoizeIdentity as J,memoizeIdentityPerRequest as Q}from"./packem_shared/memoizeIdentity-DnOj3QRi.mjs";import{e as $,a as ee}from"./packem_shared/observability-DgurIZIR.mjs";import{analyticsEngineSink as oe,combineSinks as te,consoleSink as ae,otlpSink as se,pipelineLogSink as ie,sentrySink as ne,webhookSink as pe}from"./packem_shared/analyticsEngineSink-DQyRIP6N.mjs";import{D as me,c as fe}from"./packem_shared/pipeline-log-reader-C-nuWG_e.mjs";import{createQueryCoordinator as Re,createStaticShardRegistry as xe}from"./packem_shared/createQueryCoordinator-BkZPoV26.mjs";import{applyJurisdiction as le,resolveShard as de}from"./packem_shared/applyJurisdiction-C0ddU7Tg.mjs";import{a as _e,r as ke,b as ye}from"./packem_shared/rest-cache-CmHN871W.mjs";import{a as Oe,b as be,c as Ae,r as Le}from"./packem_shared/rest-routes-D3ShCTHh.mjs";import{decorateResponse as he,enforceOrigin as He,handleCorsPreflight as Pe,resolveSecurity as ge}from"./packem_shared/decorateResponse-CRrFNW1v.mjs";import{createShardClient as Ie}from"./packem_shared/createShardClient-BrzRLSs9.mjs";import{STORAGE_UPLOAD_MAX_BODY_BYTES as Me}from"./packem_shared/STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Ne}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ke}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as Be,routeIdentityResolvers as Ye}from"./packem_shared/composeIdentityResolvers-BHZ4jH8o.mjs";const e="0.0.0";export{s as BACKUP_KEY_PREFIX,me as DEFAULT_LOG_COLUMNS,A as DEFAULT_REGISTRY_CACHE_TTL_MS,U as HEALTH_PATH,B as HEALTH_READY_PATH,Ne as LOG_ARCHIVE_NOT_CONFIGURED,V as LOG_ARCHIVE_PATH,H as LunoraError,Ke as NOOP_EXECUTION_CONTEXT,L as SHARD_REGISTRY_DO_NAME,Me as STORAGE_UPLOAD_MAX_BODY_BYTES,e as VERSION,oe as analyticsEngineSink,le as applyJurisdiction,_e as applyRestCache,Oe as argsFromQuery,i as backupManifestKey,n as backupObjectKey,p as backupObjectKeyOfManifest,Y as buildHealthRoutes,be as buildRestRoutes,te as combineSinks,Be as composeIdentityResolvers,l as composeWorker,ae as consoleSink,O as createCrossShardRelationCapabilities,T as createDynamicShardRegistry,v as createKvCursorStore,d as createLunoraHandler,I as createMemoryCursorStore,fe as createPipelineLogReader,Re as createQueryCoordinator,Ae as createRestRateLimit,Ie as createShardClient,xe as createStaticShardRegistry,u as createWorker,w as d1Probe,t as declareAppJurisdiction,he as decorateResponse,D as defineExportSink,_ as defineRpcEnvelope,z as durableObjectProbe,$ as emitLogEvent,ee as emitRpcEvent,He as enforceOrigin,Pe as handleCorsPreflight,c as isBackupManifestEntry,m as isBackupManifestKey,J as memoizeIdentity,Q as memoizeIdentityPerRequest,f as normalizeBackupPrefix,se as otlpSink,ie as pipelineLogSink,X as presenceProbe,M as r2Sink,ke as requestCarriesCredentials,W as resolveLogArchiveFromEnv,k as resolveLunoraOptions,ge as resolveSecurity,de as resolveShard,ye as restCacheHeaders,Le as restSurfaceFromRegistry,Ye as routeIdentityResolvers,F as runExportTap,N as sanitizeChange,ne as sentrySink,R as toAirbyteMessages,P as toErrorResponse,x as toFivetranResponse,G as webhookExportSink,pe as webhookSink,y as withFrameworkWorker};
1
+ import{declareAppJurisdiction as t}from"./packem_shared/declareAppJurisdiction-DEba2p42.mjs";import{BACKUP_KEY_PREFIX as s,backupManifestKey as i,backupObjectKey as n,backupObjectKeyOfManifest as p,isBackupManifestEntry as c,isBackupManifestKey as m,normalizeBackupPrefix as f}from"./packem_shared/BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toAirbyteMessages as R,toFivetranResponse as x}from"./packem_shared/toAirbyteMessages-2d_iJXPf.mjs";import{composeWorker as l,createLunoraHandler as d,createWorker as u,defineRpcEnvelope as _,resolveLunoraOptions as k,withFrameworkWorker as y}from"./packem_shared/composeWorker-CnQobr-f.mjs";import{createCrossShardRelationCapabilities as O}from"./packem_shared/createCrossShardRelationCapabilities-BiXSW10v.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as A,SHARD_REGISTRY_DO_NAME as L,createDynamicShardRegistry as T}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-CdACWUQW.mjs";import{LunoraError as H,toErrorResponse as P}from"./packem_shared/LunoraError-DksAgIpa.mjs";import{c as v,a as I,d as D,r as M,b as F,s as N,w as G}from"./packem_shared/export-tap-CAyZ2TWC.mjs";import{HEALTH_PATH as U,HEALTH_READY_PATH as B,buildHealthRoutes as Y,d1Probe as w,durableObjectProbe as z,presenceProbe as X}from"./packem_shared/HEALTH_PATH-CAX2UeFy.mjs";import{LOG_ARCHIVE_PATH as V,resolveLogArchiveFromEnv as W}from"./packem_shared/LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{memoizeIdentity as J,memoizeIdentityPerRequest as Q}from"./packem_shared/memoizeIdentity-DnOj3QRi.mjs";import{e as $,a as ee}from"./packem_shared/observability-DgurIZIR.mjs";import{analyticsEngineSink as oe,combineSinks as te,consoleSink as ae,otlpSink as se,pipelineLogSink as ie,sentrySink as ne,webhookSink as pe}from"./packem_shared/analyticsEngineSink-DQyRIP6N.mjs";import{D as me,c as fe}from"./packem_shared/pipeline-log-reader-C-nuWG_e.mjs";import{createQueryCoordinator as Re,createStaticShardRegistry as xe}from"./packem_shared/createQueryCoordinator-CXdh_RxT.mjs";import{applyJurisdiction as le,resolveShard as de}from"./packem_shared/applyJurisdiction-D4vryLhj.mjs";import{a as _e,r as ke,b as ye}from"./packem_shared/rest-cache-CmHN871W.mjs";import{a as Oe,b as be,c as Ae,r as Le}from"./packem_shared/rest-routes-D3ShCTHh.mjs";import{decorateResponse as he,enforceOrigin as He,handleCorsPreflight as Pe,resolveSecurity as ge}from"./packem_shared/decorateResponse-CRrFNW1v.mjs";import{createShardClient as Ie}from"./packem_shared/createShardClient-BLW9uJZN.mjs";import{STORAGE_UPLOAD_MAX_BODY_BYTES as Me}from"./packem_shared/STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Ne}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ke}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as Be,routeIdentityResolvers as Ye}from"./packem_shared/composeIdentityResolvers-BHZ4jH8o.mjs";const e="0.0.0";export{s as BACKUP_KEY_PREFIX,me as DEFAULT_LOG_COLUMNS,A as DEFAULT_REGISTRY_CACHE_TTL_MS,U as HEALTH_PATH,B as HEALTH_READY_PATH,Ne as LOG_ARCHIVE_NOT_CONFIGURED,V as LOG_ARCHIVE_PATH,H as LunoraError,Ke as NOOP_EXECUTION_CONTEXT,L as SHARD_REGISTRY_DO_NAME,Me as STORAGE_UPLOAD_MAX_BODY_BYTES,e as VERSION,oe as analyticsEngineSink,le as applyJurisdiction,_e as applyRestCache,Oe as argsFromQuery,i as backupManifestKey,n as backupObjectKey,p as backupObjectKeyOfManifest,Y as buildHealthRoutes,be as buildRestRoutes,te as combineSinks,Be as composeIdentityResolvers,l as composeWorker,ae as consoleSink,O as createCrossShardRelationCapabilities,T as createDynamicShardRegistry,v as createKvCursorStore,d as createLunoraHandler,I as createMemoryCursorStore,fe as createPipelineLogReader,Re as createQueryCoordinator,Ae as createRestRateLimit,Ie as createShardClient,xe as createStaticShardRegistry,u as createWorker,w as d1Probe,t as declareAppJurisdiction,he as decorateResponse,D as defineExportSink,_ as defineRpcEnvelope,z as durableObjectProbe,$ as emitLogEvent,ee as emitRpcEvent,He as enforceOrigin,Pe as handleCorsPreflight,c as isBackupManifestEntry,m as isBackupManifestKey,J as memoizeIdentity,Q as memoizeIdentityPerRequest,f as normalizeBackupPrefix,se as otlpSink,ie as pipelineLogSink,X as presenceProbe,M as r2Sink,ke as requestCarriesCredentials,W as resolveLogArchiveFromEnv,k as resolveLunoraOptions,ge as resolveSecurity,de as resolveShard,ye as restCacheHeaders,Le as restSurfaceFromRegistry,Ye as routeIdentityResolvers,F as runExportTap,N as sanitizeChange,ne as sentrySink,R as toAirbyteMessages,P as toErrorResponse,x as toFivetranResponse,G as webhookExportSink,pe as webhookSink,y as withFrameworkWorker};
@@ -1 +1 @@
1
- import{LunoraError as a}from"./LunoraError-DksAgIpa.mjs";import{applyJurisdiction as S,resolveShard as _}from"./applyJurisdiction-C0ddU7Tg.mjs";const l="__lunora_shard_registry__",f=3e4,y="https://shard-registry.internal",g=async r=>await r.json(),T=r=>{const p=r.instanceName??l,i=r.cacheTtlMs??f,n=new Map,w=S(r.namespace,r.jurisdiction),c=()=>_(w,p),d=async(e,t)=>c().fetch(new Request(`${y}${e}`,{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST"})),h=async e=>c().fetch(new Request(`${y}${e}`,{method:"GET"}));return{invalidate(e){e===void 0?n.clear():n.delete(e)},async listShardKeys(e){const t=Date.now(),s=n.get(e);if(s&&s.expiresAt>t)return s.shardKeys;const o=await h(`/list?table=${encodeURIComponent(e)}`);if(!o.ok)throw new a(`shard registry /list returned ${String(o.status)}`);const{shardKeys:u}=await g(o);return i>0&&n.set(e,{expiresAt:t+i,shardKeys:u}),u},async register(e,t){const s=await d("/register",{shardKey:t,table:e});if(!s.ok)throw new a(`shard registry /register returned ${String(s.status)}`);n.delete(e)},async snapshot(){const e=await h("/snapshot");if(!e.ok)throw new a(`shard registry /snapshot returned ${String(e.status)}`);const{tables:t}=await g(e);return t},async unregister(e,t){const s=await d("/unregister",{shardKey:t,table:e});if(!s.ok)throw new a(`shard registry /unregister returned ${String(s.status)}`);n.delete(e)}}};export{f as DEFAULT_REGISTRY_CACHE_TTL_MS,l as SHARD_REGISTRY_DO_NAME,T as createDynamicShardRegistry};
1
+ import{LunoraError as a}from"./LunoraError-DksAgIpa.mjs";import{applyJurisdiction as S,resolveShard as _}from"./applyJurisdiction-D4vryLhj.mjs";const l="__lunora_shard_registry__",f=3e4,y="https://shard-registry.internal",g=async r=>await r.json(),T=r=>{const p=r.instanceName??l,i=r.cacheTtlMs??f,n=new Map,w=S(r.namespace,r.jurisdiction),c=()=>_(w,p),d=async(e,t)=>c().fetch(new Request(`${y}${e}`,{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST"})),h=async e=>c().fetch(new Request(`${y}${e}`,{method:"GET"}));return{invalidate(e){e===void 0?n.clear():n.delete(e)},async listShardKeys(e){const t=Date.now(),s=n.get(e);if(s&&s.expiresAt>t)return s.shardKeys;const o=await h(`/list?table=${encodeURIComponent(e)}`);if(!o.ok)throw new a(`shard registry /list returned ${String(o.status)}`);const{shardKeys:u}=await g(o);return i>0&&n.set(e,{expiresAt:t+i,shardKeys:u}),u},async register(e,t){const s=await d("/register",{shardKey:t,table:e});if(!s.ok)throw new a(`shard registry /register returned ${String(s.status)}`);n.delete(e)},async snapshot(){const e=await h("/snapshot");if(!e.ok)throw new a(`shard registry /snapshot returned ${String(e.status)}`);const{tables:t}=await g(e);return t},async unregister(e,t){const s=await d("/unregister",{shardKey:t,table:e});if(!s.ok)throw new a(`shard registry /unregister returned ${String(s.status)}`);n.delete(e)}}};export{f as DEFAULT_REGISTRY_CACHE_TTL_MS,l as SHARD_REGISTRY_DO_NAME,T as createDynamicShardRegistry};
@@ -1 +1 @@
1
- import{LunoraError as T}from"./LunoraError-DksAgIpa.mjs";import{m as A}from"./method-guard-BG_vJNTl.mjs";import{resolveShard as R}from"./applyJurisdiction-C0ddU7Tg.mjs";const H="/_lunora/health",C="/_lunora/health/ready",N=t=>t==="liveness"?["liveness"]:t==="readiness"?["readiness"]:["liveness","readiness"];class P{#e=new Map;addChecker(e,s,r){this.#e.set(e,{run:s,types:r.type})}async getReport(e){const s=[...this.#e].filter(([,a])=>e===void 0||a.types.includes(e)),r=await Promise.all(s.map(async([a,o])=>[a,await o.run()]));return{healthy:r.every(([,a])=>a.health.healthy),report:Object.fromEntries(r)}}}const S=t=>{const e=new P,s=new Set;for(const r of t)r.critical&&s.add(r.name),e.addChecker(r.name,async()=>{let a;try{a=await r.check()}catch(o){a={healthy:!1,message:o instanceof Error?o.message:"probe failed"}}return{health:{healthy:a.healthy,...a.message===void 0?{}:{message:a.message}}}},{type:N(r.kind)});return{criticalNames:s,registry:e}},_=(t,e)=>{const s=t.includes(":")?t.slice(0,t.indexOf(":")):"probe",r=(e.get(s)??0)+1;return e.set(s,r),r===1?s:`${s}#${String(r)}`},j=(t,e)=>t?"unhealthy":e?"degraded":"healthy",M=(t,e,s,r,a)=>{const o=[];let u=!1,d=!1;const y=new Map;for(const[h,c]of Object.entries(t)){const n=e.has(h),i=c.health.healthy;d=d||!i,u=u||!i&&n;const l=s==="admin"?h:_(h,y);o.push({critical:n,...s==="admin"&&c.health.message!==void 0?{message:c.health.message}:{},name:l,status:i?"up":"down"})}return o.sort((h,c)=>h.name<c.name?-1:+(h.name>c.name)),{anyCriticalDown:u,body:{appName:r,appVersion:a,checks:o,status:j(u,d),timestamp:new Date().toISOString()}}},G=t=>{const{appName:e="lunora",appVersion:s="0.0.0",auth:r="public",cacheTtlMs:a,isAdmin:o,resolveProbes:u}=t,d=n=>a!==void 0?a:n==="readiness"?0:r==="public"?5e3:0,y={},h=n=>{if(r==="admin"&&!o(n))throw new T("health endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403})},c=async(n,i,l)=>{const p=A(n,["GET","HEAD"]);if(p)return p;h(n);const f=d(l);if(f>0){const m=y[l];if(m!==void 0&&Date.now()<m.expiresAt)return Response.json(m.body,{headers:{"cache-control":"no-store"},status:m.down?503:200})}const{criticalNames:b,registry:v}=S(u(i)),{healthy:E,report:k}=await v.getReport(l==="readiness"?"readiness":void 0),{anyCriticalDown:D,body:g}=M(k,b,r,e,s),w=l==="readiness"?!E:D;return f>0&&(y[l]={body:g,down:w,expiresAt:Date.now()+f}),Response.json(g,{headers:{"cache-control":"no-store"},status:w?503:200})};return{[H]:(n,i)=>c(n,i,"aggregate"),[C]:(n,i)=>c(n,i,"readiness")}},I=(t,e,s)=>({check:async()=>{try{return await R(e,s).fetch(new Request("https://shard.internal/_lunora/status",{method:"GET"})),{healthy:!0}}catch{return{healthy:!1,message:"durable object unreachable"}}},critical:!0,name:t}),q=(t,e)=>({check:async()=>{try{return await e.prepare("SELECT 1").first(),{healthy:!0}}catch{return{healthy:!1,message:"d1 query failed"}}},critical:!0,name:t}),B=(t,e)=>({check:()=>e?{healthy:!0}:{healthy:!1,message:"binding not configured"},critical:!1,name:t});export{H as HEALTH_PATH,C as HEALTH_READY_PATH,G as buildHealthRoutes,q as d1Probe,I as durableObjectProbe,B as presenceProbe};
1
+ import{LunoraError as T}from"./LunoraError-DksAgIpa.mjs";import{m as A}from"./method-guard-BG_vJNTl.mjs";import{resolveShard as R}from"./applyJurisdiction-D4vryLhj.mjs";const H="/_lunora/health",C="/_lunora/health/ready",N=t=>t==="liveness"?["liveness"]:t==="readiness"?["readiness"]:["liveness","readiness"];class P{#e=new Map;addChecker(e,s,r){this.#e.set(e,{run:s,types:r.type})}async getReport(e){const s=[...this.#e].filter(([,a])=>e===void 0||a.types.includes(e)),r=await Promise.all(s.map(async([a,o])=>[a,await o.run()]));return{healthy:r.every(([,a])=>a.health.healthy),report:Object.fromEntries(r)}}}const S=t=>{const e=new P,s=new Set;for(const r of t)r.critical&&s.add(r.name),e.addChecker(r.name,async()=>{let a;try{a=await r.check()}catch(o){a={healthy:!1,message:o instanceof Error?o.message:"probe failed"}}return{health:{healthy:a.healthy,...a.message===void 0?{}:{message:a.message}}}},{type:N(r.kind)});return{criticalNames:s,registry:e}},_=(t,e)=>{const s=t.includes(":")?t.slice(0,t.indexOf(":")):"probe",r=(e.get(s)??0)+1;return e.set(s,r),r===1?s:`${s}#${String(r)}`},j=(t,e)=>t?"unhealthy":e?"degraded":"healthy",M=(t,e,s,r,a)=>{const o=[];let u=!1,d=!1;const y=new Map;for(const[h,c]of Object.entries(t)){const n=e.has(h),i=c.health.healthy;d=d||!i,u=u||!i&&n;const l=s==="admin"?h:_(h,y);o.push({critical:n,...s==="admin"&&c.health.message!==void 0?{message:c.health.message}:{},name:l,status:i?"up":"down"})}return o.sort((h,c)=>h.name<c.name?-1:+(h.name>c.name)),{anyCriticalDown:u,body:{appName:r,appVersion:a,checks:o,status:j(u,d),timestamp:new Date().toISOString()}}},G=t=>{const{appName:e="lunora",appVersion:s="0.0.0",auth:r="public",cacheTtlMs:a,isAdmin:o,resolveProbes:u}=t,d=n=>a!==void 0?a:n==="readiness"?0:r==="public"?5e3:0,y={},h=n=>{if(r==="admin"&&!o(n))throw new T("health endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403})},c=async(n,i,l)=>{const p=A(n,["GET","HEAD"]);if(p)return p;h(n);const f=d(l);if(f>0){const m=y[l];if(m!==void 0&&Date.now()<m.expiresAt)return Response.json(m.body,{headers:{"cache-control":"no-store"},status:m.down?503:200})}const{criticalNames:b,registry:v}=S(u(i)),{healthy:E,report:k}=await v.getReport(l==="readiness"?"readiness":void 0),{anyCriticalDown:D,body:g}=M(k,b,r,e,s),w=l==="readiness"?!E:D;return f>0&&(y[l]={body:g,down:w,expiresAt:Date.now()+f}),Response.json(g,{headers:{"cache-control":"no-store"},status:w?503:200})};return{[H]:(n,i)=>c(n,i,"aggregate"),[C]:(n,i)=>c(n,i,"readiness")}},I=(t,e,s)=>({check:async()=>{try{return await R(e,s).fetch(new Request("https://shard.internal/_lunora/status",{method:"GET"})),{healthy:!0}}catch{return{healthy:!1,message:"durable object unreachable"}}},critical:!0,name:t}),q=(t,e)=>({check:async()=>{try{return await e.prepare("SELECT 1").first(),{healthy:!0}}catch{return{healthy:!1,message:"d1 query failed"}}},critical:!0,name:t}),B=(t,e)=>({check:()=>e?{healthy:!0}:{healthy:!1,message:"binding not configured"},critical:!1,name:t});export{H as HEALTH_PATH,C as HEALTH_READY_PATH,G as buildHealthRoutes,q as d1Probe,I as durableObjectProbe,B as presenceProbe};
@@ -0,0 +1 @@
1
+ import{LUNORA_ROLE_PREFIX as d,resolveShard as f}from"@lunora/platform";import{LunoraError as m}from"./LunoraError-DksAgIpa.mjs";const a=new WeakMap,n=e=>e===void 0?void 0:{locationHint:e},p=e=>typeof e.idFromName=="function",u=e=>{if(!p(e))return e;const o=e,i=a.get(e);if(i!==void 0)return i;const s=typeof o.jurisdiction=="function"?r=>u(o.jurisdiction(r)):void 0,c=typeof o.getByName=="function"?{get:(r,t)=>o.get(r,n(t)),getByName:(r,t)=>o.getByName(r,n(t)),idForName:r=>o.idFromName(r),jurisdiction:s}:{get:(r,t)=>o.get(r,n(t)),idForName:r=>o.idFromName(r),jurisdiction:s};return a.set(e,c),c},g=(e,o)=>{if(o===void 0)return e;if(typeof e.jurisdiction!="function")throw new TypeError(`@lunora/runtime: Durable Object namespace does not support jurisdiction("${o}") — update @cloudflare/workers-types or remove the jurisdiction option`);return e.jurisdiction(o)},h=(e,o,i)=>{if(o.startsWith(d))throw new m(`shard key "${o}" uses the reserved "${d}" prefix`,{code:"BAD_REQUEST",status:400});return f(u(e),o,i)};export{g as applyJurisdiction,h as resolveShard};
@@ -1,4 +1,4 @@
1
- import{isLunoraError as pr,toErrorBody as mr}from"@lunora/errors";import{e as tn}from"./evict-oldest-BNXsKx4s.mjs";import{NOOP_EXECUTION_CONTEXT as wr}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{t as gr,f as yr}from"./base64-Bl1_r2k1.mjs";import{i as br,e as _r,a as Rr,E as gt,d as Er}from"./identity-header-pR617HTs.mjs";import{O as yt,a as bt}from"./origin-paywall-B6eOO67m.mjs";import{o as ge,b as nn,p as Ar,m as Sr,d as Tr,a as Or,r as vr}from"./otlp-resource-BwFJnvwB.mjs";import{r as Ir,f as _t,a as ce,S as Rt}from"./observability-DgurIZIR.mjs";import{e as Ee,d as Ye,a as kr}from"./wire-codec-BLvSm5Mn.mjs";import{d as ee,e as ne,M as rn,b as Pr,f as Dr,g as on,w as Nr,h as an,t as Ur}from"./rest-routes-D3ShCTHh.mjs";import{LunoraError as c,toErrorResponse as Et}from"./LunoraError-DksAgIpa.mjs";import{a as M,m as we}from"./method-guard-BG_vJNTl.mjs";import{normalizeBackupPrefix as nt,BACKUP_KEY_PREFIX as rt,isBackupManifestKey as Cr,backupObjectKeyOfManifest as sn,backupObjectKey as Br,backupManifestKey as xr}from"./BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toHex as Hr,buildStorageAdminRoutes as Lr,STORAGE_UPLOAD_MAX_BODY_BYTES as jr,STORAGE_PATH as Mr}from"./STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs";import{b as $r,e as Fr,f as At,g as Kr,h as Gr}from"./export-tap-CAyZ2TWC.mjs";import{buildHealthRoutes as Qr,durableObjectProbe as Wr,d1Probe as zr,presenceProbe as je}from"./HEALTH_PATH-D0i8LhwT.mjs";import{wrapResolverWithContract as Vr}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{composeIdentityResolvers as xi,routeIdentityResolvers as Hi}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{buildLogArchiveAdminRoutes as Jr}from"./LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{pruneShardRegistry as Yr,createQueryCoordinator as qr,createDefaultShardRegistry as Xr}from"./createQueryCoordinator-BkZPoV26.mjs";import{resolveShard as ye,applyJurisdiction as Me}from"./applyJurisdiction-C0ddU7Tg.mjs";import{resolveSecurity as St,handleCorsPreflight as Zr,enforceOrigin as eo,decorateResponse as $e,enforceWebSocketOrigin as Tt}from"./decorateResponse-CRrFNW1v.mjs";const to=e=>{const t=e??{};if(typeof t.bucket=="function")return t;const n=t.bucketName,a={...t,bucketName:typeof n=="string"&&n!==""?n:"default"};return a.bucket=()=>a,a},cn="__lunoraBranch",no=e=>typeof e=="object"&&e!==null&&Object.hasOwn(e,cn),ro=`may not contain the reserved workflow branch-marker key ("${cn}")`,oo=async e=>{const t=[];let n;for(;;){const o=await e(n);if(t.push(...Array.isArray(o.records)?o.records:[]),o.truncated!==!0||typeof o.cursor!="string"||o.cursor.length===0)return t;if(o.cursor===n)throw new Error("collectPages: the list did not advance its cursor — refusing to page forever");n=o.cursor}},ot=(e,t)=>{const n=Math.max(e.length,t.length);let o=e.length^t.length;for(let a=0;a<n;a+=1){const i=a<e.length?e.charCodeAt(a):0,d=a<t.length?t.charCodeAt(a):0;o|=i^d}return o===0},ao=/already[\s_-]?exists/iu,so=e=>ao.test(e instanceof Error?e.message:String(e)),io=(e,t,n,o)=>{const a=e.get(t);if(a!==void 0)return a;tn(e,o);const i=n().catch(d=>{throw e.get(t)===i&&e.delete(t),d});return e.set(t,i),i},at=new TextEncoder,co=Array.from({length:32},(e,t)=>t);new RegExp(`[${co.map(e=>String.fromCodePoint(e)).join("")}]`,"u");const uo=64,lo=new Map,dn=async e=>io(lo,e,async()=>crypto.subtle.importKey("raw",at.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]),uo),un=async(e,t)=>{const n=await dn(e),o=await crypto.subtle.sign("HMAC",n,at.encode(t));return gr(new Uint8Array(o))},ho=async(e,t,n)=>{const o=await dn(e);return crypto.subtle.verify("HMAC",o,n,at.encode(t))},fo="cf-ray",po="x-lunora-ray-id",mo=/^([\da-f]{16})(?:-[a-z]{3,4})?$/i,wo=e=>e==null?void 0:mo.exec(e.trim())?.[1]?.toLowerCase(),go=["wnam","enam","sam","weur","eeur","apac","apac-ne","apac-se","oc","afr","me"];new Set(go);const yo=new Set(["AE","BH","IL","IQ","IR","JO","KW","LB","OM","PS","QA","SA","SY","TR","YE"]),bo=-100,_o=15,Ro=e=>{const t=Number(e.longitude??Number.NaN);switch(e.continent){case"AF":return"afr";case"AS":return e.country!==void 0&&yo.has(e.country)?"me":"apac";case"EU":return Number.isFinite(t)&&t>_o?"eeur":"weur";case"NA":return Number.isFinite(t)&&t<bo?"wnam":"enam";case"OC":return"oc";case"SA":return"sam";default:return}},Ot=e=>{const t=e.cf;return t===void 0?void 0:Ro(t)},qe="::relay::",Eo=(e,t)=>`${e}${qe}${String(t)}`,Xe="::replica::",Ao=(e,t)=>`${e}${Xe}${t}`,So=e=>{if(e==null||!/^\d+$/.test(e))return;const t=Number.parseInt(e,10);return Number.isSafeInteger(t)&&t>0?t:void 0},To=(e,t,n)=>e?.[n]??t?.[n],Oo=(e,t,n,o)=>{const a=To(e,t,n);if(!(typeof a!="object"||a===null))return o.every(i=>typeof a[i]=="function")?a:void 0},vo=new Set(["1","enabled","on","true","yes"]),Io=new Set(["0","disabled","false","no","off"]),ko=(e,t)=>{const n=(e??"").trim().toLowerCase();return vo.has(n)?!0:Io.has(n)?!1:t},ln="v1",Po=6e4,Do=async(e,t={})=>{const n=(t.now??Date.now())+(t.ttlMs??Po),o=`${ln}.${String(n)}`,a=await un(e,o);return{expiresAtMs:n,token:`${o}.${a}`}},No=async(e,t,n=Date.now())=>{if(e.length===0||t.length===0)return!1;const o=t.split(".");if(o.length!==3)return!1;const[a,i,d]=o;if(a!==ln||d.length===0)return!1;const f=Number(i);if(!Number.isFinite(f)||f<=n)return!1;let h;try{h=yr(d)}catch{return!1}return ho(e,`${a}.${i}`,h)},N="/_lunora/admin/auth",Uo={INVITER_REQUIRED:400,ORG_SLUG_INVALID:400,ORG_SLUG_TAKEN:409,PASSWORD_TOO_LONG:400,PASSWORD_TOO_SHORT:400,USER_ALREADY_EXISTS:409,USER_NOT_FOUND:404},C=(e,t)=>{const n=e[t];if(typeof n!="string"||n==="")throw new c(`\`${t}\` is required`,{code:"BAD_REQUEST",status:400});return n},he=(e,t)=>{const n=e(t);if(n===void 0)throw new c(`\`${t}\` query parameter is required`,{code:"BAD_REQUEST",status:400});return n},hn=e=>{if(typeof e=="string"||Array.isArray(e)&&e.every(t=>typeof t=="string"))return e},te=(e,t)=>typeof e[t]=="string"?e[t]:void 0,Fe=(e,t)=>{const n=e[t];return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:void 0},vt=e=>{const t=hn(e.role);if(t===void 0||typeof t=="string"&&t.trim()==="")throw new c("`role` is required",{code:"BAD_REQUEST",status:400});return t},It=e=>{const t=e.permission;if(typeof t!="object"||t===null||Array.isArray(t))throw new c("`permission` object is required",{code:"BAD_REQUEST",status:400});const n={};for(const[o,a]of Object.entries(t))Array.isArray(a)&&a.every(i=>typeof i=="string")&&(n[o]=a);return n},Co={[`${N}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${N}/users`]:{build:({paging:e,query:t})=>{const n=t("sortDirection");return{...e,filterField:t("filterField"),filterValue:t("filterValue"),search:t("search"),searchField:t("searchField"),sortBy:t("sortBy"),sortDirection:n==="asc"||n==="desc"?n:void 0}},http:"GET",method:"listUsers"},[`${N}/sessions`]:{build:({paging:e,query:t})=>({...e,userId:t("userId")}),http:"GET",method:"listSessions"},[`${N}/accounts`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listAccounts"},[`${N}/passkeys`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listPasskeys"},[`${N}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${N}/organizations/members`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listMembers"},[`${N}/organizations/invitations`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listInvitations"},[`${N}/sign-up-invitations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listSignUpInvitations"},[`${N}/sign-up-invitations/create`]:{build:({body:e})=>({email:C(e,"email"),expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,invitedBy:te(e,"invitedBy")}),http:"POST",method:"createSignUpInvitation"},[`${N}/sign-up-invitations/revoke`]:{build:({body:e})=>({email:C(e,"email")}),http:"POST",method:"revokeSignUpInvitation",returns:"void"},[`${N}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${N}/organizations/teams`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listTeams"},[`${N}/organizations/teams/members`]:{build:({paging:e,query:t})=>({...e,teamId:he(t,"teamId")}),http:"GET",method:"listTeamMembers"},[`${N}/organizations/roles`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${N}/users/create`]:{build:({body:e})=>({data:Fe(e,"data"),email:C(e,"email"),name:C(e,"name"),password:te(e,"password"),role:hn(e.role)}),http:"POST",method:"createUser"},[`${N}/users/update`]:{build:({body:e})=>{const{data:t}=e;if(typeof t!="object"||t===null||Array.isArray(t))throw new c("`data` object is required",{code:"BAD_REQUEST",status:400});return{data:t,userId:C(e,"userId")}},http:"POST",method:"updateUser"},[`${N}/users/role`]:{build:({body:e})=>({role:vt(e),userId:C(e,"userId")}),http:"POST",method:"setRole"},[`${N}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:te(e,"reason"),userId:C(e,"userId")}),http:"POST",method:"banUser"},[`${N}/users/unban`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"unbanUser"},[`${N}/users/password`]:{build:({body:e})=>({newPassword:C(e,"newPassword"),userId:C(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${N}/users/remove`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${N}/users/impersonate`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"impersonateUser"},[`${N}/sessions/revoke`]:{build:({body:e})=>({sessionId:C(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${N}/sessions/revoke-all`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${N}/accounts/unlink`]:{build:({body:e})=>({accountId:C(e,"accountId"),userId:C(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${N}/two-factor/disable`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${N}/passkeys/delete`]:{build:({body:e})=>({passkeyId:C(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${N}/organizations/members/remove`]:{build:({body:e})=>({memberId:C(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${N}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:C(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${N}/organizations/create`]:{build:({body:e})=>({logo:te(e,"logo"),metadata:Fe(e,"metadata"),name:C(e,"name"),ownerId:te(e,"ownerId"),slug:te(e,"slug")}),http:"POST",method:"createOrganization"},[`${N}/organizations/update`]:{build:({body:e})=>({logo:te(e,"logo"),metadata:Fe(e,"metadata"),name:te(e,"name"),organizationId:C(e,"organizationId"),slug:te(e,"slug")}),http:"POST",method:"updateOrganization"},[`${N}/organizations/remove`]:{build:({body:e})=>({organizationId:C(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${N}/organizations/members/add`]:{build:({body:e})=>({organizationId:C(e,"organizationId"),role:te(e,"role"),userId:C(e,"userId")}),http:"POST",method:"addMember"},[`${N}/organizations/members/invite`]:{build:({body:e})=>({email:C(e,"email"),inviterId:te(e,"inviterId"),organizationId:C(e,"organizationId"),role:te(e,"role")}),http:"POST",method:"inviteMember"},[`${N}/organizations/members/role`]:{build:({body:e})=>({memberId:C(e,"memberId"),role:vt(e)}),http:"POST",method:"updateMemberRole"},[`${N}/organizations/teams/create`]:{build:({body:e})=>({name:C(e,"name"),organizationId:C(e,"organizationId")}),http:"POST",method:"createTeam"},[`${N}/organizations/teams/update`]:{build:({body:e})=>({name:C(e,"name"),teamId:C(e,"teamId")}),http:"POST",method:"updateTeam"},[`${N}/organizations/teams/remove`]:{build:({body:e})=>({teamId:C(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${N}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:C(e,"teamId"),userId:C(e,"userId")}),http:"POST",method:"addTeamMember"},[`${N}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:C(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${N}/organizations/roles/create`]:{build:({body:e})=>({organizationId:C(e,"organizationId"),permission:It(e),role:C(e,"role")}),http:"POST",method:"createOrgRole"},[`${N}/organizations/roles/update`]:{build:({body:e})=>({permission:It(e),roleId:C(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${N}/organizations/roles/remove`]:{build:({body:e})=>({roleId:C(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},Bo=e=>{const t=async a=>{try{return await a()}catch(i){if(i instanceof c)throw i;const d=i,f=typeof d.code=="string"?d.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new c("auth admin operation failed",{code:f,status:Uo[f]??500})}},n=async(a,i)=>{if(e.assertAdmin(a),a.method!==i.http)throw new c(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const d=e.getAuthAdmin();if(d===void 0)throw new c("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const f=d[i.method];if(f===void 0)throw new c(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const h=new URL(a.url),m={body:i.http==="POST"?await e.readJsonBody(a):{},paging:e.parsePaging(a),query:T=>e.queryParameter(h,T)},b=i.build(m),S=await t(()=>f(b));return Response.json(i.returns==="void"?{ok:!0}:S,{headers:{"cache-control":"no-store","content-type":"application/json"},status:200})},o={};for(const[a,i]of Object.entries(Co))o[a]=d=>n(d,i);return o},kt="__lunora_admin__:getAuthAuditLog",Pt=e=>typeof e=="string"&&e!==""?e:void 0,Dt=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0,xo=e=>async(n,o)=>{e.assertAdmin(n);const a=e.getReader();if(a===void 0)throw new c("the auth/security audit endpoint requires an `authAuditReader` on the worker",{code:"AUTH_AUDIT_NOT_CONFIGURED",status:400});const i=Pt(o.actorId),d=Pt(o.event),f=Dt(o.sinceSeq),h=Dt(o.limit),m={...i===void 0?{}:{actorId:i},...d===void 0?{}:{event:d},...f===void 0?{}:{sinceSeq:f},...h===void 0?{}:{limit:h}};let b;try{b=await a.read(m)}catch(T){throw T instanceof c?T:(console.error("[lunora] auth audit read failed:",T),new c("auth audit read failed",{code:"AUTH_AUDIT_READ_FAILED",status:500}))}const S={entries:b};return Response.json({result:Ee(S)},{headers:{"content-type":"application/json"},status:200})},Ze="__lunora_admin__:copyAuthToJurisdiction",fn="__lunora_admin__:purgeUnpinnedAuth",Ho=e=>async(t,n,o)=>{if(n!==Ze&&n!==fn)return;e.assertAdmin(t);const a=e.getMove();if(a===void 0)throw new c("moving auth into the jurisdiction needs DO-backed auth pinned with `.jurisdiction(…, { pinAuth: true })`",{code:"AUTH_MOVE_NOT_CONFIGURED",status:400});const i=n===Ze?await a.copy({force:o.force===!0}):await a.purge();return Response.json({result:Ee(i)},{headers:{"content-type":"application/json"},status:200})},Lo=(e,t)=>{const n=[],o=[];if(t&&t.length>0)for(const a of t)e.resolveTableSharding?.(a)?.mode.kind==="global"?o.push(a):n.push(a);return{globalTables:o,shardLocalTables:n}},jo=async(e,t,n,o,a,i)=>{if(n!==void 0&&o.length===0)return[];const d=await e.orchestrateExport(a,{args:{tables:o},defaultShardKey:i,headers:t,tables:o}),f=d.shards.filter(h=>h.error);if(f.length>0){const h=f.map(m=>`${m.shardKey}: ${m.error?.message??"unknown error"}`).join("; ");throw new c(`export failed on ${String(f.length)} of ${String(d.shards.length)} shard(s) — ${h}`,{code:"EXPORT_SHARD_FAILED",status:502})}return d.shards.flatMap(h=>h.rows??[])},pn=async(e,t,n,o,a)=>{const i=o??e.listSchemaTables?.();o===void 0&&e.listSchemaTables===void 0&&console.warn("[lunora] export: no table list available (`listSchemaTables` is unset and no `tables` were named), so only the default shard is reachable. A `.shardBy()` deployment's other shards will be missing from this export. Name the tables explicitly, or regenerate the worker so codegen supplies the list.");const{globalTables:d,shardLocalTables:f}=Lo(e,i),h=await jo(t,n,i,f,a,e.defaultShardKey??"__root__"),m=e.exportGlobals,b=o===void 0||d.length>0;return(async function*(){yield*h,b&&m&&(yield*m({tables:d}))})()},Mo=async(e,t,n,o,a,i)=>{for await(const d of await pn(e,t,n,o,i))a(d)},$o=new TextEncoder,Fo=1e3,mn=10,Ko=200,Nt=8,wn="lunoraBackupCron",Ut=24*1048576,Ct=e=>{const t=e.slice(0,mn).map(o=>sn(o)),n=e.length-t.length;return`${t.join(", ")}${n>0?` (+${String(n)} more)`:""}`},Go=(e,t)=>{const n=new Uint8Array(new ArrayBuffer(t));let o=0;for(const a of e)n.set(a,o),o+=a.byteLength;return n},st=async(e,t,n,o)=>{if(n===void 0||!Number.isInteger(n)||n<=0)return{eligible:0,stale:[]};const a=[];let i;for(let d=0;d<Fo;d+=1){const f=await e.list({cursor:i,include:["customMetadata"],prefix:t});for(const h of f.objects)Cr(h.key)&&h.customMetadata?.[wn]===o&&a.push(h.key);if(!f.truncated||f.cursor===void 0)break;i=f.cursor}return{eligible:a.length,stale:a.toSorted((d,f)=>f.localeCompare(d)).slice(n)}},Qo=async(e,t,n,o,a)=>{const{stale:i}=await st(e,t,n,o),d=new Set(a),f=i.filter(k=>d.has(k)),h=f.slice(0,Ko),m=i.length-h.length,b=a.length-f.length;if(h.length===0)return{deleted:[],failed:[],ignored:b,remaining:m};const S=[],T=[];for(let k=0;k<h.length;k+=Nt){const w=await Promise.allSettled(h.slice(k,k+Nt).map(async g=>(await e.delete(sn(g)),await e.delete(g),g)));for(const[g,y]of w.entries())y.status==="fulfilled"?S.push(y.value):T.push(h[k+g])}return S.length>0&&console.info(`[lunora] backup prune kept the newest ${String(n)} and deleted ${String(S.length)}: ${Ct(S)}`),T.length>0&&console.warn(`[lunora] backup prune failed to remove ${String(T.length)}: ${Ct(T)}`),{deleted:S,failed:T,ignored:b,remaining:m}},Wo=async e=>{const t=e.backupStore;if(!t)throw new c("backup retention preview requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});const n=nt(e.backupPrefix??rt),o=e.backupCron,{eligible:a,stale:i}=o===void 0?{eligible:0,stale:[]}:await st(t,n,e.backupRetain,o);return{cron:o,eligible:a,keep:e.backupRetain??0,prefix:n,wouldDelete:i}},zo=async(e,t,n,o,a)=>{const i=e.backupStore;if(!i)throw new c("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!o||o.length===0)throw new c("scheduled backup requires an `adminToken` (or `env.LUNORA_ADMIN_TOKEN`) to authenticate the per-shard export gate",{code:"BACKUP_NOT_CONFIGURED",status:500});const d={authorization:`Bearer ${o}`,"content-type":"application/json"},f=e.backupTables;let h=0,m=0,b=[];await Mo(e,t,d,f,I=>{const E=$o.encode(`${JSON.stringify(I)}
1
+ import{isLunoraError as pr,toErrorBody as mr}from"@lunora/errors";import{e as tn}from"./evict-oldest-BNXsKx4s.mjs";import{NOOP_EXECUTION_CONTEXT as wr}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{t as gr,f as yr}from"./base64-Bl1_r2k1.mjs";import{i as br,e as _r,a as Rr,E as gt,d as Er}from"./identity-header-pR617HTs.mjs";import{O as yt,a as bt}from"./origin-paywall-B6eOO67m.mjs";import{o as ge,b as nn,p as Ar,m as Sr,d as Tr,a as Or,r as vr}from"./otlp-resource-BwFJnvwB.mjs";import{r as Ir,f as _t,a as ce,S as Rt}from"./observability-DgurIZIR.mjs";import{e as Ee,d as Ye,a as kr}from"./wire-codec-BLvSm5Mn.mjs";import{d as ee,e as ne,M as rn,b as Pr,f as Dr,g as on,w as Nr,h as an,t as Ur}from"./rest-routes-D3ShCTHh.mjs";import{LunoraError as c,toErrorResponse as Et}from"./LunoraError-DksAgIpa.mjs";import{a as M,m as we}from"./method-guard-BG_vJNTl.mjs";import{normalizeBackupPrefix as nt,BACKUP_KEY_PREFIX as rt,isBackupManifestKey as Cr,backupObjectKeyOfManifest as sn,backupObjectKey as Br,backupManifestKey as xr}from"./BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toHex as Hr,buildStorageAdminRoutes as Lr,STORAGE_UPLOAD_MAX_BODY_BYTES as jr,STORAGE_PATH as Mr}from"./STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs";import{b as $r,e as Fr,f as At,g as Kr,h as Gr}from"./export-tap-CAyZ2TWC.mjs";import{buildHealthRoutes as Qr,durableObjectProbe as Wr,d1Probe as zr,presenceProbe as je}from"./HEALTH_PATH-CAX2UeFy.mjs";import{wrapResolverWithContract as Vr}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{composeIdentityResolvers as xi,routeIdentityResolvers as Hi}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{buildLogArchiveAdminRoutes as Jr}from"./LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{pruneShardRegistry as Yr,createQueryCoordinator as qr,createDefaultShardRegistry as Xr}from"./createQueryCoordinator-CXdh_RxT.mjs";import{resolveShard as ye,applyJurisdiction as Me}from"./applyJurisdiction-D4vryLhj.mjs";import{resolveSecurity as St,handleCorsPreflight as Zr,enforceOrigin as eo,decorateResponse as $e,enforceWebSocketOrigin as Tt}from"./decorateResponse-CRrFNW1v.mjs";const to=e=>{const t=e??{};if(typeof t.bucket=="function")return t;const n=t.bucketName,a={...t,bucketName:typeof n=="string"&&n!==""?n:"default"};return a.bucket=()=>a,a},cn="__lunoraBranch",no=e=>typeof e=="object"&&e!==null&&Object.hasOwn(e,cn),ro=`may not contain the reserved workflow branch-marker key ("${cn}")`,oo=async e=>{const t=[];let n;for(;;){const o=await e(n);if(t.push(...Array.isArray(o.records)?o.records:[]),o.truncated!==!0||typeof o.cursor!="string"||o.cursor.length===0)return t;if(o.cursor===n)throw new Error("collectPages: the list did not advance its cursor — refusing to page forever");n=o.cursor}},ot=(e,t)=>{const n=Math.max(e.length,t.length);let o=e.length^t.length;for(let a=0;a<n;a+=1){const i=a<e.length?e.charCodeAt(a):0,d=a<t.length?t.charCodeAt(a):0;o|=i^d}return o===0},ao=/already[\s_-]?exists/iu,so=e=>ao.test(e instanceof Error?e.message:String(e)),io=(e,t,n,o)=>{const a=e.get(t);if(a!==void 0)return a;tn(e,o);const i=n().catch(d=>{throw e.get(t)===i&&e.delete(t),d});return e.set(t,i),i},at=new TextEncoder,co=Array.from({length:32},(e,t)=>t);new RegExp(`[${co.map(e=>String.fromCodePoint(e)).join("")}]`,"u");const uo=64,lo=new Map,dn=async e=>io(lo,e,async()=>crypto.subtle.importKey("raw",at.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]),uo),un=async(e,t)=>{const n=await dn(e),o=await crypto.subtle.sign("HMAC",n,at.encode(t));return gr(new Uint8Array(o))},ho=async(e,t,n)=>{const o=await dn(e);return crypto.subtle.verify("HMAC",o,n,at.encode(t))},fo="cf-ray",po="x-lunora-ray-id",mo=/^([\da-f]{16})(?:-[a-z]{3,4})?$/i,wo=e=>e==null?void 0:mo.exec(e.trim())?.[1]?.toLowerCase(),go=["wnam","enam","sam","weur","eeur","apac","apac-ne","apac-se","oc","afr","me"];new Set(go);const yo=new Set(["AE","BH","IL","IQ","IR","JO","KW","LB","OM","PS","QA","SA","SY","TR","YE"]),bo=-100,_o=15,Ro=e=>{const t=Number(e.longitude??Number.NaN);switch(e.continent){case"AF":return"afr";case"AS":return e.country!==void 0&&yo.has(e.country)?"me":"apac";case"EU":return Number.isFinite(t)&&t>_o?"eeur":"weur";case"NA":return Number.isFinite(t)&&t<bo?"wnam":"enam";case"OC":return"oc";case"SA":return"sam";default:return}},Ot=e=>{const t=e.cf;return t===void 0?void 0:Ro(t)},qe="::relay::",Eo=(e,t)=>`${e}${qe}${String(t)}`,Xe="::replica::",Ao=(e,t)=>`${e}${Xe}${t}`,So=e=>{if(e==null||!/^\d+$/.test(e))return;const t=Number.parseInt(e,10);return Number.isSafeInteger(t)&&t>0?t:void 0},To=(e,t,n)=>e?.[n]??t?.[n],Oo=(e,t,n,o)=>{const a=To(e,t,n);if(!(typeof a!="object"||a===null))return o.every(i=>typeof a[i]=="function")?a:void 0},vo=new Set(["1","enabled","on","true","yes"]),Io=new Set(["0","disabled","false","no","off"]),ko=(e,t)=>{const n=(e??"").trim().toLowerCase();return vo.has(n)?!0:Io.has(n)?!1:t},ln="v1",Po=6e4,Do=async(e,t={})=>{const n=(t.now??Date.now())+(t.ttlMs??Po),o=`${ln}.${String(n)}`,a=await un(e,o);return{expiresAtMs:n,token:`${o}.${a}`}},No=async(e,t,n=Date.now())=>{if(e.length===0||t.length===0)return!1;const o=t.split(".");if(o.length!==3)return!1;const[a,i,d]=o;if(a!==ln||d.length===0)return!1;const f=Number(i);if(!Number.isFinite(f)||f<=n)return!1;let h;try{h=yr(d)}catch{return!1}return ho(e,`${a}.${i}`,h)},N="/_lunora/admin/auth",Uo={INVITER_REQUIRED:400,ORG_SLUG_INVALID:400,ORG_SLUG_TAKEN:409,PASSWORD_TOO_LONG:400,PASSWORD_TOO_SHORT:400,USER_ALREADY_EXISTS:409,USER_NOT_FOUND:404},C=(e,t)=>{const n=e[t];if(typeof n!="string"||n==="")throw new c(`\`${t}\` is required`,{code:"BAD_REQUEST",status:400});return n},he=(e,t)=>{const n=e(t);if(n===void 0)throw new c(`\`${t}\` query parameter is required`,{code:"BAD_REQUEST",status:400});return n},hn=e=>{if(typeof e=="string"||Array.isArray(e)&&e.every(t=>typeof t=="string"))return e},te=(e,t)=>typeof e[t]=="string"?e[t]:void 0,Fe=(e,t)=>{const n=e[t];return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:void 0},vt=e=>{const t=hn(e.role);if(t===void 0||typeof t=="string"&&t.trim()==="")throw new c("`role` is required",{code:"BAD_REQUEST",status:400});return t},It=e=>{const t=e.permission;if(typeof t!="object"||t===null||Array.isArray(t))throw new c("`permission` object is required",{code:"BAD_REQUEST",status:400});const n={};for(const[o,a]of Object.entries(t))Array.isArray(a)&&a.every(i=>typeof i=="string")&&(n[o]=a);return n},Co={[`${N}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${N}/users`]:{build:({paging:e,query:t})=>{const n=t("sortDirection");return{...e,filterField:t("filterField"),filterValue:t("filterValue"),search:t("search"),searchField:t("searchField"),sortBy:t("sortBy"),sortDirection:n==="asc"||n==="desc"?n:void 0}},http:"GET",method:"listUsers"},[`${N}/sessions`]:{build:({paging:e,query:t})=>({...e,userId:t("userId")}),http:"GET",method:"listSessions"},[`${N}/accounts`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listAccounts"},[`${N}/passkeys`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listPasskeys"},[`${N}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${N}/organizations/members`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listMembers"},[`${N}/organizations/invitations`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listInvitations"},[`${N}/sign-up-invitations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listSignUpInvitations"},[`${N}/sign-up-invitations/create`]:{build:({body:e})=>({email:C(e,"email"),expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,invitedBy:te(e,"invitedBy")}),http:"POST",method:"createSignUpInvitation"},[`${N}/sign-up-invitations/revoke`]:{build:({body:e})=>({email:C(e,"email")}),http:"POST",method:"revokeSignUpInvitation",returns:"void"},[`${N}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${N}/organizations/teams`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listTeams"},[`${N}/organizations/teams/members`]:{build:({paging:e,query:t})=>({...e,teamId:he(t,"teamId")}),http:"GET",method:"listTeamMembers"},[`${N}/organizations/roles`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${N}/users/create`]:{build:({body:e})=>({data:Fe(e,"data"),email:C(e,"email"),name:C(e,"name"),password:te(e,"password"),role:hn(e.role)}),http:"POST",method:"createUser"},[`${N}/users/update`]:{build:({body:e})=>{const{data:t}=e;if(typeof t!="object"||t===null||Array.isArray(t))throw new c("`data` object is required",{code:"BAD_REQUEST",status:400});return{data:t,userId:C(e,"userId")}},http:"POST",method:"updateUser"},[`${N}/users/role`]:{build:({body:e})=>({role:vt(e),userId:C(e,"userId")}),http:"POST",method:"setRole"},[`${N}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:te(e,"reason"),userId:C(e,"userId")}),http:"POST",method:"banUser"},[`${N}/users/unban`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"unbanUser"},[`${N}/users/password`]:{build:({body:e})=>({newPassword:C(e,"newPassword"),userId:C(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${N}/users/remove`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${N}/users/impersonate`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"impersonateUser"},[`${N}/sessions/revoke`]:{build:({body:e})=>({sessionId:C(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${N}/sessions/revoke-all`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${N}/accounts/unlink`]:{build:({body:e})=>({accountId:C(e,"accountId"),userId:C(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${N}/two-factor/disable`]:{build:({body:e})=>({userId:C(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${N}/passkeys/delete`]:{build:({body:e})=>({passkeyId:C(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${N}/organizations/members/remove`]:{build:({body:e})=>({memberId:C(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${N}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:C(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${N}/organizations/create`]:{build:({body:e})=>({logo:te(e,"logo"),metadata:Fe(e,"metadata"),name:C(e,"name"),ownerId:te(e,"ownerId"),slug:te(e,"slug")}),http:"POST",method:"createOrganization"},[`${N}/organizations/update`]:{build:({body:e})=>({logo:te(e,"logo"),metadata:Fe(e,"metadata"),name:te(e,"name"),organizationId:C(e,"organizationId"),slug:te(e,"slug")}),http:"POST",method:"updateOrganization"},[`${N}/organizations/remove`]:{build:({body:e})=>({organizationId:C(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${N}/organizations/members/add`]:{build:({body:e})=>({organizationId:C(e,"organizationId"),role:te(e,"role"),userId:C(e,"userId")}),http:"POST",method:"addMember"},[`${N}/organizations/members/invite`]:{build:({body:e})=>({email:C(e,"email"),inviterId:te(e,"inviterId"),organizationId:C(e,"organizationId"),role:te(e,"role")}),http:"POST",method:"inviteMember"},[`${N}/organizations/members/role`]:{build:({body:e})=>({memberId:C(e,"memberId"),role:vt(e)}),http:"POST",method:"updateMemberRole"},[`${N}/organizations/teams/create`]:{build:({body:e})=>({name:C(e,"name"),organizationId:C(e,"organizationId")}),http:"POST",method:"createTeam"},[`${N}/organizations/teams/update`]:{build:({body:e})=>({name:C(e,"name"),teamId:C(e,"teamId")}),http:"POST",method:"updateTeam"},[`${N}/organizations/teams/remove`]:{build:({body:e})=>({teamId:C(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${N}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:C(e,"teamId"),userId:C(e,"userId")}),http:"POST",method:"addTeamMember"},[`${N}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:C(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${N}/organizations/roles/create`]:{build:({body:e})=>({organizationId:C(e,"organizationId"),permission:It(e),role:C(e,"role")}),http:"POST",method:"createOrgRole"},[`${N}/organizations/roles/update`]:{build:({body:e})=>({permission:It(e),roleId:C(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${N}/organizations/roles/remove`]:{build:({body:e})=>({roleId:C(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},Bo=e=>{const t=async a=>{try{return await a()}catch(i){if(i instanceof c)throw i;const d=i,f=typeof d.code=="string"?d.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new c("auth admin operation failed",{code:f,status:Uo[f]??500})}},n=async(a,i)=>{if(e.assertAdmin(a),a.method!==i.http)throw new c(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const d=e.getAuthAdmin();if(d===void 0)throw new c("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const f=d[i.method];if(f===void 0)throw new c(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const h=new URL(a.url),m={body:i.http==="POST"?await e.readJsonBody(a):{},paging:e.parsePaging(a),query:T=>e.queryParameter(h,T)},b=i.build(m),S=await t(()=>f(b));return Response.json(i.returns==="void"?{ok:!0}:S,{headers:{"cache-control":"no-store","content-type":"application/json"},status:200})},o={};for(const[a,i]of Object.entries(Co))o[a]=d=>n(d,i);return o},kt="__lunora_admin__:getAuthAuditLog",Pt=e=>typeof e=="string"&&e!==""?e:void 0,Dt=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0,xo=e=>async(n,o)=>{e.assertAdmin(n);const a=e.getReader();if(a===void 0)throw new c("the auth/security audit endpoint requires an `authAuditReader` on the worker",{code:"AUTH_AUDIT_NOT_CONFIGURED",status:400});const i=Pt(o.actorId),d=Pt(o.event),f=Dt(o.sinceSeq),h=Dt(o.limit),m={...i===void 0?{}:{actorId:i},...d===void 0?{}:{event:d},...f===void 0?{}:{sinceSeq:f},...h===void 0?{}:{limit:h}};let b;try{b=await a.read(m)}catch(T){throw T instanceof c?T:(console.error("[lunora] auth audit read failed:",T),new c("auth audit read failed",{code:"AUTH_AUDIT_READ_FAILED",status:500}))}const S={entries:b};return Response.json({result:Ee(S)},{headers:{"content-type":"application/json"},status:200})},Ze="__lunora_admin__:copyAuthToJurisdiction",fn="__lunora_admin__:purgeUnpinnedAuth",Ho=e=>async(t,n,o)=>{if(n!==Ze&&n!==fn)return;e.assertAdmin(t);const a=e.getMove();if(a===void 0)throw new c("moving auth into the jurisdiction needs DO-backed auth pinned with `.jurisdiction(…, { pinAuth: true })`",{code:"AUTH_MOVE_NOT_CONFIGURED",status:400});const i=n===Ze?await a.copy({force:o.force===!0}):await a.purge();return Response.json({result:Ee(i)},{headers:{"content-type":"application/json"},status:200})},Lo=(e,t)=>{const n=[],o=[];if(t&&t.length>0)for(const a of t)e.resolveTableSharding?.(a)?.mode.kind==="global"?o.push(a):n.push(a);return{globalTables:o,shardLocalTables:n}},jo=async(e,t,n,o,a,i)=>{if(n!==void 0&&o.length===0)return[];const d=await e.orchestrateExport(a,{args:{tables:o},defaultShardKey:i,headers:t,tables:o}),f=d.shards.filter(h=>h.error);if(f.length>0){const h=f.map(m=>`${m.shardKey}: ${m.error?.message??"unknown error"}`).join("; ");throw new c(`export failed on ${String(f.length)} of ${String(d.shards.length)} shard(s) — ${h}`,{code:"EXPORT_SHARD_FAILED",status:502})}return d.shards.flatMap(h=>h.rows??[])},pn=async(e,t,n,o,a)=>{const i=o??e.listSchemaTables?.();o===void 0&&e.listSchemaTables===void 0&&console.warn("[lunora] export: no table list available (`listSchemaTables` is unset and no `tables` were named), so only the default shard is reachable. A `.shardBy()` deployment's other shards will be missing from this export. Name the tables explicitly, or regenerate the worker so codegen supplies the list.");const{globalTables:d,shardLocalTables:f}=Lo(e,i),h=await jo(t,n,i,f,a,e.defaultShardKey??"__root__"),m=e.exportGlobals,b=o===void 0||d.length>0;return(async function*(){yield*h,b&&m&&(yield*m({tables:d}))})()},Mo=async(e,t,n,o,a,i)=>{for await(const d of await pn(e,t,n,o,i))a(d)},$o=new TextEncoder,Fo=1e3,mn=10,Ko=200,Nt=8,wn="lunoraBackupCron",Ut=24*1048576,Ct=e=>{const t=e.slice(0,mn).map(o=>sn(o)),n=e.length-t.length;return`${t.join(", ")}${n>0?` (+${String(n)} more)`:""}`},Go=(e,t)=>{const n=new Uint8Array(new ArrayBuffer(t));let o=0;for(const a of e)n.set(a,o),o+=a.byteLength;return n},st=async(e,t,n,o)=>{if(n===void 0||!Number.isInteger(n)||n<=0)return{eligible:0,stale:[]};const a=[];let i;for(let d=0;d<Fo;d+=1){const f=await e.list({cursor:i,include:["customMetadata"],prefix:t});for(const h of f.objects)Cr(h.key)&&h.customMetadata?.[wn]===o&&a.push(h.key);if(!f.truncated||f.cursor===void 0)break;i=f.cursor}return{eligible:a.length,stale:a.toSorted((d,f)=>f.localeCompare(d)).slice(n)}},Qo=async(e,t,n,o,a)=>{const{stale:i}=await st(e,t,n,o),d=new Set(a),f=i.filter(k=>d.has(k)),h=f.slice(0,Ko),m=i.length-h.length,b=a.length-f.length;if(h.length===0)return{deleted:[],failed:[],ignored:b,remaining:m};const S=[],T=[];for(let k=0;k<h.length;k+=Nt){const w=await Promise.allSettled(h.slice(k,k+Nt).map(async g=>(await e.delete(sn(g)),await e.delete(g),g)));for(const[g,y]of w.entries())y.status==="fulfilled"?S.push(y.value):T.push(h[k+g])}return S.length>0&&console.info(`[lunora] backup prune kept the newest ${String(n)} and deleted ${String(S.length)}: ${Ct(S)}`),T.length>0&&console.warn(`[lunora] backup prune failed to remove ${String(T.length)}: ${Ct(T)}`),{deleted:S,failed:T,ignored:b,remaining:m}},Wo=async e=>{const t=e.backupStore;if(!t)throw new c("backup retention preview requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});const n=nt(e.backupPrefix??rt),o=e.backupCron,{eligible:a,stale:i}=o===void 0?{eligible:0,stale:[]}:await st(t,n,e.backupRetain,o);return{cron:o,eligible:a,keep:e.backupRetain??0,prefix:n,wouldDelete:i}},zo=async(e,t,n,o,a)=>{const i=e.backupStore;if(!i)throw new c("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!o||o.length===0)throw new c("scheduled backup requires an `adminToken` (or `env.LUNORA_ADMIN_TOKEN`) to authenticate the per-shard export gate",{code:"BACKUP_NOT_CONFIGURED",status:500});const d={authorization:`Bearer ${o}`,"content-type":"application/json"},f=e.backupTables;let h=0,m=0,b=[];await Mo(e,t,d,f,I=>{const E=$o.encode(`${JSON.stringify(I)}
2
2
  `);if(h+=1,m+=E.byteLength,m>Ut)throw new c(`scheduled backup reached ${String(m)} bytes of NDJSON, past the ${String(Ut)}-byte limit for a snapshot assembled inside a Worker — nothing was written. Narrow it with \`backupTables\`, or take this snapshot off-platform with \`lunora backup create --bucket\`.`,{code:"BACKUP_TOO_LARGE",status:507});b.push(E)},n);const T=nt(e.backupPrefix??rt),k=new Date(a.scheduledTime).toISOString(),w=Br(T,k),g=Go(b,m);b=[];const y=Hr(await crypto.subtle.digest("SHA-256",g));await i.put(w,g,{httpMetadata:{contentType:"application/x-ndjson"},sha256:y});const v={bytes:m,createdAt:k,cron:a.cron,file:w,id:k,rows:h,scheduledTime:a.scheduledTime,sha256:y,...f?{tables:f.join(",")}:{}};await i.put(xr(w),`${JSON.stringify(v,void 0,2)}
3
3
  `,{customMetadata:{[wn]:a.cron},httpMetadata:{contentType:"application/json"}});try{const{stale:I}=await st(i,T,e.backupRetain,a.cron);if(I.length>0){const E=I.slice(0,mn),j=I.length-E.length;console.info(`[lunora] backup retention: ${String(I.length)} snapshot(s) past the newest ${String(e.backupRetain)} — run \`lunora backup prune\` to remove them: ${E.join(", ")}${j>0?` (+${String(j)} more)`:""}`)}}catch(I){console.warn(`[lunora] backup ${w} was written, but the retention report failed:`,I)}},Vo=async(e,t)=>{const n=e.backupStore;if(!n)throw new c("backup prune requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});const o=e.backupCron,a=e.backupRetain;if(o===void 0||a===void 0||!Number.isInteger(a)||a<=0)throw new c("backup prune needs a retention window: set `backupRetain` (and `backupCron`, which decides whose snapshots retention owns) on the worker. Without one there is nothing past the window to remove.",{code:"BACKUP_RETENTION_NOT_CONFIGURED",status:400});return Qo(n,nt(e.backupPrefix??rt),a,o,t)},Jo="/_lunora/admin/backup/retention",Yo="/_lunora/admin/backup/prune",qo=e=>{const{options:t,readJsonBody:n,requireAdminOption:o}=e,a=(f,h)=>{o(f,t.backupStore,{code:"BACKUP_NOT_CONFIGURED",message:`backup ${h} requires a \`backupStore\` on the worker`})},i=async f=>(M(f,"GET","Backup-retention"),a(f,"retention preview"),Response.json(await Wo(t),{headers:{"cache-control":"no-store"}})),d=async f=>{M(f,"POST","Backup-prune"),a(f,"prune");const{confirm:h}=await n(f);if(!Array.isArray(h)||h.some(m=>typeof m!="string"))throw new c("backup prune requires a `confirm` array of the sidecar keys to remove — read them from `GET /_lunora/admin/backup/retention` and pass back the ones you mean to delete",{code:"BAD_REQUEST",status:400});return Response.json(await Vo(t,h),{headers:{"cache-control":"no-store"}})};return{[Yo]:d,[Jo]:i}},Bt=500,Xo=(e,t,n)=>{if(typeof e!="object"||e===null||Array.isArray(e))throw new c("each batch call must be an object",{code:"BAD_REQUEST",status:400});const o=e;if(typeof o.functionPath!="string")throw new c("each batch call needs a string `functionPath`",{code:"BAD_REQUEST",status:400});if(o.functionPath.startsWith("__lunora_relation__:")||o.functionPath.startsWith("__lunora_admin__"))throw new c("reserved function path cannot be batched",{code:"FORBIDDEN",status:403});if(o.args!==void 0&&(typeof o.args!="object"||o.args===null||Array.isArray(o.args)))throw new c("each batch call `args` must be an object",{code:"BAD_REQUEST",status:400});if(o.id!==void 0&&typeof o.id!="number")throw new c("each batch call `id` must be a number",{code:"BAD_REQUEST",status:400});return{entry:{args:o.args===void 0?{}:o.args,baselineSeq:typeof o.baselineSeq=="number"?o.baselineSeq:void 0,clientId:typeof o.clientId=="string"?o.clientId:void 0,clientSeq:typeof o.clientSeq=="number"?o.clientSeq:void 0,functionPath:o.functionPath,id:typeof o.id=="number"?o.id:t,mutationId:typeof o.mutationId=="string"?o.mutationId:void 0},shardKey:typeof o.shardKey=="string"?o.shardKey:n}},Zo=(e,t)=>{if(e.length>Bt)throw new c(`RPC batch exceeds the ${String(Bt)}-call limit`,{code:"BAD_REQUEST",status:400});const n=new Map,o=new Set;for(const[a,i]of e.entries()){const{entry:d,shardKey:f}=Xo(i,a,t);if(o.has(d.id))throw new c(`batch call id ${String(d.id)} is used twice; ids must be distinct`,{code:"BAD_REQUEST",status:400});o.add(d.id);const h=n.get(f)??[];h.push(d),n.set(f,h)}return n},ea="/_lunora/admin/export",ta="/_lunora/admin/import",na="/_lunora/admin/sync",ra="/_lunora/admin/connector/sync",oa="/_lunora/admin/apply",aa="/_lunora/admin/export-tap/run",sa=new TextEncoder,ia=async e=>{const n=await ne(e,"Export")??{};if(n.tables===void 0)return{tables:void 0};if(!Array.isArray(n.tables))throw new c("Export `tables` must be a string array",{code:"BAD_REQUEST",status:400});const o=[];for(const a of n.tables){if(typeof a!="string"||a.length===0)throw new c("Export `tables` entries must be non-empty strings",{code:"BAD_REQUEST",status:400});o.push(a)}return{tables:o}},Ke=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):void 0,ca=e=>{const{applyGlobals:t,defaultShardKey:n,exportCursorStore:o,exportSinks:a,knownTables:i,queryCoordinator:d,assertAdmin:f,resolveForwardContext:h,shardDO:m,prepareExportRows:b,streamingImport:S,syncGlobals:T}=e,k=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;f(E);const U=await ia(E),{headers:F}=await h(E,j),W=await b(F,U.tables),J=new ReadableStream({async pull(Y){try{for await(const G of W)Y.enqueue(sa.encode(`${JSON.stringify(G)}
4
4
  `));Y.close()}catch(G){Y.error(G)}}});return new Response(J,{headers:{"content-type":"application/x-ndjson"},status:200})},w=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;f(E);const U=await ee(E),F=typeof U.cursors=="object"&&U.cursors!==null?U.cursors:{},W=typeof U.epochs=="object"&&U.epochs!==null?U.epochs:{},J=typeof U.limit=="number"?U.limit:void 0,Y=typeof U.globalCursor=="number"?U.globalCursor:0,G=Ke(U.tables),{headers:re}=await h(E,j),Q=G??i(),de=await d.orchestrateCdcSync(m,{cursors:F,defaultShardKey:n,epochs:W,headers:re,limit:J,tables:Q}),oe=T?await T({limit:J,sinceSeq:Y}):void 0;return Response.json({global:oe,shards:de.shards},{status:200})},g=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;f(E);const U=await ee(E),F=Fr(U.cursor),W=typeof U.limit=="number"&&U.limit>0?U.limit:void 0,J=Ke(U.tables),{headers:Y}=await h(E,j),G=J??i(),re=await d.orchestrateCdcSync(m,{cursors:F.s,defaultShardKey:n,headers:Y,limit:W,tables:G}),Q=[],de={...F.s};let oe=!1;for(const se of re.shards)oe=At(Q,se.changes??[],Gr(W))||oe,de[se.shardKey]=se.cursor;let be=F.g;if(T){const se=await T({limit:W,sinceSeq:F.g});oe=At(Q,se.changes,W)||oe,be=se.cursor}const z=Kr({g:be,s:de,v:1}),ae={changes:Q,hasMore:oe,nextCursor:z};return Response.json(ae,{status:200})},y=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;f(E);const U=await ee(E),W=(Array.isArray(U.batches)?U.batches:[]).map(Q=>Q).filter(Q=>Q!==null&&typeof Q=="object"&&typeof Q.shardKey=="string"&&Array.isArray(Q.changes)),J=Array.isArray(U.globalChanges)?U.globalChanges:[],{headers:Y}=await h(E,j),G=await d.orchestrateApplyCdc(m,{batches:W,headers:Y}),re=J.length>0&&t?await t({changes:J}):0;return Response.json({applied:G.applied+re,failed:G.failed,ok:G.ok},{status:200})},v=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;f(E);const{headers:U}=await h(E,j),F=await S(E,U);return Response.json(F,{headers:{"content-type":"application/json"},status:F.failed.length>0?207:200})},I=async(E,j)=>{const H=we(E,["POST"]);if(H)return H;if(f(E),a===void 0||Object.keys(a).length===0||o===void 0)throw new c("Export-tap endpoint requires `exportSinks` + `exportCursorStore` on the worker",{code:"EXPORT_TAP_NOT_CONFIGURED",status:400});const U=await ee(E),F=typeof U.sink=="string"?U.sink:void 0,W=typeof U.limit=="number"&&U.limit>0?U.limit:void 0,J=Ke(U.tables);if(F===void 0)throw new c("Export-tap `sink` must name a configured sink",{code:"BAD_REQUEST",status:400});const Y=a[F];if(Y===void 0)throw new c(`Export-tap sink "${F}" is not configured`,{code:"NOT_FOUND",status:404});const{headers:G}=await h(E,j),re=J??i(),Q=await $r({coordinator:d,cursorStore:o,defaultShardKey:n,headers:G,limit:W,shardDO:m,sink:Y,tables:re});return Response.json(Q,{headers:{"content-type":"application/json"},status:200})};return{[oa]:y,[ra]:g,[ea]:k,[aa]:I,[ta]:v,[na]:w}},da=(e,t)=>{let n;try{n=JSON.parse(e)}catch{return{error:{code:"BAD_ROW",line:t,message:"line is not valid JSON",table:""},ok:!1}}if(!n||typeof n!="object"||Array.isArray(n))return{error:{code:"BAD_ROW",line:t,message:"row must be a JSON object",table:""},ok:!1};const o=n;return typeof o.table!="string"||o.table.length===0?{error:{code:"BAD_ROW",line:t,message:"row is missing `table`",table:""},ok:!1}:!o.doc||typeof o.doc!="object"||Array.isArray(o.doc)?{error:{code:"BAD_ROW",line:t,message:"row is missing or malformed `doc`",table:o.table},ok:!1}:{doc:o.doc,ok:!0,table:o.table}},ua=(e,t,n,o,a)=>{if(n?.mode.kind==="shardBy"&&typeof n.mode.field=="string"){const i=e[n.mode.field];return i==null?{error:{code:"BAD_ROW",line:a,message:`row missing shard field "${n.mode.field}" for table "${t}"`,table:t},ok:!1}:{ok:!0,shardKey:typeof i=="string"?i:JSON.stringify(i)}}return{ok:!0,shardKey:o}},la=async(e,t,n)=>{if(!e.body)throw new c("Import endpoint requires a request body",{code:"BAD_REQUEST",status:400});const o=[],a=[],i=new Map;let d=0,f=0;const h=e.body.getReader(),m=new TextDecoder;let b="",S=0;const T=k=>{f+=1;const w=k.trim();if(w.length===0)return;d+=1;const g=da(w,f);if(!g.ok){o.push(g.error);return}const{doc:y,table:v}=g,I=t.resolveTableSharding?.(v);if(I?.mode.kind==="global"){a.push({doc:y,line:f,table:v});return}const E=ua(y,v,I,n,f);if(!E.ok){o.push(E.error);return}const j=i.get(E.shardKey);j?j.rows.push({doc:y,table:v}):i.set(E.shardKey,{rows:[{doc:y,table:v}],shardKey:E.shardKey,startLine:f})};for(;;){const{done:k,value:w}=await h.read();if(k)break;if(w&&(S+=w.byteLength,S>rn))throw await h.cancel().catch(()=>{}),new c("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});b+=m.decode(w,{stream:!0});let g=b.indexOf(`
@@ -1 +1 @@
1
- import{toErrorBody as I}from"@lunora/errors";import{b as U,a as F}from"./base64-Bl1_r2k1.mjs";import{LunoraError as v}from"./LunoraError-DksAgIpa.mjs";import{resolveShard as V}from"./applyJurisdiction-C0ddU7Tg.mjs";const ke=r=>({listShardKeys(e){return r[e]??[]}}),be=(r,e)=>({listShardKeys(s){if(r===void 0)throw new v(`cannot discover the shards of "${s}": the worker has no \`resolveTableSharding\` to tell a sharded table from a root one, and no shard registry is configured`,{code:"BAD_REQUEST",status:400});const o=r(s)?.mode.kind;if(o==="shardBy")throw new v(`cannot discover the shards of "${s}": it is \`.shardBy()\` and the worker has no shard registry — declare \`.shardRegistry((env) => env.SHARD_REGISTRY)\` on the app builder and bind \`SHARD_REGISTRY\` to \`ShardRegistryDO\` (or pass \`queryCoordinator\` to \`createWorker\`)`,{code:"BAD_REQUEST",status:400});return o==="global"?[]:[e]}}),P=16,x=5e3,y=r=>r!==null&&typeof r=="object"&&"result"in r?r.result:r,L=r=>{const e=r??{};return{changed:typeof e.changed=="number"?e.changed:0,processed:typeof e.processed=="number"?e.processed:0,status:typeof e.status=="string"?e.status:void 0}},$=(r,e)=>r?"failed":e?"in_progress":"completed",j=r=>{const e=[];let s=0,o=0,t=0,n=0,a=!1,c=!1;for(const d of r){if(d.kind==="err"){o+=1,e.push({error:{message:d.message,timedOut:d.timedOut},shardKey:d.shardKey});continue}s+=1;const i=y(d.value),u=L(i);t+=u.changed,n+=u.processed,a||=u.status==="in_progress",c||=u.status==="failed",e.push({result:i,shardKey:d.shardKey})}return{changed:t,failed:o,ok:s,processed:n,shards:e,status:$(c,a||o>0)}},G=r=>{const e=r??{};return{before:typeof e.before=="number"&&Number.isFinite(e.before)?e.before:0,total:typeof e.total=="number"&&Number.isFinite(e.total)?e.total:0}},H=r=>{const e=[];let s=0,o=0,t=0,n=0;for(const a of r){if(a.kind==="err"){o+=1,e.push({error:{message:a.message,timedOut:a.timedOut},shardKey:a.shardKey});continue}s+=1;const c=G(y(a.value));t+=c.before,n+=c.total,e.push({result:c,shardKey:a.shardKey})}return{failed:o,ok:s,partial:o>0,position:t+1,shards:e,total:n}},B=0,D=1,J=2,k=(r,e)=>r<e?-1:r>e?1:0,E=r=>r==null?B:typeof r=="number"?D:J,O=(r,e)=>{const s=E(r),o=E(e);return s!==o?s<o?-1:1:s===B?0:s===D?k(r,e):k(String(r),String(e))},Q=(r,e,s)=>{const o=O(r.partitionKey,e.partitionKey);if(o!==0)return o;const t=Math.max(r.sortValues.length,e.sortValues.length);for(let n=0;n<t;n+=1){const a=O(r.sortValues[n],e.sortValues[n]);if(a!==0)return s[n]==="desc"?-a:a}return O(r.rowId,e.rowId)},Y=r=>F(new TextEncoder().encode(JSON.stringify(r))),W=r=>{try{const e=JSON.parse(new TextDecoder().decode(U(r)));if(e!==null&&typeof e=="object"&&"perShard"in e){const{perShard:s}=e;if(s!==null&&typeof s=="object")return{perShard:s}}}catch{}return{perShard:{}}},X=r=>{const e=r??{},s=Array.isArray(e.rows)?e.rows:[];return{directions:Array.isArray(e.directions)?e.directions:[],hasMore:e.hasMore===!0,rows:s}},z=(r,e)=>{let s;for(const o of r){const t=o.rows[o.head];t!==void 0&&(s===void 0||Q(t.key,s.row.key,e)<0)&&(s={row:t,slice:o})}return s},Z=(r,e)=>{let s=!1;const o=new Set;for(const n of r)o.add(n.shardKey),(n.head<n.rows.length||n.hasMore)&&(s=!0);const t={...e};for(const n of Object.keys(e))o.has(n)||(s=!0);return s?Y({perShard:t}):null},q=(r,e,s,o)=>{const t=[],n={...o};for(;t.length<e;){const c=z(r,s);if(c===void 0)break;t.push(c.row.doc),n[c.slice.shardKey]=c.row.key,c.slice.head+=1}const a=Z(r,n);return{isDone:a===null,nextCursor:a,page:t}},ee=r=>{const e=[];let s=0,o=0;for(const t of r){if(t.kind==="err"){o+=1,e.push({error:{message:t.message,timedOut:t.timedOut},shardKey:t.shardKey});continue}s+=1;const n=y(t.value),a=Array.isArray(n?.rows)?n.rows:[];e.push({rows:a,shardKey:t.shardKey})}return{failed:o,ok:s,shards:e}},re=r=>{const e=[];let s=0,o=0;for(const{outcome:t,sinceEpoch:n,sinceSeq:a}of r){if(t.kind==="err"){o+=1,e.push({cursor:a,error:{code:t.code,message:t.message,timedOut:t.timedOut},shardKey:t.shardKey,...n===void 0?{}:{epoch:n}});continue}s+=1;const c=y(t.value),d=Array.isArray(c?.changes)?c.changes:[],i=typeof c?.cursor=="number"?c.cursor:a,u=typeof c?.epoch=="string"&&c.epoch.length>0?c.epoch:n;e.push({changes:d,cursor:i,shardKey:t.shardKey,...u===void 0?{}:{epoch:u}})}return{failed:o,ok:s,shards:e}},te=r=>{let e=0,s=0,o=0;for(const t of r){if(t.kind==="err"){s+=1;continue}e+=1;const n=y(t.value);o+=typeof n?.applied=="number"?n.applied:0}return{applied:o,failed:s,ok:e}},se=r=>{const e=r??{};return typeof e.requests=="number"&&Number.isFinite(e.requests)&&e.requests>=0?e.requests:0},oe=r=>{const e=[];let s=0,o=0;for(const t of r){if(t.kind==="err"){o+=1,e.push({requests:0,shardKey:t.shardKey});continue}s+=1,e.push({requests:se(y(t.value)),shardKey:t.shardKey})}return{failed:o,ok:s,shards:e}},ne=r=>{const e=[],s={},o=[];let t=0,n=0,a=0;for(const c of r){if(c.kind==="err"){a+=1,e.push({error:{message:c.message,timedOut:c.timedOut},shardKey:c.shardKey});continue}n+=1;const d=y(c.value),i=d?.inserted??{};for(const[l,f]of Object.entries(i))s[l]=(s[l]??0)+f;const u=d?.errors;Array.isArray(u)&&o.push(...u),t+=d?.conflicts??0,e.push({result:{conflicts:d?.conflicts??0,errors:d?.errors??[],inserted:i},shardKey:c.shardKey})}return{conflicts:t,errors:o,failed:a,inserted:s,ok:n,shards:e}},m=r=>({body:JSON.stringify({args:r.args??{},functionPath:r.functionPath}),headers:{"content-type":"application/json",...r.headers}}),ae=async r=>{try{const s=(await r.json())?.error;return typeof s?.code!="string"||s.code.length===0?void 0:{code:s.code,message:typeof s.message=="string"?s.message:""}}catch{return}},g=async(r,e,s,o)=>{const t=V(r,e),n=new AbortController,a=new Request("https://shard.internal/rpc",{body:s.body,headers:s.headers,method:"POST",signal:n.signal});let c;const d=new Promise(u=>{c=setTimeout(()=>{try{n.abort()}catch{}u({code:"SHARD_TIMEOUT",kind:"err",message:`shard "${e}" timed out after ${String(o)}ms`,shardKey:e,timedOut:!0})},o)}),i=(async()=>{try{const u=await t.fetch(a);if(!u.ok){const f=await ae(u),p=`shard "${e}" returned ${String(u.status)}`;return{code:f?.code??"SHARD_HTTP_ERROR",kind:"err",message:f===void 0||f.message.length===0?p:`${p}: ${f.message}`,shardKey:e,timedOut:!1}}const l=await u.json();return{kind:"ok",shardKey:e,value:l}}catch(u){const{body:l}=I(u,{fallbackCode:"INTERNAL",redactedMessage:"shard call failed"});return{code:l.code,kind:"err",message:`shard "${e}" failed: ${l.message}`,shardKey:e,timedOut:!1}}})();try{return await Promise.race([i,d])}finally{c!==void 0&&clearTimeout(c)}},w=async(r,e,s)=>{if(r.length===0)return[];const o=Array.from({length:r.length});let t=0;const n=async()=>{for(;;){const c=t;t+=1;const d=r[c];if(c>=r.length||d===void 0)return;o[c]=await s(d,c)}},a=Math.min(e,r.length);return await Promise.all(Array.from({length:a},()=>n())),o},K=(r,e)=>r.length>0||e===null?r:[e],T=async(r,e,s)=>{const o=await Promise.all(e.map(async t=>K(await r.listShardKeys(t),s)));return[...new Set(o.flat())]},S=async(r,e,s,o,t)=>{const n=m(s);return w(e,o,async a=>g(r,a,n,t))},ce=r=>{const e={};for(const s of Object.keys(r).toSorted(k))e[s]=r[s]??null;return JSON.stringify(e)},ie=r=>r.flatMap(e=>Array.isArray(e)?e:[]),de=(r,e,s)=>{switch(s){case"max":return Math.max(r,e);case"min":return Math.min(r,e);case"sum":return r+e;default:return r}},ue=(r,e,s)=>{if(e===null||typeof e!="object")return;const o=e.key??{},t=e.value??null,n=ce(o),a=r.get(n);if(!a){r.set(n,{key:o,value:t});return}if(a.value===null){a.value=t;return}t!==null&&(a.value=de(a.value,t,s))},le=(r,e)=>{const s=new Map;for(const o of r)if(Array.isArray(o))for(const t of o)ue(s,t,e);return[...s.values()]},M=(r,e)=>{let s=null;for(const o of r)typeof o=="number"&&Number.isFinite(o)&&(s=s===null?o:e(s,o));return s},he=r=>{let e=0;for(const s of r)typeof s=="number"&&Number.isFinite(s)&&(e+=s);return e},fe=r=>{let e=0,s=0;for(const o of r){if(o===null||typeof o!="object")continue;const t=o;typeof t.before=="number"&&Number.isFinite(t.before)&&(e+=t.before),typeof t.total=="number"&&Number.isFinite(t.total)&&(s+=t.total)}return{position:e+1,total:s}},ye=(r,e)=>{const s=[];for(const t of r)if(Array.isArray(t))for(const n of t){if(n===null||typeof n!="object")continue;const a=n[e.by],c=typeof a=="number"&&Number.isFinite(a)?a:Number.NEGATIVE_INFINITY;s.push({row:n,score:c})}const o=e.direction??"desc";return s.sort((t,n)=>o==="asc"?k(t.score,n.score):k(n.score,t.score)),s.slice(0,e.k).map(t=>t.row)},pe=(r,e)=>{switch(e.kind){case"concat":return ie(r);case"first":return r[0];case"groupBy":return le(r,e.op??"sum");case"max":return M(r,Math.max);case"min":return M(r,Math.min);case"rank":return fe(r);case"sum":return he(r);case"topK":return ye(r,e);default:return r}},N=(r,e)=>(Array.isArray(e)?e:[]).filter(s=>typeof s=="string").map(s=>({shardKey:r,table:s})),Ke=async(r,e,s)=>{const o=new Map,t=await Promise.all(s.tables.map(async i=>({keys:await r.listShardKeys(i),table:i})));for(const{keys:i,table:u}of t)for(const l of i)o.set(l,[...o.get(l)??[],u]);const n=await w([...o],P,async([i,u])=>({outcome:await g(e,i,m({args:{dryRun:s.dryRun===!0,tables:u},functionPath:"__lunora_admin__:releaseShardRegistration",headers:s.headers}),x),tables:u})),a=[],c=[],d=[];for(const{outcome:i,tables:u}of n){if(i.kind==="err"){a.push({message:i.message,shardKey:i.shardKey,tables:u});continue}const l=y(i.value)??{};c.push(...N(i.shardKey,l.kept)),d.push(...N(i.shardKey,l.released))}if(s.dryRun!==!0)for(const i of new Set(d.map(u=>u.table)))r.invalidate?.(i);return{failed:a,kept:c,released:d}},_e=r=>{const e=r.maxConcurrency??P,s=r.perShardTimeoutMs??x;if(e<1)throw new v("maxConcurrency must be >= 1",{code:"BAD_REQUEST",status:400});return{async fanOut(o,t){const n=await r.registry.listShardKeys(t.fanOut.table),a=await S(o,n,t,e,s),c=[],d=[];for(const i of a)i.kind==="ok"?c.push(i.value):d.push({code:i.code,message:i.message,shardKey:i.shardKey,timedOut:i.timedOut});return{data:pe(c,t.fanOut.merge),errors:d,failed:d.length,ok:c.length}},async orchestrateExport(o,t){const n=await T(r.registry,t.tables,t.defaultShardKey),a=K(n,t.defaultShardKey),c={args:{...t.args,tables:[...t.tables]},functionPath:"__lunora_admin__:exportShard",headers:t.headers},d=await S(o,a,c,e,s);return ee(d)},async orchestrateCdcSync(o,t){const n=K(await T(r.registry,t.tables,t.defaultShardKey),t.defaultShardKey),a=t.cursors??{},c=t.epochs??{},d=await w(n,e,async i=>{const u=a[i]??0,l=c[i];return{outcome:await g(o,i,m({args:{limit:t.limit,sinceEpoch:l,sinceSeq:u},functionPath:"__lunora_admin__:cdcSync",headers:t.headers}),s),sinceEpoch:l,sinceSeq:u}});return re(d)},async orchestrateImport(o,t){const{batches:n}=t,a=await w(n,e,async c=>g(o,c.shardKey,m({args:{rows:[...c.rows],startLine:c.startLine??1},functionPath:"__lunora_admin__:importShard",headers:t.headers}),s));return ne(a)},async orchestrateApplyCdc(o,t){const{batches:n}=t,a=await w(n,e,async c=>g(o,c.shardKey,m({args:{changes:[...c.changes]},functionPath:"__lunora_admin__:applyCdc",headers:t.headers}),s));return te(a)},async orchestrateMigration(o,t){const n=K(await r.registry.listShardKeys(t.table),t.defaultShardKey),a=await S(o,n,t,e,s);return j(a)},async orchestrateRank(o,t){const n=await r.registry.listShardKeys(t.table),a={args:{index:t.index,partitionKey:t.partitionKey,rowId:t.rowId,sortValues:[...t.sortValues],table:t.table},functionPath:"__lunora_admin__:rankBefore",headers:t.headers},c=await S(o,n,a,e,s);return H(c)},async orchestrateRankPage(o,t){const n=await r.registry.listShardKeys(t.table),a=Math.max(1,Math.min(1e3,Math.floor(t.take??100))),c=t.directions??[],d=t.cursor?W(t.cursor):{perShard:{}},i=await w(n,e,async h=>{const C=d.perShard[h],R={index:t.index,table:t.table,take:a};t.partitionKey!==void 0&&(R.partitionKey=t.partitionKey),C!==void 0&&(R.after=C);const b=await g(o,h,m({args:R,functionPath:"__lunora_admin__:rankPage",headers:t.headers}),s);if(b.kind==="err")return{error:{message:b.message,timedOut:b.timedOut},shardKey:h};const A=X(y(b.value));return{directions:A.directions,hasMore:A.hasMore,rows:A.rows,shardKey:h}}),u=[];let l=0,f=0,p;for(const h of i){if(h.error){f+=1;continue}l+=1,p===void 0&&h.directions&&h.directions.length>0&&(p=h.directions),u.push({hasMore:h.hasMore??!1,head:0,rows:h.rows??[],shardKey:h.shardKey})}const _=q(u,a,p??c,d.perShard);return{continueCursor:_.nextCursor,failed:f,isDone:_.isDone,ok:l,page:_.page,partial:f>0,shards:i}},async orchestrateShardTraffic(o,t){const n=await r.registry.listShardKeys(t.table),a={functionPath:"__lunora_admin__:getMetrics",headers:t.headers},c=await S(o,n,a,e,s);return oe(c)},registry:r.registry}};export{be as createDefaultShardRegistry,_e as createQueryCoordinator,ke as createStaticShardRegistry,Ke as pruneShardRegistry};
1
+ import{toErrorBody as I}from"@lunora/errors";import{b as U,a as F}from"./base64-Bl1_r2k1.mjs";import{LunoraError as v}from"./LunoraError-DksAgIpa.mjs";import{resolveShard as V}from"./applyJurisdiction-D4vryLhj.mjs";const ke=r=>({listShardKeys(e){return r[e]??[]}}),be=(r,e)=>({listShardKeys(s){if(r===void 0)throw new v(`cannot discover the shards of "${s}": the worker has no \`resolveTableSharding\` to tell a sharded table from a root one, and no shard registry is configured`,{code:"BAD_REQUEST",status:400});const o=r(s)?.mode.kind;if(o==="shardBy")throw new v(`cannot discover the shards of "${s}": it is \`.shardBy()\` and the worker has no shard registry — declare \`.shardRegistry((env) => env.SHARD_REGISTRY)\` on the app builder and bind \`SHARD_REGISTRY\` to \`ShardRegistryDO\` (or pass \`queryCoordinator\` to \`createWorker\`)`,{code:"BAD_REQUEST",status:400});return o==="global"?[]:[e]}}),P=16,x=5e3,y=r=>r!==null&&typeof r=="object"&&"result"in r?r.result:r,L=r=>{const e=r??{};return{changed:typeof e.changed=="number"?e.changed:0,processed:typeof e.processed=="number"?e.processed:0,status:typeof e.status=="string"?e.status:void 0}},$=(r,e)=>r?"failed":e?"in_progress":"completed",j=r=>{const e=[];let s=0,o=0,t=0,n=0,a=!1,c=!1;for(const d of r){if(d.kind==="err"){o+=1,e.push({error:{message:d.message,timedOut:d.timedOut},shardKey:d.shardKey});continue}s+=1;const i=y(d.value),u=L(i);t+=u.changed,n+=u.processed,a||=u.status==="in_progress",c||=u.status==="failed",e.push({result:i,shardKey:d.shardKey})}return{changed:t,failed:o,ok:s,processed:n,shards:e,status:$(c,a||o>0)}},G=r=>{const e=r??{};return{before:typeof e.before=="number"&&Number.isFinite(e.before)?e.before:0,total:typeof e.total=="number"&&Number.isFinite(e.total)?e.total:0}},H=r=>{const e=[];let s=0,o=0,t=0,n=0;for(const a of r){if(a.kind==="err"){o+=1,e.push({error:{message:a.message,timedOut:a.timedOut},shardKey:a.shardKey});continue}s+=1;const c=G(y(a.value));t+=c.before,n+=c.total,e.push({result:c,shardKey:a.shardKey})}return{failed:o,ok:s,partial:o>0,position:t+1,shards:e,total:n}},B=0,D=1,J=2,k=(r,e)=>r<e?-1:r>e?1:0,E=r=>r==null?B:typeof r=="number"?D:J,O=(r,e)=>{const s=E(r),o=E(e);return s!==o?s<o?-1:1:s===B?0:s===D?k(r,e):k(String(r),String(e))},Q=(r,e,s)=>{const o=O(r.partitionKey,e.partitionKey);if(o!==0)return o;const t=Math.max(r.sortValues.length,e.sortValues.length);for(let n=0;n<t;n+=1){const a=O(r.sortValues[n],e.sortValues[n]);if(a!==0)return s[n]==="desc"?-a:a}return O(r.rowId,e.rowId)},Y=r=>F(new TextEncoder().encode(JSON.stringify(r))),W=r=>{try{const e=JSON.parse(new TextDecoder().decode(U(r)));if(e!==null&&typeof e=="object"&&"perShard"in e){const{perShard:s}=e;if(s!==null&&typeof s=="object")return{perShard:s}}}catch{}return{perShard:{}}},X=r=>{const e=r??{},s=Array.isArray(e.rows)?e.rows:[];return{directions:Array.isArray(e.directions)?e.directions:[],hasMore:e.hasMore===!0,rows:s}},z=(r,e)=>{let s;for(const o of r){const t=o.rows[o.head];t!==void 0&&(s===void 0||Q(t.key,s.row.key,e)<0)&&(s={row:t,slice:o})}return s},Z=(r,e)=>{let s=!1;const o=new Set;for(const n of r)o.add(n.shardKey),(n.head<n.rows.length||n.hasMore)&&(s=!0);const t={...e};for(const n of Object.keys(e))o.has(n)||(s=!0);return s?Y({perShard:t}):null},q=(r,e,s,o)=>{const t=[],n={...o};for(;t.length<e;){const c=z(r,s);if(c===void 0)break;t.push(c.row.doc),n[c.slice.shardKey]=c.row.key,c.slice.head+=1}const a=Z(r,n);return{isDone:a===null,nextCursor:a,page:t}},ee=r=>{const e=[];let s=0,o=0;for(const t of r){if(t.kind==="err"){o+=1,e.push({error:{message:t.message,timedOut:t.timedOut},shardKey:t.shardKey});continue}s+=1;const n=y(t.value),a=Array.isArray(n?.rows)?n.rows:[];e.push({rows:a,shardKey:t.shardKey})}return{failed:o,ok:s,shards:e}},re=r=>{const e=[];let s=0,o=0;for(const{outcome:t,sinceEpoch:n,sinceSeq:a}of r){if(t.kind==="err"){o+=1,e.push({cursor:a,error:{code:t.code,message:t.message,timedOut:t.timedOut},shardKey:t.shardKey,...n===void 0?{}:{epoch:n}});continue}s+=1;const c=y(t.value),d=Array.isArray(c?.changes)?c.changes:[],i=typeof c?.cursor=="number"?c.cursor:a,u=typeof c?.epoch=="string"&&c.epoch.length>0?c.epoch:n;e.push({changes:d,cursor:i,shardKey:t.shardKey,...u===void 0?{}:{epoch:u}})}return{failed:o,ok:s,shards:e}},te=r=>{let e=0,s=0,o=0;for(const t of r){if(t.kind==="err"){s+=1;continue}e+=1;const n=y(t.value);o+=typeof n?.applied=="number"?n.applied:0}return{applied:o,failed:s,ok:e}},se=r=>{const e=r??{};return typeof e.requests=="number"&&Number.isFinite(e.requests)&&e.requests>=0?e.requests:0},oe=r=>{const e=[];let s=0,o=0;for(const t of r){if(t.kind==="err"){o+=1,e.push({requests:0,shardKey:t.shardKey});continue}s+=1,e.push({requests:se(y(t.value)),shardKey:t.shardKey})}return{failed:o,ok:s,shards:e}},ne=r=>{const e=[],s={},o=[];let t=0,n=0,a=0;for(const c of r){if(c.kind==="err"){a+=1,e.push({error:{message:c.message,timedOut:c.timedOut},shardKey:c.shardKey});continue}n+=1;const d=y(c.value),i=d?.inserted??{};for(const[l,f]of Object.entries(i))s[l]=(s[l]??0)+f;const u=d?.errors;Array.isArray(u)&&o.push(...u),t+=d?.conflicts??0,e.push({result:{conflicts:d?.conflicts??0,errors:d?.errors??[],inserted:i},shardKey:c.shardKey})}return{conflicts:t,errors:o,failed:a,inserted:s,ok:n,shards:e}},m=r=>({body:JSON.stringify({args:r.args??{},functionPath:r.functionPath}),headers:{"content-type":"application/json",...r.headers}}),ae=async r=>{try{const s=(await r.json())?.error;return typeof s?.code!="string"||s.code.length===0?void 0:{code:s.code,message:typeof s.message=="string"?s.message:""}}catch{return}},g=async(r,e,s,o)=>{const t=V(r,e),n=new AbortController,a=new Request("https://shard.internal/rpc",{body:s.body,headers:s.headers,method:"POST",signal:n.signal});let c;const d=new Promise(u=>{c=setTimeout(()=>{try{n.abort()}catch{}u({code:"SHARD_TIMEOUT",kind:"err",message:`shard "${e}" timed out after ${String(o)}ms`,shardKey:e,timedOut:!0})},o)}),i=(async()=>{try{const u=await t.fetch(a);if(!u.ok){const f=await ae(u),p=`shard "${e}" returned ${String(u.status)}`;return{code:f?.code??"SHARD_HTTP_ERROR",kind:"err",message:f===void 0||f.message.length===0?p:`${p}: ${f.message}`,shardKey:e,timedOut:!1}}const l=await u.json();return{kind:"ok",shardKey:e,value:l}}catch(u){const{body:l}=I(u,{fallbackCode:"INTERNAL",redactedMessage:"shard call failed"});return{code:l.code,kind:"err",message:`shard "${e}" failed: ${l.message}`,shardKey:e,timedOut:!1}}})();try{return await Promise.race([i,d])}finally{c!==void 0&&clearTimeout(c)}},w=async(r,e,s)=>{if(r.length===0)return[];const o=Array.from({length:r.length});let t=0;const n=async()=>{for(;;){const c=t;t+=1;const d=r[c];if(c>=r.length||d===void 0)return;o[c]=await s(d,c)}},a=Math.min(e,r.length);return await Promise.all(Array.from({length:a},()=>n())),o},K=(r,e)=>r.length>0||e===null?r:[e],T=async(r,e,s)=>{const o=await Promise.all(e.map(async t=>K(await r.listShardKeys(t),s)));return[...new Set(o.flat())]},S=async(r,e,s,o,t)=>{const n=m(s);return w(e,o,async a=>g(r,a,n,t))},ce=r=>{const e={};for(const s of Object.keys(r).toSorted(k))e[s]=r[s]??null;return JSON.stringify(e)},ie=r=>r.flatMap(e=>Array.isArray(e)?e:[]),de=(r,e,s)=>{switch(s){case"max":return Math.max(r,e);case"min":return Math.min(r,e);case"sum":return r+e;default:return r}},ue=(r,e,s)=>{if(e===null||typeof e!="object")return;const o=e.key??{},t=e.value??null,n=ce(o),a=r.get(n);if(!a){r.set(n,{key:o,value:t});return}if(a.value===null){a.value=t;return}t!==null&&(a.value=de(a.value,t,s))},le=(r,e)=>{const s=new Map;for(const o of r)if(Array.isArray(o))for(const t of o)ue(s,t,e);return[...s.values()]},M=(r,e)=>{let s=null;for(const o of r)typeof o=="number"&&Number.isFinite(o)&&(s=s===null?o:e(s,o));return s},he=r=>{let e=0;for(const s of r)typeof s=="number"&&Number.isFinite(s)&&(e+=s);return e},fe=r=>{let e=0,s=0;for(const o of r){if(o===null||typeof o!="object")continue;const t=o;typeof t.before=="number"&&Number.isFinite(t.before)&&(e+=t.before),typeof t.total=="number"&&Number.isFinite(t.total)&&(s+=t.total)}return{position:e+1,total:s}},ye=(r,e)=>{const s=[];for(const t of r)if(Array.isArray(t))for(const n of t){if(n===null||typeof n!="object")continue;const a=n[e.by],c=typeof a=="number"&&Number.isFinite(a)?a:Number.NEGATIVE_INFINITY;s.push({row:n,score:c})}const o=e.direction??"desc";return s.sort((t,n)=>o==="asc"?k(t.score,n.score):k(n.score,t.score)),s.slice(0,e.k).map(t=>t.row)},pe=(r,e)=>{switch(e.kind){case"concat":return ie(r);case"first":return r[0];case"groupBy":return le(r,e.op??"sum");case"max":return M(r,Math.max);case"min":return M(r,Math.min);case"rank":return fe(r);case"sum":return he(r);case"topK":return ye(r,e);default:return r}},N=(r,e)=>(Array.isArray(e)?e:[]).filter(s=>typeof s=="string").map(s=>({shardKey:r,table:s})),Ke=async(r,e,s)=>{const o=new Map,t=await Promise.all(s.tables.map(async i=>({keys:await r.listShardKeys(i),table:i})));for(const{keys:i,table:u}of t)for(const l of i)o.set(l,[...o.get(l)??[],u]);const n=await w([...o],P,async([i,u])=>({outcome:await g(e,i,m({args:{dryRun:s.dryRun===!0,tables:u},functionPath:"__lunora_admin__:releaseShardRegistration",headers:s.headers}),x),tables:u})),a=[],c=[],d=[];for(const{outcome:i,tables:u}of n){if(i.kind==="err"){a.push({message:i.message,shardKey:i.shardKey,tables:u});continue}const l=y(i.value)??{};c.push(...N(i.shardKey,l.kept)),d.push(...N(i.shardKey,l.released))}if(s.dryRun!==!0)for(const i of new Set(d.map(u=>u.table)))r.invalidate?.(i);return{failed:a,kept:c,released:d}},_e=r=>{const e=r.maxConcurrency??P,s=r.perShardTimeoutMs??x;if(e<1)throw new v("maxConcurrency must be >= 1",{code:"BAD_REQUEST",status:400});return{async fanOut(o,t){const n=await r.registry.listShardKeys(t.fanOut.table),a=await S(o,n,t,e,s),c=[],d=[];for(const i of a)i.kind==="ok"?c.push(i.value):d.push({code:i.code,message:i.message,shardKey:i.shardKey,timedOut:i.timedOut});return{data:pe(c,t.fanOut.merge),errors:d,failed:d.length,ok:c.length}},async orchestrateExport(o,t){const n=await T(r.registry,t.tables,t.defaultShardKey),a=K(n,t.defaultShardKey),c={args:{...t.args,tables:[...t.tables]},functionPath:"__lunora_admin__:exportShard",headers:t.headers},d=await S(o,a,c,e,s);return ee(d)},async orchestrateCdcSync(o,t){const n=K(await T(r.registry,t.tables,t.defaultShardKey),t.defaultShardKey),a=t.cursors??{},c=t.epochs??{},d=await w(n,e,async i=>{const u=a[i]??0,l=c[i];return{outcome:await g(o,i,m({args:{limit:t.limit,sinceEpoch:l,sinceSeq:u},functionPath:"__lunora_admin__:cdcSync",headers:t.headers}),s),sinceEpoch:l,sinceSeq:u}});return re(d)},async orchestrateImport(o,t){const{batches:n}=t,a=await w(n,e,async c=>g(o,c.shardKey,m({args:{rows:[...c.rows],startLine:c.startLine??1},functionPath:"__lunora_admin__:importShard",headers:t.headers}),s));return ne(a)},async orchestrateApplyCdc(o,t){const{batches:n}=t,a=await w(n,e,async c=>g(o,c.shardKey,m({args:{changes:[...c.changes]},functionPath:"__lunora_admin__:applyCdc",headers:t.headers}),s));return te(a)},async orchestrateMigration(o,t){const n=K(await r.registry.listShardKeys(t.table),t.defaultShardKey),a=await S(o,n,t,e,s);return j(a)},async orchestrateRank(o,t){const n=await r.registry.listShardKeys(t.table),a={args:{index:t.index,partitionKey:t.partitionKey,rowId:t.rowId,sortValues:[...t.sortValues],table:t.table},functionPath:"__lunora_admin__:rankBefore",headers:t.headers},c=await S(o,n,a,e,s);return H(c)},async orchestrateRankPage(o,t){const n=await r.registry.listShardKeys(t.table),a=Math.max(1,Math.min(1e3,Math.floor(t.take??100))),c=t.directions??[],d=t.cursor?W(t.cursor):{perShard:{}},i=await w(n,e,async h=>{const C=d.perShard[h],R={index:t.index,table:t.table,take:a};t.partitionKey!==void 0&&(R.partitionKey=t.partitionKey),C!==void 0&&(R.after=C);const b=await g(o,h,m({args:R,functionPath:"__lunora_admin__:rankPage",headers:t.headers}),s);if(b.kind==="err")return{error:{message:b.message,timedOut:b.timedOut},shardKey:h};const A=X(y(b.value));return{directions:A.directions,hasMore:A.hasMore,rows:A.rows,shardKey:h}}),u=[];let l=0,f=0,p;for(const h of i){if(h.error){f+=1;continue}l+=1,p===void 0&&h.directions&&h.directions.length>0&&(p=h.directions),u.push({hasMore:h.hasMore??!1,head:0,rows:h.rows??[],shardKey:h.shardKey})}const _=q(u,a,p??c,d.perShard);return{continueCursor:_.nextCursor,failed:f,isDone:_.isDone,ok:l,page:_.page,partial:f>0,shards:i}},async orchestrateShardTraffic(o,t){const n=await r.registry.listShardKeys(t.table),a={functionPath:"__lunora_admin__:getMetrics",headers:t.headers},c=await S(o,n,a,e,s);return oe(c)},registry:r.registry}};export{be as createDefaultShardRegistry,_e as createQueryCoordinator,ke as createStaticShardRegistry,Ke as pruneShardRegistry};
@@ -1 +1 @@
1
- import{LunoraError as n}from"@lunora/errors";import{e as S,a as I}from"./identity-header-pR617HTs.mjs";import{O as w,a as p}from"./origin-paywall-B6eOO67m.mjs";import{e as N,d as f}from"./wire-codec-BLvSm5Mn.mjs";import{applyJurisdiction as g,resolveShard as L}from"./applyJurisdiction-C0ddU7Tg.mjs";const A=e=>{if(typeof e=="string")return e;const t=e?.__lunoraRef;if(typeof t!="string"||t.length===0)throw new n("INTERNAL","createShardClient: expected a generated function reference (api.*/internal.*) or a 'namespace:fn' string");return t},E=e=>{const t=new n(e.code,e.message);return e.data!==void 0&&(t.data=f(e.data)),t},x=(e,t={})=>{const l=g(e,t.jurisdiction),m=t.system??!0,c=r=>x(e,{...t,...r});return{as:r=>c({as:r}),asSystem:()=>c({as:void 0}),call:async(r,y,o)=>{const i=A(r),h=o?.shardKey??t.shardKey;if(h===void 0||h.length===0)throw new n("INTERNAL",`createShardClient: no shard key for "${i}" — pass one to createShardClient({ shardKey }), .forShard(key), or the call's options`);const a={"content-type":"application/json"};m&&(a[p]=w,a["x-lunora-system"]="1"),t.as&&(a["x-lunora-userid"]=S(t.as.userId),t.as.claims&&(a["x-lunora-identity"]=I(t.as.claims))),o?.mutationId!==void 0&&o.mutationId.length>0&&(a["x-lunora-mutation-id"]=o.mutationId);const s=await L(l,h).fetch(new Request("https://shard.internal/rpc",{body:JSON.stringify({args:N(y??{}),functionPath:i}),headers:a,method:"POST"})),u=s.statusText?` ${s.statusText}`:"";let d;try{d=await s.json()}catch{throw new n("INTERNAL",`createShardClient: shard response for "${i}" was not JSON (status ${String(s.status)}${u})`)}if("error"in d)throw E(d.error);if(!s.ok)throw new n("INTERNAL",`createShardClient: shard call "${i}" failed (status ${String(s.status)}${u})`);return f(d.result)},forShard:r=>c({shardKey:r})}};export{x as createShardClient};
1
+ import{LunoraError as n}from"@lunora/errors";import{e as S,a as I}from"./identity-header-pR617HTs.mjs";import{O as w,a as p}from"./origin-paywall-B6eOO67m.mjs";import{e as N,d as f}from"./wire-codec-BLvSm5Mn.mjs";import{applyJurisdiction as g,resolveShard as L}from"./applyJurisdiction-D4vryLhj.mjs";const A=e=>{if(typeof e=="string")return e;const t=e?.__lunoraRef;if(typeof t!="string"||t.length===0)throw new n("INTERNAL","createShardClient: expected a generated function reference (api.*/internal.*) or a 'namespace:fn' string");return t},E=e=>{const t=new n(e.code,e.message);return e.data!==void 0&&(t.data=f(e.data)),t},x=(e,t={})=>{const l=g(e,t.jurisdiction),m=t.system??!0,c=r=>x(e,{...t,...r});return{as:r=>c({as:r}),asSystem:()=>c({as:void 0}),call:async(r,y,o)=>{const i=A(r),h=o?.shardKey??t.shardKey;if(h===void 0||h.length===0)throw new n("INTERNAL",`createShardClient: no shard key for "${i}" — pass one to createShardClient({ shardKey }), .forShard(key), or the call's options`);const a={"content-type":"application/json"};m&&(a[p]=w,a["x-lunora-system"]="1"),t.as&&(a["x-lunora-userid"]=S(t.as.userId),t.as.claims&&(a["x-lunora-identity"]=I(t.as.claims))),o?.mutationId!==void 0&&o.mutationId.length>0&&(a["x-lunora-mutation-id"]=o.mutationId);const s=await L(l,h).fetch(new Request("https://shard.internal/rpc",{body:JSON.stringify({args:N(y??{}),functionPath:i}),headers:a,method:"POST"})),u=s.statusText?` ${s.statusText}`:"";let d;try{d=await s.json()}catch{throw new n("INTERNAL",`createShardClient: shard response for "${i}" was not JSON (status ${String(s.status)}${u})`)}if("error"in d)throw E(d.error);if(!s.ok)throw new n("INTERNAL",`createShardClient: shard call "${i}" failed (status ${String(s.status)}${u})`);return f(d.result)},forShard:r=>c({shardKey:r})}};export{x as createShardClient};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.177",
3
+ "version": "1.0.0-alpha.178",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,10 +46,10 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/bindings": "1.0.0-alpha.96",
49
+ "@lunora/bindings": "1.0.0-alpha.97",
50
50
  "@lunora/errors": "1.0.0-alpha.50",
51
- "@lunora/observability": "1.0.0-alpha.121",
52
- "@lunora/platform": "1.0.0-alpha.55"
51
+ "@lunora/observability": "1.0.0-alpha.122",
52
+ "@lunora/platform": "1.0.0-alpha.56"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@lunora/shard-engine": ">=1.0.0-alpha.24 <2.0.0-0",
@@ -1 +0,0 @@
1
- import{resolveShard as u}from"@lunora/platform";const s=new WeakMap,n=o=>o===void 0?void 0:{locationHint:o},f=o=>typeof o.idFromName=="function",a=o=>{if(!f(o))return o;const e=o,i=s.get(o);if(i!==void 0)return i;const c=typeof e.jurisdiction=="function"?r=>a(e.jurisdiction(r)):void 0,d=typeof e.getByName=="function"?{get:(r,t)=>e.get(r,n(t)),getByName:(r,t)=>e.getByName(r,n(t)),idForName:r=>e.idFromName(r),jurisdiction:c}:{get:(r,t)=>e.get(r,n(t)),idForName:r=>e.idFromName(r),jurisdiction:c};return s.set(o,d),d},y=(o,e)=>{if(e===void 0)return o;if(typeof o.jurisdiction!="function")throw new TypeError(`@lunora/runtime: Durable Object namespace does not support jurisdiction("${e}") — update @cloudflare/workers-types or remove the jurisdiction option`);return o.jurisdiction(e)},p=(o,e,i)=>u(a(o),e,i);export{y as applyJurisdiction,p as resolveShard};