@lunora/runtime 1.0.0-alpha.156 → 1.0.0-alpha.157

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
@@ -3349,7 +3349,8 @@ type StorageDownloadFunction = (key: string, options?: {
3349
3349
  * `method` and `contentType` are forwarded to the underlying signer and let the
3350
3350
  * caller mint a presigned PUT URL for large-blob uploads that bypass the
3351
3351
  * worker's body-size cap (the importer uses this for Convex storage blobs
3352
- * above the 1 MiB limit).
3352
+ * above the 1 MiB limit). `origin` is the origin the admin request reached
3353
+ * the worker on — the base to sign against when no `publicBaseUrl` is set.
3353
3354
  * Structurally compatible with `@lunora/storage`'s `Storage["getSignedUrl"]`.
3354
3355
  */
3355
3356
  type StorageSignedUrlFunction = (key: string, options?: {
@@ -3357,6 +3358,7 @@ type StorageSignedUrlFunction = (key: string, options?: {
3357
3358
  contentType?: string;
3358
3359
  expiresInSeconds?: number;
3359
3360
  method?: "GET" | "PUT";
3361
+ origin?: string;
3360
3362
  }) => Promise<string> | string;
3361
3363
  /** One `.global()` table plus its row count. Mirrors `@lunora/d1`'s `GlobalTableInfo`. */
3362
3364
  interface GlobalTableInfo {
package/dist/index.d.ts CHANGED
@@ -3349,7 +3349,8 @@ type StorageDownloadFunction = (key: string, options?: {
3349
3349
  * `method` and `contentType` are forwarded to the underlying signer and let the
3350
3350
  * caller mint a presigned PUT URL for large-blob uploads that bypass the
3351
3351
  * worker's body-size cap (the importer uses this for Convex storage blobs
3352
- * above the 1 MiB limit).
3352
+ * above the 1 MiB limit). `origin` is the origin the admin request reached
3353
+ * the worker on — the base to sign against when no `publicBaseUrl` is set.
3353
3354
  * Structurally compatible with `@lunora/storage`'s `Storage["getSignedUrl"]`.
3354
3355
  */
3355
3356
  type StorageSignedUrlFunction = (key: string, options?: {
@@ -3357,6 +3358,7 @@ type StorageSignedUrlFunction = (key: string, options?: {
3357
3358
  contentType?: string;
3358
3359
  expiresInSeconds?: number;
3359
3360
  method?: "GET" | "PUT";
3361
+ origin?: string;
3360
3362
  }) => Promise<string> | string;
3361
3363
  /** One `.global()` table plus its row count. Mirrors `@lunora/d1`'s `GlobalTableInfo`. */
3362
3364
  interface GlobalTableInfo {
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-D0x-hUTa.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-D5O7elXI.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-BlkElAL2.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-D3__w6LU.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-D1BlbZb1.mjs";import{a as Oe,b as be,c as Ae,r as Le}from"./packem_shared/rest-routes-CpbO5QEx.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-KGQR1LvR.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-BnfduQW6.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-D5O7elXI.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-BlkElAL2.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-D3__w6LU.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-D1BlbZb1.mjs";import{a as Oe,b as be,c as Ae,r as Le}from"./packem_shared/rest-routes-CpbO5QEx.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 +1 @@
1
- import{LunoraError as i}from"./LunoraError-DksAgIpa.mjs";import{a as O}from"./method-guard-BG_vJNTl.mjs";const j="/_lunora/admin/storage",P="/_lunora/admin/storage/object",B="/_lunora/admin/storage/url",C="/_lunora/admin/storage/buckets",v=10080*60,I=32*1048576,M=new Set(["GET","PUT"]),H=E=>{const w=new Uint8Array(E);let T="";for(const s of w)T+=s.toString(16).padStart(2,"0");return T},z=E=>{const{assertAdmin:w,parsePaging:T,queryParameter:s,readBodyBytes:R,requireAdminOption:d,storage:r}=E,h=e=>{const o=s(e,"key");if(o===void 0)throw new i("Storage endpoint requires a `key` query parameter",{code:"BAD_REQUEST",status:400});return o},u=e=>{const o=s(e,"bucket"),t=r.storageBuckets;if(o===void 0||t===void 0||t.length===0)return o;if(!t.includes(o))throw new i(`Unknown storage bucket \`${o}\``,{code:"NOT_FOUND",status:404});return o},U=async e=>{const o=d(e,r.storageList,{code:"STORAGE_NOT_CONFIGURED",message:"storage endpoint requires a `storageList` function on the worker"}),t=new URL(e.url),n=await o(s(t,"prefix"),{bucket:u(t),cursor:s(t,"cursor"),...T(e)});return Response.json(n,{headers:{"content-type":"application/json"},status:200})},m=e=>(O(e,"GET","Storage-buckets"),w(e),Response.json({buckets:r.storageBuckets??[]},{headers:{"content-type":"application/json"},status:200})),A=async e=>{const o=d(e,r.storageDelete,{code:"STORAGE_DELETE_NOT_CONFIGURED",message:"storage delete requires a `storageDelete` function on the worker"}),t=new URL(e.url),n=h(t);return await o(n,{bucket:u(t)}),Response.json({deleted:!0,key:n},{headers:{"content-type":"application/json"},status:200})},k=async e=>{const o=d(e,r.storageUpload,{code:"STORAGE_UPLOAD_NOT_CONFIGURED",message:"storage upload requires a `storageUpload` function on the worker"}),t=new URL(e.url),n=h(t),a=u(t),l=await R(e,I),c=e.headers.get("content-type"),_=c===null||c===""?void 0:c,g=s(t,"expectedSha256"),p=s(t,"expectedSize");let S;if(g!==void 0||p!==void 0){const L=await crypto.subtle.digest("SHA-256",l);S=H(L);const N=p!==void 0&&l.byteLength!==Number(p),f=g!==void 0&&S!==g.toLowerCase();if(N||f)throw new i("Upload failed verification — the body did not match the declared size or SHA-256 checksum, so nothing was written",{code:"STORAGE_CHECKSUM_MISMATCH",status:400})}const y=await o(n,l,{bucket:a,contentType:_,sha256:S});return Response.json(S===void 0?y:{...y,sha256:S},{headers:{"content-type":"application/json"},status:200})},b=async e=>{switch(e.method){case"DELETE":return A(e);case"GET":return U(e);case"POST":case"PUT":return k(e);default:throw new i("Storage endpoint requires GET, PUT, POST, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405})}},D=async e=>{O(e,"GET","Storage-object");const o=d(e,r.storageDownload,{code:"STORAGE_DOWNLOAD_NOT_CONFIGURED",message:"storage download requires a `storageDownload` function on the worker"}),t=new URL(e.url),n=h(t),a=await o(n,{bucket:u(t)});if(!a?.body)throw new i(`No object at key ${n}`,{code:"STORAGE_OBJECT_NOT_FOUND",status:404});return new Response(a.body,{headers:{"content-type":a.httpMetadata?.contentType??"application/octet-stream",...a.size===void 0?{}:{"content-length":String(a.size)}},status:200})},G=async e=>{O(e,"GET","Storage URL");const o=d(e,r.storageSignedUrl,{code:"STORAGE_URL_NOT_CONFIGURED",message:"storage URL endpoint requires a `storageSignedUrl` function on the worker"}),t=new URL(e.url),n=h(t),a=Number(s(t,"expiresIn")??""),l=Number.isFinite(a)&&a>0?Math.min(a,v):void 0,c=s(t,"method");if(c!==void 0&&!M.has(c))throw new i("Storage URL `method` must be GET or PUT",{code:"BAD_REQUEST",status:400});const _=c,g=s(t,"contentType"),p=await o(n,{bucket:u(t),contentType:g,expiresInSeconds:l,method:_});return Response.json({key:n,url:p},{headers:{"content-type":"application/json"},status:200})};return{[C]:m,[P]:D,[j]:b,[B]:G}};export{C as STORAGE_BUCKETS_PATH,j as STORAGE_PATH,I as STORAGE_UPLOAD_MAX_BODY_BYTES,B as STORAGE_URL_PATH,z as buildStorageAdminRoutes,H as toHex};
1
+ import{LunoraError as i}from"./LunoraError-DksAgIpa.mjs";import{a as O}from"./method-guard-BG_vJNTl.mjs";const j="/_lunora/admin/storage",P="/_lunora/admin/storage/object",B="/_lunora/admin/storage/url",C="/_lunora/admin/storage/buckets",v=10080*60,I=32*1048576,M=new Set(["GET","PUT"]),x=E=>{const w=new Uint8Array(E);let T="";for(const s of w)T+=s.toString(16).padStart(2,"0");return T},z=E=>{const{assertAdmin:w,parsePaging:T,queryParameter:s,readBodyBytes:R,requireAdminOption:d,storage:r}=E,h=e=>{const o=s(e,"key");if(o===void 0)throw new i("Storage endpoint requires a `key` query parameter",{code:"BAD_REQUEST",status:400});return o},u=e=>{const o=s(e,"bucket"),t=r.storageBuckets;if(o===void 0||t===void 0||t.length===0)return o;if(!t.includes(o))throw new i(`Unknown storage bucket \`${o}\``,{code:"NOT_FOUND",status:404});return o},U=async e=>{const o=d(e,r.storageList,{code:"STORAGE_NOT_CONFIGURED",message:"storage endpoint requires a `storageList` function on the worker"}),t=new URL(e.url),n=await o(s(t,"prefix"),{bucket:u(t),cursor:s(t,"cursor"),...T(e)});return Response.json(n,{headers:{"content-type":"application/json"},status:200})},m=e=>(O(e,"GET","Storage-buckets"),w(e),Response.json({buckets:r.storageBuckets??[]},{headers:{"content-type":"application/json"},status:200})),A=async e=>{const o=d(e,r.storageDelete,{code:"STORAGE_DELETE_NOT_CONFIGURED",message:"storage delete requires a `storageDelete` function on the worker"}),t=new URL(e.url),n=h(t);return await o(n,{bucket:u(t)}),Response.json({deleted:!0,key:n},{headers:{"content-type":"application/json"},status:200})},k=async e=>{const o=d(e,r.storageUpload,{code:"STORAGE_UPLOAD_NOT_CONFIGURED",message:"storage upload requires a `storageUpload` function on the worker"}),t=new URL(e.url),n=h(t),a=u(t),g=await R(e,I),c=e.headers.get("content-type"),_=c===null||c===""?void 0:c,l=s(t,"expectedSha256"),p=s(t,"expectedSize");let S;if(l!==void 0||p!==void 0){const L=await crypto.subtle.digest("SHA-256",g);S=x(L);const N=p!==void 0&&g.byteLength!==Number(p),f=l!==void 0&&S!==l.toLowerCase();if(N||f)throw new i("Upload failed verification — the body did not match the declared size or SHA-256 checksum, so nothing was written",{code:"STORAGE_CHECKSUM_MISMATCH",status:400})}const y=await o(n,g,{bucket:a,contentType:_,sha256:S});return Response.json(S===void 0?y:{...y,sha256:S},{headers:{"content-type":"application/json"},status:200})},b=async e=>{switch(e.method){case"DELETE":return A(e);case"GET":return U(e);case"POST":case"PUT":return k(e);default:throw new i("Storage endpoint requires GET, PUT, POST, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405})}},D=async e=>{O(e,"GET","Storage-object");const o=d(e,r.storageDownload,{code:"STORAGE_DOWNLOAD_NOT_CONFIGURED",message:"storage download requires a `storageDownload` function on the worker"}),t=new URL(e.url),n=h(t),a=await o(n,{bucket:u(t)});if(!a?.body)throw new i(`No object at key ${n}`,{code:"STORAGE_OBJECT_NOT_FOUND",status:404});return new Response(a.body,{headers:{"content-disposition":"attachment","content-type":a.httpMetadata?.contentType??"application/octet-stream","x-content-type-options":"nosniff",...a.size===void 0?{}:{"content-length":String(a.size)}},status:200})},G=async e=>{O(e,"GET","Storage URL");const o=d(e,r.storageSignedUrl,{code:"STORAGE_URL_NOT_CONFIGURED",message:"storage URL endpoint requires a `storageSignedUrl` function on the worker"}),t=new URL(e.url),n=h(t),a=Number(s(t,"expiresIn")??""),g=Number.isFinite(a)&&a>0?Math.min(a,v):void 0,c=s(t,"method");if(c!==void 0&&!M.has(c))throw new i("Storage URL `method` must be GET or PUT",{code:"BAD_REQUEST",status:400});const _=c,l=s(t,"contentType"),p=await o(n,{bucket:u(t),contentType:l,expiresInSeconds:g,method:_,origin:t.origin});return Response.json({key:n,url:p},{headers:{"content-type":"application/json"},status:200})};return{[C]:m,[P]:D,[j]:b,[B]:G}};export{C as STORAGE_BUCKETS_PATH,j as STORAGE_PATH,I as STORAGE_UPLOAD_MAX_BODY_BYTES,B as STORAGE_URL_PATH,z as buildStorageAdminRoutes,x as toHex};
@@ -1,4 +1,4 @@
1
- import{isLunoraError as hr,toErrorBody as fr}from"@lunora/errors";import{e as tn}from"./evict-oldest-BNXsKx4s.mjs";import{NOOP_EXECUTION_CONTEXT as pr}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{t as mr,f as wr}from"./base64-Bl1_r2k1.mjs";import{i as gr,e as yr,a as br,E as yt,d as _r}from"./identity-header-pR617HTs.mjs";import{O as bt,a as _t}from"./origin-paywall-B6eOO67m.mjs";import{o as ge,b as nn,p as Er,m as Rr,d as Sr,a as Ar,r as Tr}from"./otlp-resource-BI3MvjSy.mjs";import{r as Or,f as Et,a as ue,S as Rt}from"./observability-DgurIZIR.mjs";import{e as Ee,d as Xe,a as vr}from"./wire-codec-BLvSm5Mn.mjs";import{d as re,e as ie,M as rn,b as Ir,f as kr,g as on,h as sn,t as Pr}from"./rest-routes-CpbO5QEx.mjs";import{LunoraError as c,toErrorResponse as St}from"./LunoraError-DksAgIpa.mjs";import{a as $,m as we}from"./method-guard-BG_vJNTl.mjs";import{normalizeBackupPrefix as ot,BACKUP_KEY_PREFIX as st,isBackupManifestKey as Dr,backupObjectKeyOfManifest as an,backupObjectKey as Nr,backupManifestKey as Ur}from"./BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toHex as Cr,buildStorageAdminRoutes as Br,STORAGE_UPLOAD_MAX_BODY_BYTES as xr,STORAGE_PATH as Hr}from"./STORAGE_UPLOAD_MAX_BODY_BYTES-KGQR1LvR.mjs";import{b as Lr,e as jr,f as At,g as Mr,h as $r}from"./export-tap-CAyZ2TWC.mjs";import{buildHealthRoutes as Kr,durableObjectProbe as Fr,d1Probe as Gr,presenceProbe as $e}from"./HEALTH_PATH-D0i8LhwT.mjs";import{wrapResolverWithContract as Qr}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{composeIdentityResolvers as bi,routeIdentityResolvers as _i}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{buildLogArchiveAdminRoutes as Wr}from"./LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{resolveShard as ye,applyJurisdiction as Ke}from"./applyJurisdiction-C0ddU7Tg.mjs";import{resolveSecurity as Tt,handleCorsPreflight as zr,enforceOrigin as Vr,decorateResponse as Fe,enforceWebSocketOrigin as Ot}from"./decorateResponse-CRrFNW1v.mjs";const qr=e=>{const t=e??{};if(typeof t.bucket=="function")return t;const n=t.bucketName,s={...t,bucketName:typeof n=="string"&&n!==""?n:"default"};return s.bucket=()=>s,s},cn="__lunoraBranch",Jr=e=>typeof e=="object"&&e!==null&&Object.hasOwn(e,cn),Yr=`may not contain the reserved workflow branch-marker key ("${cn}")`,Xr=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}},at=(e,t)=>{const n=Math.max(e.length,t.length);let o=e.length^t.length;for(let s=0;s<n;s+=1){const i=s<e.length?e.charCodeAt(s):0,u=s<t.length?t.charCodeAt(s):0;o|=i^u}return o===0},Zr=/already[\s_-]?exists/iu,eo=e=>Zr.test(e instanceof Error?e.message:String(e)),to=(e,t,n,o)=>{const s=e.get(t);if(s!==void 0)return s;tn(e,o);const i=n().catch(u=>{throw e.get(t)===i&&e.delete(t),u});return e.set(t,i),i},it=new TextEncoder,no=Array.from({length:32},(e,t)=>t);new RegExp(`[${no.map(e=>String.fromCodePoint(e)).join("")}]`,"u");const ro=64,oo=new Map,dn=async e=>to(oo,e,async()=>crypto.subtle.importKey("raw",it.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]),ro),un=async(e,t)=>{const n=await dn(e),o=await crypto.subtle.sign("HMAC",n,it.encode(t));return mr(new Uint8Array(o))},so=async(e,t,n)=>{const o=await dn(e);return crypto.subtle.verify("HMAC",o,n,it.encode(t))},ao=["wnam","enam","sam","weur","eeur","apac","apac-ne","apac-se","oc","afr","me"];new Set(ao);const io=new Set(["AE","BH","IL","IQ","IR","JO","KW","LB","OM","PS","QA","SA","SY","TR","YE"]),co=-100,uo=15,lo=e=>{const t=Number(e.longitude??Number.NaN);switch(e.continent){case"AF":return"afr";case"AS":return e.country!==void 0&&io.has(e.country)?"me":"apac";case"EU":return Number.isFinite(t)&&t>uo?"eeur":"weur";case"NA":return Number.isFinite(t)&&t<co?"wnam":"enam";case"OC":return"oc";case"SA":return"sam";default:return}},vt=e=>{const t=e.cf;return t===void 0?void 0:lo(t)},Ze="::relay::",ho=(e,t)=>`${e}${Ze}${String(t)}`,et="::replica::",fo=(e,t)=>`${e}${et}${t}`,po=e=>{if(e==null||!/^\d+$/.test(e))return;const t=Number.parseInt(e,10);return Number.isSafeInteger(t)&&t>0?t:void 0},mo=new Set(["1","enabled","on","true","yes"]),wo=new Set(["0","disabled","false","no","off"]),go=(e,t)=>{const n=(e??"").trim().toLowerCase();return mo.has(n)?!0:wo.has(n)?!1:t},ln="v1",yo=6e4,bo=async(e,t={})=>{const n=(t.now??Date.now())+(t.ttlMs??yo),o=`${ln}.${String(n)}`,s=await un(e,o);return{expiresAtMs:n,token:`${o}.${s}`}},_o=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[s,i,u]=o;if(s!==ln||u.length===0)return!1;const h=Number(i);if(!Number.isFinite(h)||h<=n)return!1;let p;try{p=wr(u)}catch{return!1}return so(e,`${s}.${i}`,p)},D="/_lunora/admin/auth",Eo={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},U=(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},se=(e,t)=>typeof e[t]=="string"?e[t]:void 0,Ge=(e,t)=>{const n=e[t];return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:void 0},It=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},kt=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,s]of Object.entries(t))Array.isArray(s)&&s.every(i=>typeof i=="string")&&(n[o]=s);return n},Ro={[`${D}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${D}/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"},[`${D}/sessions`]:{build:({paging:e,query:t})=>({...e,userId:t("userId")}),http:"GET",method:"listSessions"},[`${D}/accounts`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listAccounts"},[`${D}/passkeys`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listPasskeys"},[`${D}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${D}/organizations/members`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listMembers"},[`${D}/organizations/invitations`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listInvitations"},[`${D}/sign-up-invitations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listSignUpInvitations"},[`${D}/sign-up-invitations/create`]:{build:({body:e})=>({email:U(e,"email"),expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,invitedBy:se(e,"invitedBy")}),http:"POST",method:"createSignUpInvitation"},[`${D}/sign-up-invitations/revoke`]:{build:({body:e})=>({email:U(e,"email")}),http:"POST",method:"revokeSignUpInvitation",returns:"void"},[`${D}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${D}/organizations/teams`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listTeams"},[`${D}/organizations/teams/members`]:{build:({paging:e,query:t})=>({...e,teamId:he(t,"teamId")}),http:"GET",method:"listTeamMembers"},[`${D}/organizations/roles`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${D}/users/create`]:{build:({body:e})=>({data:Ge(e,"data"),email:U(e,"email"),name:U(e,"name"),password:se(e,"password"),role:hn(e.role)}),http:"POST",method:"createUser"},[`${D}/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:U(e,"userId")}},http:"POST",method:"updateUser"},[`${D}/users/role`]:{build:({body:e})=>({role:It(e),userId:U(e,"userId")}),http:"POST",method:"setRole"},[`${D}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:se(e,"reason"),userId:U(e,"userId")}),http:"POST",method:"banUser"},[`${D}/users/unban`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"unbanUser"},[`${D}/users/password`]:{build:({body:e})=>({newPassword:U(e,"newPassword"),userId:U(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${D}/users/remove`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${D}/users/impersonate`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"impersonateUser"},[`${D}/sessions/revoke`]:{build:({body:e})=>({sessionId:U(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${D}/sessions/revoke-all`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${D}/accounts/unlink`]:{build:({body:e})=>({accountId:U(e,"accountId"),userId:U(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${D}/two-factor/disable`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${D}/passkeys/delete`]:{build:({body:e})=>({passkeyId:U(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${D}/organizations/members/remove`]:{build:({body:e})=>({memberId:U(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${D}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:U(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${D}/organizations/create`]:{build:({body:e})=>({logo:se(e,"logo"),metadata:Ge(e,"metadata"),name:U(e,"name"),ownerId:se(e,"ownerId"),slug:se(e,"slug")}),http:"POST",method:"createOrganization"},[`${D}/organizations/update`]:{build:({body:e})=>({logo:se(e,"logo"),metadata:Ge(e,"metadata"),name:se(e,"name"),organizationId:U(e,"organizationId"),slug:se(e,"slug")}),http:"POST",method:"updateOrganization"},[`${D}/organizations/remove`]:{build:({body:e})=>({organizationId:U(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${D}/organizations/members/add`]:{build:({body:e})=>({organizationId:U(e,"organizationId"),role:se(e,"role"),userId:U(e,"userId")}),http:"POST",method:"addMember"},[`${D}/organizations/members/invite`]:{build:({body:e})=>({email:U(e,"email"),inviterId:se(e,"inviterId"),organizationId:U(e,"organizationId"),role:se(e,"role")}),http:"POST",method:"inviteMember"},[`${D}/organizations/members/role`]:{build:({body:e})=>({memberId:U(e,"memberId"),role:It(e)}),http:"POST",method:"updateMemberRole"},[`${D}/organizations/teams/create`]:{build:({body:e})=>({name:U(e,"name"),organizationId:U(e,"organizationId")}),http:"POST",method:"createTeam"},[`${D}/organizations/teams/update`]:{build:({body:e})=>({name:U(e,"name"),teamId:U(e,"teamId")}),http:"POST",method:"updateTeam"},[`${D}/organizations/teams/remove`]:{build:({body:e})=>({teamId:U(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${D}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:U(e,"teamId"),userId:U(e,"userId")}),http:"POST",method:"addTeamMember"},[`${D}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:U(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${D}/organizations/roles/create`]:{build:({body:e})=>({organizationId:U(e,"organizationId"),permission:kt(e),role:U(e,"role")}),http:"POST",method:"createOrgRole"},[`${D}/organizations/roles/update`]:{build:({body:e})=>({permission:kt(e),roleId:U(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${D}/organizations/roles/remove`]:{build:({body:e})=>({roleId:U(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},So=e=>{const t=async s=>{try{return await s()}catch(i){if(i instanceof c)throw i;const u=i,h=typeof u.code=="string"?u.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new c("auth admin operation failed",{code:h,status:Eo[h]??500})}},n=async(s,i)=>{if(e.assertAdmin(s),s.method!==i.http)throw new c(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const u=e.getAuthAdmin();if(u===void 0)throw new c("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const h=u[i.method];if(h===void 0)throw new c(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const p=new URL(s.url),f={body:i.http==="POST"?await e.readJsonBody(s):{},paging:e.parsePaging(s),query:T=>e.queryParameter(p,T)},g=i.build(f),S=await t(()=>h(g));return Response.json(i.returns==="void"?{ok:!0}:S,{headers:{"cache-control":"no-store","content-type":"application/json"},status:200})},o={};for(const[s,i]of Object.entries(Ro))o[s]=u=>n(u,i);return o},Pt="__lunora_admin__:getAuthAuditLog",Dt=e=>typeof e=="string"&&e!==""?e:void 0,Nt=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0,Ao=e=>async(n,o)=>{e.assertAdmin(n);const s=e.getReader();if(s===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=Dt(o.actorId),u=Dt(o.event),h=Nt(o.sinceSeq),p=Nt(o.limit),f={...i===void 0?{}:{actorId:i},...u===void 0?{}:{event:u},...h===void 0?{}:{sinceSeq:h},...p===void 0?{}:{limit:p}};let g;try{g=await s.read(f)}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:g};return Response.json({result:Ee(S)},{headers:{"content-type":"application/json"},status:200})},tt="__lunora_admin__:copyAuthToJurisdiction",fn="__lunora_admin__:purgeUnpinnedAuth",To=e=>async(t,n,o)=>{if(n!==tt&&n!==fn)return;e.assertAdmin(t);const s=e.getMove();if(s===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===tt?await s.copy({force:o.force===!0}):await s.purge();return Response.json({result:Ee(i)},{headers:{"content-type":"application/json"},status:200})},Oo=(e,t)=>{const n=[],o=[];if(t&&t.length>0)for(const s of t)e.resolveTableSharding?.(s)?.mode.kind==="global"?o.push(s):n.push(s);return{globalTables:o,shardLocalTables:n}},vo=async(e,t,n,o,s,i,u)=>{if(n!==void 0&&o.length===0)return;const h=await e.orchestrateExport(i,{args:{tables:o},defaultShardKey:u,headers:t,tables:o}),p=h.shards.filter(f=>f.error);if(p.length>0){const f=p.map(g=>`${g.shardKey}: ${g.error?.message??"unknown error"}`).join("; ");throw new c(`export failed on ${String(p.length)} of ${String(h.shards.length)} shard(s) — ${f}`,{code:"EXPORT_SHARD_FAILED",status:502})}for(const f of h.shards)for(const g of f.rows??[])s(g)},pn=async(e,t,n,o,s,i)=>{const u=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:h,shardLocalTables:p}=Oo(e,u);await vo(t,n,u,p,s,i,e.defaultShardKey??"__root__");const f=e.exportGlobals;if((o===void 0||h.length>0)&&f)for await(const S of f({tables:h}))s(S)},Io=new TextEncoder,ko=1e3,mn=10,Po=200,Ut=8,wn="lunoraBackupCron",Ct=24*1048576,Bt=e=>{const t=e.slice(0,mn).map(o=>an(o)),n=e.length-t.length;return`${t.join(", ")}${n>0?` (+${String(n)} more)`:""}`},Do=(e,t)=>{const n=new Uint8Array(new ArrayBuffer(t));let o=0;for(const s of e)n.set(s,o),o+=s.byteLength;return n},ct=async(e,t,n,o)=>{if(n===void 0||!Number.isInteger(n)||n<=0)return{eligible:0,stale:[]};const s=[];let i;for(let u=0;u<ko;u+=1){const h=await e.list({cursor:i,include:["customMetadata"],prefix:t});for(const p of h.objects)Dr(p.key)&&p.customMetadata?.[wn]===o&&s.push(p.key);if(!h.truncated||h.cursor===void 0)break;i=h.cursor}return{eligible:s.length,stale:s.toSorted((u,h)=>h.localeCompare(u)).slice(n)}},No=async(e,t,n,o,s)=>{const{stale:i}=await ct(e,t,n,o),u=new Set(s),h=i.filter(w=>u.has(w)),p=h.slice(0,Po),f=i.length-p.length,g=s.length-h.length;if(p.length===0)return{deleted:[],failed:[],ignored:g,remaining:f};const S=[],T=[];for(let w=0;w<p.length;w+=Ut){const b=await Promise.allSettled(p.slice(w,w+Ut).map(async R=>(await e.delete(an(R)),await e.delete(R),R)));for(const[R,y]of b.entries())y.status==="fulfilled"?S.push(y.value):T.push(p[w+R])}return S.length>0&&console.info(`[lunora] backup prune kept the newest ${String(n)} and deleted ${String(S.length)}: ${Bt(S)}`),T.length>0&&console.warn(`[lunora] backup prune failed to remove ${String(T.length)}: ${Bt(T)}`),{deleted:S,failed:T,ignored:g,remaining:f}},Uo=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=ot(e.backupPrefix??st),o=e.backupCron,{eligible:s,stale:i}=o===void 0?{eligible:0,stale:[]}:await ct(t,n,e.backupRetain,o);return{cron:o,eligible:s,keep:e.backupRetain??0,prefix:n,wouldDelete:i}},Co=async(e,t,n,o)=>{const s=e.backupStore,i=e.queryCoordinator;if(!s)throw new c("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!i)throw new c("scheduled backup requires a `queryCoordinator` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!n||n.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 u={authorization:`Bearer ${n}`,"content-type":"application/json"},h=e.backupTables;let p=0,f=0,g=[];await pn(e,i,u,h,k=>{const L=Io.encode(`${JSON.stringify(k)}
1
+ import{isLunoraError as hr,toErrorBody as fr}from"@lunora/errors";import{e as tn}from"./evict-oldest-BNXsKx4s.mjs";import{NOOP_EXECUTION_CONTEXT as pr}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{t as mr,f as wr}from"./base64-Bl1_r2k1.mjs";import{i as gr,e as yr,a as br,E as yt,d as _r}from"./identity-header-pR617HTs.mjs";import{O as bt,a as _t}from"./origin-paywall-B6eOO67m.mjs";import{o as ge,b as nn,p as Er,m as Rr,d as Sr,a as Ar,r as Tr}from"./otlp-resource-BI3MvjSy.mjs";import{r as Or,f as Et,a as ue,S as Rt}from"./observability-DgurIZIR.mjs";import{e as Ee,d as Xe,a as vr}from"./wire-codec-BLvSm5Mn.mjs";import{d as re,e as ie,M as rn,b as Ir,f as kr,g as on,h as sn,t as Pr}from"./rest-routes-CpbO5QEx.mjs";import{LunoraError as c,toErrorResponse as St}from"./LunoraError-DksAgIpa.mjs";import{a as $,m as we}from"./method-guard-BG_vJNTl.mjs";import{normalizeBackupPrefix as ot,BACKUP_KEY_PREFIX as st,isBackupManifestKey as Dr,backupObjectKeyOfManifest as an,backupObjectKey as Nr,backupManifestKey as Ur}from"./BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toHex as Cr,buildStorageAdminRoutes as Br,STORAGE_UPLOAD_MAX_BODY_BYTES as xr,STORAGE_PATH as Hr}from"./STORAGE_UPLOAD_MAX_BODY_BYTES-BIiV5kqV.mjs";import{b as Lr,e as jr,f as At,g as Mr,h as $r}from"./export-tap-CAyZ2TWC.mjs";import{buildHealthRoutes as Kr,durableObjectProbe as Fr,d1Probe as Gr,presenceProbe as $e}from"./HEALTH_PATH-D0i8LhwT.mjs";import{wrapResolverWithContract as Qr}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{composeIdentityResolvers as bi,routeIdentityResolvers as _i}from"./composeIdentityResolvers-BHZ4jH8o.mjs";import{buildLogArchiveAdminRoutes as Wr}from"./LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{resolveShard as ye,applyJurisdiction as Ke}from"./applyJurisdiction-C0ddU7Tg.mjs";import{resolveSecurity as Tt,handleCorsPreflight as zr,enforceOrigin as Vr,decorateResponse as Fe,enforceWebSocketOrigin as Ot}from"./decorateResponse-CRrFNW1v.mjs";const qr=e=>{const t=e??{};if(typeof t.bucket=="function")return t;const n=t.bucketName,s={...t,bucketName:typeof n=="string"&&n!==""?n:"default"};return s.bucket=()=>s,s},cn="__lunoraBranch",Jr=e=>typeof e=="object"&&e!==null&&Object.hasOwn(e,cn),Yr=`may not contain the reserved workflow branch-marker key ("${cn}")`,Xr=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}},at=(e,t)=>{const n=Math.max(e.length,t.length);let o=e.length^t.length;for(let s=0;s<n;s+=1){const i=s<e.length?e.charCodeAt(s):0,u=s<t.length?t.charCodeAt(s):0;o|=i^u}return o===0},Zr=/already[\s_-]?exists/iu,eo=e=>Zr.test(e instanceof Error?e.message:String(e)),to=(e,t,n,o)=>{const s=e.get(t);if(s!==void 0)return s;tn(e,o);const i=n().catch(u=>{throw e.get(t)===i&&e.delete(t),u});return e.set(t,i),i},it=new TextEncoder,no=Array.from({length:32},(e,t)=>t);new RegExp(`[${no.map(e=>String.fromCodePoint(e)).join("")}]`,"u");const ro=64,oo=new Map,dn=async e=>to(oo,e,async()=>crypto.subtle.importKey("raw",it.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]),ro),un=async(e,t)=>{const n=await dn(e),o=await crypto.subtle.sign("HMAC",n,it.encode(t));return mr(new Uint8Array(o))},so=async(e,t,n)=>{const o=await dn(e);return crypto.subtle.verify("HMAC",o,n,it.encode(t))},ao=["wnam","enam","sam","weur","eeur","apac","apac-ne","apac-se","oc","afr","me"];new Set(ao);const io=new Set(["AE","BH","IL","IQ","IR","JO","KW","LB","OM","PS","QA","SA","SY","TR","YE"]),co=-100,uo=15,lo=e=>{const t=Number(e.longitude??Number.NaN);switch(e.continent){case"AF":return"afr";case"AS":return e.country!==void 0&&io.has(e.country)?"me":"apac";case"EU":return Number.isFinite(t)&&t>uo?"eeur":"weur";case"NA":return Number.isFinite(t)&&t<co?"wnam":"enam";case"OC":return"oc";case"SA":return"sam";default:return}},vt=e=>{const t=e.cf;return t===void 0?void 0:lo(t)},Ze="::relay::",ho=(e,t)=>`${e}${Ze}${String(t)}`,et="::replica::",fo=(e,t)=>`${e}${et}${t}`,po=e=>{if(e==null||!/^\d+$/.test(e))return;const t=Number.parseInt(e,10);return Number.isSafeInteger(t)&&t>0?t:void 0},mo=new Set(["1","enabled","on","true","yes"]),wo=new Set(["0","disabled","false","no","off"]),go=(e,t)=>{const n=(e??"").trim().toLowerCase();return mo.has(n)?!0:wo.has(n)?!1:t},ln="v1",yo=6e4,bo=async(e,t={})=>{const n=(t.now??Date.now())+(t.ttlMs??yo),o=`${ln}.${String(n)}`,s=await un(e,o);return{expiresAtMs:n,token:`${o}.${s}`}},_o=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[s,i,u]=o;if(s!==ln||u.length===0)return!1;const h=Number(i);if(!Number.isFinite(h)||h<=n)return!1;let p;try{p=wr(u)}catch{return!1}return so(e,`${s}.${i}`,p)},D="/_lunora/admin/auth",Eo={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},U=(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},se=(e,t)=>typeof e[t]=="string"?e[t]:void 0,Ge=(e,t)=>{const n=e[t];return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:void 0},It=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},kt=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,s]of Object.entries(t))Array.isArray(s)&&s.every(i=>typeof i=="string")&&(n[o]=s);return n},Ro={[`${D}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${D}/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"},[`${D}/sessions`]:{build:({paging:e,query:t})=>({...e,userId:t("userId")}),http:"GET",method:"listSessions"},[`${D}/accounts`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listAccounts"},[`${D}/passkeys`]:{build:({query:e})=>({userId:he(e,"userId")}),http:"GET",method:"listPasskeys"},[`${D}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${D}/organizations/members`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listMembers"},[`${D}/organizations/invitations`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listInvitations"},[`${D}/sign-up-invitations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listSignUpInvitations"},[`${D}/sign-up-invitations/create`]:{build:({body:e})=>({email:U(e,"email"),expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,invitedBy:se(e,"invitedBy")}),http:"POST",method:"createSignUpInvitation"},[`${D}/sign-up-invitations/revoke`]:{build:({body:e})=>({email:U(e,"email")}),http:"POST",method:"revokeSignUpInvitation",returns:"void"},[`${D}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${D}/organizations/teams`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listTeams"},[`${D}/organizations/teams/members`]:{build:({paging:e,query:t})=>({...e,teamId:he(t,"teamId")}),http:"GET",method:"listTeamMembers"},[`${D}/organizations/roles`]:{build:({paging:e,query:t})=>({...e,organizationId:he(t,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${D}/users/create`]:{build:({body:e})=>({data:Ge(e,"data"),email:U(e,"email"),name:U(e,"name"),password:se(e,"password"),role:hn(e.role)}),http:"POST",method:"createUser"},[`${D}/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:U(e,"userId")}},http:"POST",method:"updateUser"},[`${D}/users/role`]:{build:({body:e})=>({role:It(e),userId:U(e,"userId")}),http:"POST",method:"setRole"},[`${D}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:se(e,"reason"),userId:U(e,"userId")}),http:"POST",method:"banUser"},[`${D}/users/unban`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"unbanUser"},[`${D}/users/password`]:{build:({body:e})=>({newPassword:U(e,"newPassword"),userId:U(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${D}/users/remove`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${D}/users/impersonate`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"impersonateUser"},[`${D}/sessions/revoke`]:{build:({body:e})=>({sessionId:U(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${D}/sessions/revoke-all`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${D}/accounts/unlink`]:{build:({body:e})=>({accountId:U(e,"accountId"),userId:U(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${D}/two-factor/disable`]:{build:({body:e})=>({userId:U(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${D}/passkeys/delete`]:{build:({body:e})=>({passkeyId:U(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${D}/organizations/members/remove`]:{build:({body:e})=>({memberId:U(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${D}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:U(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${D}/organizations/create`]:{build:({body:e})=>({logo:se(e,"logo"),metadata:Ge(e,"metadata"),name:U(e,"name"),ownerId:se(e,"ownerId"),slug:se(e,"slug")}),http:"POST",method:"createOrganization"},[`${D}/organizations/update`]:{build:({body:e})=>({logo:se(e,"logo"),metadata:Ge(e,"metadata"),name:se(e,"name"),organizationId:U(e,"organizationId"),slug:se(e,"slug")}),http:"POST",method:"updateOrganization"},[`${D}/organizations/remove`]:{build:({body:e})=>({organizationId:U(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${D}/organizations/members/add`]:{build:({body:e})=>({organizationId:U(e,"organizationId"),role:se(e,"role"),userId:U(e,"userId")}),http:"POST",method:"addMember"},[`${D}/organizations/members/invite`]:{build:({body:e})=>({email:U(e,"email"),inviterId:se(e,"inviterId"),organizationId:U(e,"organizationId"),role:se(e,"role")}),http:"POST",method:"inviteMember"},[`${D}/organizations/members/role`]:{build:({body:e})=>({memberId:U(e,"memberId"),role:It(e)}),http:"POST",method:"updateMemberRole"},[`${D}/organizations/teams/create`]:{build:({body:e})=>({name:U(e,"name"),organizationId:U(e,"organizationId")}),http:"POST",method:"createTeam"},[`${D}/organizations/teams/update`]:{build:({body:e})=>({name:U(e,"name"),teamId:U(e,"teamId")}),http:"POST",method:"updateTeam"},[`${D}/organizations/teams/remove`]:{build:({body:e})=>({teamId:U(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${D}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:U(e,"teamId"),userId:U(e,"userId")}),http:"POST",method:"addTeamMember"},[`${D}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:U(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${D}/organizations/roles/create`]:{build:({body:e})=>({organizationId:U(e,"organizationId"),permission:kt(e),role:U(e,"role")}),http:"POST",method:"createOrgRole"},[`${D}/organizations/roles/update`]:{build:({body:e})=>({permission:kt(e),roleId:U(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${D}/organizations/roles/remove`]:{build:({body:e})=>({roleId:U(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},So=e=>{const t=async s=>{try{return await s()}catch(i){if(i instanceof c)throw i;const u=i,h=typeof u.code=="string"?u.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new c("auth admin operation failed",{code:h,status:Eo[h]??500})}},n=async(s,i)=>{if(e.assertAdmin(s),s.method!==i.http)throw new c(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const u=e.getAuthAdmin();if(u===void 0)throw new c("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const h=u[i.method];if(h===void 0)throw new c(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const p=new URL(s.url),f={body:i.http==="POST"?await e.readJsonBody(s):{},paging:e.parsePaging(s),query:T=>e.queryParameter(p,T)},g=i.build(f),S=await t(()=>h(g));return Response.json(i.returns==="void"?{ok:!0}:S,{headers:{"cache-control":"no-store","content-type":"application/json"},status:200})},o={};for(const[s,i]of Object.entries(Ro))o[s]=u=>n(u,i);return o},Pt="__lunora_admin__:getAuthAuditLog",Dt=e=>typeof e=="string"&&e!==""?e:void 0,Nt=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0,Ao=e=>async(n,o)=>{e.assertAdmin(n);const s=e.getReader();if(s===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=Dt(o.actorId),u=Dt(o.event),h=Nt(o.sinceSeq),p=Nt(o.limit),f={...i===void 0?{}:{actorId:i},...u===void 0?{}:{event:u},...h===void 0?{}:{sinceSeq:h},...p===void 0?{}:{limit:p}};let g;try{g=await s.read(f)}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:g};return Response.json({result:Ee(S)},{headers:{"content-type":"application/json"},status:200})},tt="__lunora_admin__:copyAuthToJurisdiction",fn="__lunora_admin__:purgeUnpinnedAuth",To=e=>async(t,n,o)=>{if(n!==tt&&n!==fn)return;e.assertAdmin(t);const s=e.getMove();if(s===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===tt?await s.copy({force:o.force===!0}):await s.purge();return Response.json({result:Ee(i)},{headers:{"content-type":"application/json"},status:200})},Oo=(e,t)=>{const n=[],o=[];if(t&&t.length>0)for(const s of t)e.resolveTableSharding?.(s)?.mode.kind==="global"?o.push(s):n.push(s);return{globalTables:o,shardLocalTables:n}},vo=async(e,t,n,o,s,i,u)=>{if(n!==void 0&&o.length===0)return;const h=await e.orchestrateExport(i,{args:{tables:o},defaultShardKey:u,headers:t,tables:o}),p=h.shards.filter(f=>f.error);if(p.length>0){const f=p.map(g=>`${g.shardKey}: ${g.error?.message??"unknown error"}`).join("; ");throw new c(`export failed on ${String(p.length)} of ${String(h.shards.length)} shard(s) — ${f}`,{code:"EXPORT_SHARD_FAILED",status:502})}for(const f of h.shards)for(const g of f.rows??[])s(g)},pn=async(e,t,n,o,s,i)=>{const u=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:h,shardLocalTables:p}=Oo(e,u);await vo(t,n,u,p,s,i,e.defaultShardKey??"__root__");const f=e.exportGlobals;if((o===void 0||h.length>0)&&f)for await(const S of f({tables:h}))s(S)},Io=new TextEncoder,ko=1e3,mn=10,Po=200,Ut=8,wn="lunoraBackupCron",Ct=24*1048576,Bt=e=>{const t=e.slice(0,mn).map(o=>an(o)),n=e.length-t.length;return`${t.join(", ")}${n>0?` (+${String(n)} more)`:""}`},Do=(e,t)=>{const n=new Uint8Array(new ArrayBuffer(t));let o=0;for(const s of e)n.set(s,o),o+=s.byteLength;return n},ct=async(e,t,n,o)=>{if(n===void 0||!Number.isInteger(n)||n<=0)return{eligible:0,stale:[]};const s=[];let i;for(let u=0;u<ko;u+=1){const h=await e.list({cursor:i,include:["customMetadata"],prefix:t});for(const p of h.objects)Dr(p.key)&&p.customMetadata?.[wn]===o&&s.push(p.key);if(!h.truncated||h.cursor===void 0)break;i=h.cursor}return{eligible:s.length,stale:s.toSorted((u,h)=>h.localeCompare(u)).slice(n)}},No=async(e,t,n,o,s)=>{const{stale:i}=await ct(e,t,n,o),u=new Set(s),h=i.filter(w=>u.has(w)),p=h.slice(0,Po),f=i.length-p.length,g=s.length-h.length;if(p.length===0)return{deleted:[],failed:[],ignored:g,remaining:f};const S=[],T=[];for(let w=0;w<p.length;w+=Ut){const b=await Promise.allSettled(p.slice(w,w+Ut).map(async R=>(await e.delete(an(R)),await e.delete(R),R)));for(const[R,y]of b.entries())y.status==="fulfilled"?S.push(y.value):T.push(p[w+R])}return S.length>0&&console.info(`[lunora] backup prune kept the newest ${String(n)} and deleted ${String(S.length)}: ${Bt(S)}`),T.length>0&&console.warn(`[lunora] backup prune failed to remove ${String(T.length)}: ${Bt(T)}`),{deleted:S,failed:T,ignored:g,remaining:f}},Uo=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=ot(e.backupPrefix??st),o=e.backupCron,{eligible:s,stale:i}=o===void 0?{eligible:0,stale:[]}:await ct(t,n,e.backupRetain,o);return{cron:o,eligible:s,keep:e.backupRetain??0,prefix:n,wouldDelete:i}},Co=async(e,t,n,o)=>{const s=e.backupStore,i=e.queryCoordinator;if(!s)throw new c("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!i)throw new c("scheduled backup requires a `queryCoordinator` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!n||n.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 u={authorization:`Bearer ${n}`,"content-type":"application/json"},h=e.backupTables;let p=0,f=0,g=[];await pn(e,i,u,h,k=>{const L=Io.encode(`${JSON.stringify(k)}
2
2
  `);if(p+=1,f+=L.byteLength,f>Ct)throw new c(`scheduled backup reached ${String(f)} bytes of NDJSON, past the ${String(Ct)}-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});g.push(L)},t);const T=ot(e.backupPrefix??st),w=new Date(o.scheduledTime).toISOString(),b=Nr(T,w),R=Do(g,f);g=[];const y=Cr(await crypto.subtle.digest("SHA-256",R));await s.put(b,R,{httpMetadata:{contentType:"application/x-ndjson"},sha256:y});const v={bytes:f,createdAt:w,cron:o.cron,file:b,id:w,rows:p,scheduledTime:o.scheduledTime,sha256:y,...h?{tables:h.join(",")}:{}};await s.put(Ur(b),`${JSON.stringify(v,void 0,2)}
3
3
  `,{customMetadata:{[wn]:o.cron},httpMetadata:{contentType:"application/json"}});try{const{stale:k}=await ct(s,T,e.backupRetain,o.cron);if(k.length>0){const L=k.slice(0,mn),I=k.length-L.length;console.info(`[lunora] backup retention: ${String(k.length)} snapshot(s) past the newest ${String(e.backupRetain)} — run \`lunora backup prune\` to remove them: ${L.join(", ")}${I>0?` (+${String(I)} more)`:""}`)}}catch(k){console.warn(`[lunora] backup ${b} was written, but the retention report failed:`,k)}},Bo=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,s=e.backupRetain;if(o===void 0||s===void 0||!Number.isInteger(s)||s<=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 No(n,ot(e.backupPrefix??st),s,o,t)},xo="/_lunora/admin/backup/retention",Ho="/_lunora/admin/backup/prune",Lo=e=>{const{options:t,readJsonBody:n,requireAdminOption:o}=e,s=(h,p)=>{o(h,t.backupStore,{code:"BACKUP_NOT_CONFIGURED",message:`backup ${p} requires a \`backupStore\` on the worker`})},i=async h=>($(h,"GET","Backup-retention"),s(h,"retention preview"),Response.json(await Uo(t),{headers:{"cache-control":"no-store"}})),u=async h=>{$(h,"POST","Backup-prune"),s(h,"prune");const{confirm:p}=await n(h);if(!Array.isArray(p)||p.some(f=>typeof f!="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 Bo(t,p),{headers:{"cache-control":"no-store"}})};return{[Ho]:u,[xo]:i}},xt=500,jo=(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}},Mo=(e,t)=>{if(e.length>xt)throw new c(`RPC batch exceeds the ${String(xt)}-call limit`,{code:"BAD_REQUEST",status:400});const n=new Map,o=new Set;for(const[s,i]of e.entries()){const{entry:u,shardKey:h}=jo(i,s,t);if(o.has(u.id))throw new c(`batch call id ${String(u.id)} is used twice; ids must be distinct`,{code:"BAD_REQUEST",status:400});o.add(u.id);const p=n.get(h)??[];p.push(u),n.set(h,p)}return n},$o="/_lunora/admin/export",Ko="/_lunora/admin/import",Fo="/_lunora/admin/sync",Go="/_lunora/admin/connector/sync",Qo="/_lunora/admin/apply",Wo="/_lunora/admin/export-tap/run",zo=new TextEncoder,Vo=async e=>{const n=await ie(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 s of n.tables){if(typeof s!="string"||s.length===0)throw new c("Export `tables` entries must be non-empty strings",{code:"BAD_REQUEST",status:400});o.push(s)}return{tables:o}},Qe=e=>Array.isArray(e)?e.filter(t=>typeof t=="string"):void 0,qo=e=>{const{applyGlobals:t,defaultShardKey:n,exportCursorStore:o,exportSinks:s,knownTables:i,queryCoordinator:u,assertAdmin:h,requireAdminOption:p,resolveForwardContext:f,shardDO:g,streamExportRows:S,streamingImport:T,syncGlobals:w}=e,b=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;const X=p(I,u,{code:"BAD_REQUEST",message:"Export endpoint requires a `queryCoordinator` on the worker"}),C=await Vo(I),{headers:q}=await f(I,j),W=new ReadableStream({async pull(z){const oe=V=>{z.enqueue(zo.encode(`${JSON.stringify(V)}
4
4
  `))};try{await S(X,q,C.tables,oe),z.close()}catch(V){z.error(V)}}});return new Response(W,{headers:{"content-type":"application/x-ndjson"},status:200})},R=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;const X=p(I,u,{code:"BAD_REQUEST",message:"Sync endpoint requires a `queryCoordinator` on the worker"}),C=await re(I),q=typeof C.cursors=="object"&&C.cursors!==null?C.cursors:{},W=typeof C.epochs=="object"&&C.epochs!==null?C.epochs:{},z=typeof C.limit=="number"?C.limit:void 0,oe=typeof C.globalCursor=="number"?C.globalCursor:0,V=Qe(C.tables),{headers:ae}=await f(I,j),Q=V??i(),G=await X.orchestrateCdcSync(g,{cursors:q,defaultShardKey:n,epochs:W,headers:ae,limit:z,tables:Q}),J=w?await w({limit:z,sinceSeq:oe}):void 0;return Response.json({global:J,shards:G.shards},{status:200})},y=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;const X=p(I,u,{code:"BAD_REQUEST",message:"Connector sync endpoint requires a `queryCoordinator` on the worker"}),C=await re(I),q=jr(C.cursor),W=typeof C.limit=="number"&&C.limit>0?C.limit:void 0,z=Qe(C.tables),{headers:oe}=await f(I,j),V=z??i(),ae=await X.orchestrateCdcSync(g,{cursors:q.s,defaultShardKey:n,headers:oe,limit:W,tables:V}),Q=[],G={...q.s};let J=!1;for(const ce of ae.shards)J=At(Q,ce.changes??[],$r(W))||J,G[ce.shardKey]=ce.cursor;let Re=q.g;if(w){const ce=await w({limit:W,sinceSeq:q.g});J=At(Q,ce.changes,W)||J,Re=ce.cursor}const Ce=Mr({g:Re,s:G,v:1}),Se={changes:Q,hasMore:J,nextCursor:Ce};return Response.json(Se,{status:200})},v=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;const X=p(I,u,{code:"BAD_REQUEST",message:"Apply endpoint requires a `queryCoordinator` on the worker"}),C=await re(I),W=(Array.isArray(C.batches)?C.batches:[]).map(Q=>Q).filter(Q=>Q!==null&&typeof Q=="object"&&typeof Q.shardKey=="string"&&Array.isArray(Q.changes)),z=Array.isArray(C.globalChanges)?C.globalChanges:[],{headers:oe}=await f(I,j),V=await X.orchestrateApplyCdc(g,{batches:W,headers:oe}),ae=z.length>0&&t?await t({changes:z}):0;return Response.json({applied:V.applied+ae,failed:V.failed,ok:V.ok},{status:200})},k=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;h(I);const{headers:X}=await f(I,j),C=await T(I,X);return Response.json(C,{headers:{"content-type":"application/json"},status:C.failed.length>0?207:200})},L=async(I,j)=>{const M=we(I,["POST"]);if(M)return M;const X=p(I,u,{code:"BAD_REQUEST",message:"Export-tap endpoint requires a `queryCoordinator` on the worker"});if(s===void 0||Object.keys(s).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 C=await re(I),q=typeof C.sink=="string"?C.sink:void 0,W=typeof C.limit=="number"&&C.limit>0?C.limit:void 0,z=Qe(C.tables);if(q===void 0)throw new c("Export-tap `sink` must name a configured sink",{code:"BAD_REQUEST",status:400});const oe=s[q];if(oe===void 0)throw new c(`Export-tap sink "${q}" is not configured`,{code:"NOT_FOUND",status:404});const{headers:V}=await f(I,j),ae=z??i(),Q=await Lr({coordinator:X,cursorStore:o,defaultShardKey:n,headers:V,limit:W,shardDO:g,sink:oe,tables:ae});return Response.json(Q,{headers:{"content-type":"application/json"},status:200})};return{[Qo]:v,[Go]:y,[$o]:b,[Wo]:L,[Ko]:k,[Fo]:R}},Jo=(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}},Yo=(e,t,n,o,s)=>{if(n?.mode.kind==="shardBy"&&typeof n.mode.field=="string"){const i=e[n.mode.field];return i==null?{error:{code:"BAD_ROW",line:s,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}},Xo=async(e,t,n)=>{if(!e.body)throw new c("Import endpoint requires a request body",{code:"BAD_REQUEST",status:400});const o=[],s=[],i=new Map;let u=0,h=0;const p=e.body.getReader(),f=new TextDecoder;let g="",S=0;const T=w=>{h+=1;const b=w.trim();if(b.length===0)return;u+=1;const R=Jo(b,h);if(!R.ok){o.push(R.error);return}const{doc:y,table:v}=R,k=t.resolveTableSharding?.(v);if(k?.mode.kind==="global"){s.push({doc:y,line:h,table:v});return}const L=Yo(y,v,k,n,h);if(!L.ok){o.push(L.error);return}const I=i.get(L.shardKey);I?I.rows.push({doc:y,table:v}):i.set(L.shardKey,{rows:[{doc:y,table:v}],shardKey:L.shardKey,startLine:h})};for(;;){const{done:w,value:b}=await p.read();if(w)break;if(b&&(S+=b.byteLength,S>rn))throw await p.cancel().catch(()=>{}),new c("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});g+=f.decode(b,{stream:!0});let R=g.indexOf(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.156",
3
+ "version": "1.0.0-alpha.157",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",