@uploadista/server 0.0.18-beta.8 → 0.0.18

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.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require(`./auth-Ck4gisA2.cjs`);let t=require(`effect`),n=require(`@uploadista/core/flow`),r=require(`@uploadista/core/types`),i=require(`@uploadista/core/utils`),a=require(`@uploadista/event-broadcaster-memory`),o=require(`@uploadista/event-emitter-websocket`),s=require(`@uploadista/observability`),c=require(`@uploadista/core/upload`),l=require(`@uploadista/core/errors`);var u=class extends t.Context.Tag(`AuthCacheService`)(){};const d=(e={})=>{let n=e.maxSize??1e4,r=e.ttl??36e5,i=new Map,a=()=>{let e=Date.now();for(let[t,n]of i.entries())e-n.timestamp>r&&i.delete(t)},o=()=>{if(i.size<=n)return;let e=null,t=1/0;for(let[n,r]of i.entries())r.timestamp<t&&(t=r.timestamp,e=n);e&&i.delete(e)};return t.Layer.succeed(u,{set:(e,n)=>t.Effect.sync(()=>{i.size%100==0&&a(),i.set(e,{authContext:n,timestamp:Date.now()}),o()}),get:e=>t.Effect.sync(()=>{let t=i.get(e);return t?Date.now()-t.timestamp>r?(i.delete(e),null):t.authContext:null}),delete:e=>t.Effect.sync(()=>{i.delete(e)}),clear:()=>t.Effect.sync(()=>{i.clear()}),size:()=>t.Effect.sync(()=>i.size)})},f=t.Layer.succeed(u,{set:()=>t.Effect.void,get:()=>t.Effect.succeed(null),delete:()=>t.Effect.void,clear:()=>t.Effect.void,size:()=>t.Effect.succeed(0)}),p=e=>e.split(`/`).filter(Boolean),m=e=>{let t=p(e);return t[t.length-1]},h=(e,t)=>e.includes(`${t}/api/`),g=(e,t)=>e.replace(`${t}/api/`,``).split(`/`).filter(Boolean),_=e=>{let t=500,n=`UNKNOWN_ERROR`,r=`Internal server error`,i;if(typeof e==`object`&&e){let a=e;if(`code`in a&&typeof a.code==`string`&&(n=a.code),`message`in a&&typeof a.message==`string`?r=a.message:`body`in a&&typeof a.body==`string`&&(r=a.body),`details`in a&&(i=a.details),`status`in a&&typeof a.status==`number`)t=a.status;else if(`code`in a)switch(a.code){case`FILE_NOT_FOUND`:case`FLOW_JOB_NOT_FOUND`:case`UPLOAD_ID_NOT_FOUND`:t=404;break;case`FLOW_JOB_ERROR`:case`VALIDATION_ERROR`:case`INVALID_METADATA`:case`INVALID_LENGTH`:case`ABORTED`:case`INVALID_TERMINATION`:t=400;break;case`INVALID_OFFSET`:t=409;break;case`ERR_SIZE_EXCEEDED`:case`ERR_MAX_SIZE_EXCEEDED`:t=413;break;case`FILE_NO_LONGER_EXISTS`:t=410;break;case`MISSING_OFFSET`:case`INVALID_CONTENT_TYPE`:t=403;break;default:t=500}`message`in a&&a.message===`Invalid JSON body`&&(t=400,n=`VALIDATION_ERROR`)}let a={status:t,code:n,message:r};return i!==void 0&&(a.details=i),a},v=e=>e[e.length-2],y=e=>({jobId:e[e.length-3],nodeId:e[e.length-1]}),b=e=>({storageId:e.pop(),flowId:e.pop()}),x=({kvStore:e,eventEmitter:n,dataStore:i,bufferedDataStore:a,generateId:o})=>{let s=t.Layer.provide(r.uploadFileKvStore,e),l=t.Layer.provide(i,s),u=a?t.Layer.provide(a,s):t.Layer.empty,d=t.Layer.provide(r.uploadEventEmitter,n),f=t.Layer.mergeAll(l,s,d,...o?[o]:[],u);return t.Layer.provide(c.uploadServer,f)},S=({kvStore:e,eventEmitter:i,flowProvider:a,uploadServer:o})=>{let s=t.Layer.provide(r.flowJobKvStore,e),c=t.Layer.provide(r.flowEventEmitter,i),l=t.Layer.mergeAll(a,c,s,o);return t.Layer.provide(n.flowServer,l)};var C=class extends t.Context.Tag(`AuthContextService`)(){};const w=e=>t.Layer.succeed(C,{getClientId:()=>t.Effect.succeed(e?.clientId??null),getMetadata:()=>t.Effect.succeed(e?.metadata??{}),hasPermission:n=>t.Effect.succeed(e?.permissions?.includes(n)??!1),getAuthContext:()=>t.Effect.succeed(e)}),T=w(null),E=e=>t.Effect.gen(function*(){let t=yield*(yield*n.DeadLetterQueueService).list(e.options);return{type:`dlq-list`,status:200,headers:{"Content-Type":`application/json`},body:t}}),D=e=>t.Effect.gen(function*(){let t=yield*(yield*n.DeadLetterQueueService).get(e.itemId);return{type:`dlq-get`,status:200,headers:{"Content-Type":`application/json`},body:t}}),O=e=>t.Effect.gen(function*(){return yield*(yield*n.DeadLetterQueueService).markRetrying(e.itemId),{type:`dlq-retry`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),k=e=>t.Effect.gen(function*(){let r=yield*n.DeadLetterQueueService,{items:i}=yield*r.list({status:e.options?.status,flowId:e.options?.flowId}),a=0,o=0;for(let e of i)(yield*t.Effect.either(r.markRetrying(e.id)))._tag===`Right`?a++:o++;return{type:`dlq-retry-all`,status:200,headers:{"Content-Type":`application/json`},body:{retried:i.length,succeeded:a,failed:o}}}),A=e=>t.Effect.gen(function*(){return yield*(yield*n.DeadLetterQueueService).delete(e.itemId),{type:`dlq-delete`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),j=e=>t.Effect.gen(function*(){let t=yield*(yield*n.DeadLetterQueueService).markResolved(e.itemId);return{type:`dlq-resolve`,status:200,headers:{"Content-Type":`application/json`},body:t}}),M=e=>t.Effect.gen(function*(){let t=yield*(yield*n.DeadLetterQueueService).cleanup(e.options);return{type:`dlq-cleanup`,status:200,headers:{"Content-Type":`application/json`},body:t}}),N=e=>t.Effect.gen(function*(){let e=yield*(yield*n.DeadLetterQueueService).getStats();return{type:`dlq-stats`,status:200,headers:{"Content-Type":`application/json`},body:e}}),P=({flowId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*(yield*C).getClientId();return i&&(yield*t.Effect.logInfo(`[Flow] Getting flow data: ${e}, client: ${i}`)),{status:200,body:yield*r.getFlowData(e,i)}}),F=({flowId:e,storageId:r,inputs:i})=>t.Effect.gen(function*(){let a=yield*n.FlowServer,o=yield*C,s=yield*u,c=yield*o.getClientId();c?(yield*t.Effect.logInfo(`[Flow] Executing flow: ${e}, storage: ${r}, client: ${c}`),yield*t.Effect.logInfo(JSON.stringify(i,null,2))):(yield*t.Effect.logInfo(`[Flow] Executing flow: ${e}, storage: ${r}`),yield*t.Effect.logInfo(`[Flow] Inputs: ${JSON.stringify(i,null,2)}`)),yield*t.Effect.logInfo(`[Flow] Calling flowServer.runFlow...`);let l=yield*a.runFlow({flowId:e,storageId:r,clientId:c,inputs:i}).pipe(t.Effect.tap(()=>t.Effect.logInfo(`[Flow] runFlow completed successfully`)),t.Effect.tapError(e=>t.Effect.logError(`[Flow] runFlow failed with error: ${e}`))),d=yield*o.getAuthContext();return d&&(yield*s.set(l.id,d)),yield*t.Effect.logInfo(`[Flow] Flow started with jobId: ${l.id}`),{status:200,body:l}}),I=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*C,a=yield*u,o=yield*i.getClientId();if(!e)throw Error(`No job id`);o&&(yield*t.Effect.logInfo(`[Flow] Getting job status: ${e}, client: ${o}`));let s=yield*r.getJobStatus(e);return(s.status===`completed`||s.status===`failed`)&&(yield*a.delete(e),o&&(yield*t.Effect.logInfo(`[Flow] Flow ${s.status}, cleared auth cache: ${e}`))),{status:200,body:s}}),L=({jobId:e,nodeId:r,newData:i})=>t.Effect.gen(function*(){let a=yield*n.FlowServer,o=yield*C,s=yield*u,c=yield*o.getClientId();if(c||=(yield*s.get(e))?.clientId??null,c&&(yield*t.Effect.logInfo(`[Flow] Continuing flow: jobId=${e}, nodeId=${r}, client: ${c}`)),i===void 0)throw Error(`Missing newData`);let l=yield*a.resumeFlow({jobId:e,nodeId:r,newData:i,clientId:c});return(l.status===`completed`||l.status===`failed`)&&(yield*s.delete(e),c&&(yield*t.Effect.logInfo(`[Flow] Flow ${l.status}, cleared auth cache: ${e}`))),{status:200,body:l}}),R=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*C,a=yield*u,o=yield*i.getClientId();o||=(yield*a.get(e))?.clientId??null,o&&(yield*t.Effect.logInfo(`[Flow] Pausing flow: jobId=${e}, client: ${o}`));let s=yield*r.pauseFlow(e,o);return o&&(yield*t.Effect.logInfo(`[Flow] Flow paused: ${e}, status: ${s.status}`)),{status:200,body:s}}),ee=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*C,a=yield*u;if(!e)throw Error(`No job id`);let o=yield*i.getClientId();o||=(yield*a.get(e))?.clientId??null,o&&(yield*t.Effect.logInfo(`[Flow] Cancelling flow: jobId=${e}, client: ${o}`));let s=yield*r.cancelFlow(e,o);return yield*a.delete(e),o&&(yield*t.Effect.logInfo(`[Flow] Flow cancelled, cleared auth cache: ${e}`)),{status:200,body:s}}),te=Date.now();function z(){return Date.now()-te}function B(){return new Date().toISOString()}function ne(e){return{status:`healthy`,timestamp:B(),version:e?.version,uptime:z()}}function V(e){let t=[];if(e.storage&&t.push(e.storage.status),e.kvStore&&t.push(e.kvStore.status),t.includes(`unhealthy`))return`unhealthy`;let n=[...t];return e.eventBroadcaster&&n.push(e.eventBroadcaster.status),e.circuitBreaker&&n.push(e.circuitBreaker.status),e.deadLetterQueue&&n.push(e.deadLetterQueue.status),n.includes(`degraded`)?`degraded`:`healthy`}function H(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Storage backend configured`,lastCheck:B()})}function U(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`KV store configured`,lastCheck:B()})}function W(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Event broadcaster configured`,lastCheck:B()})}function re(){return t.Effect.gen(function*(){let e=yield*t.Effect.serviceOption(r.CircuitBreakerStoreService);if(t.Option.isNone(e))return;let n=e.value,i=yield*t.Effect.either(n.getAllStats());if(i._tag===`Left`)return{status:`degraded`,openCircuits:0,totalCircuits:0};let a=i.right,o=Array.from(a.values()),s=o.filter(e=>e.state===`open`).length,c=o.length,l=`healthy`;return s>0&&(l=`degraded`),{status:l,openCircuits:s,totalCircuits:c,circuits:o.map(e=>({nodeType:e.nodeType,state:e.state,failureCount:e.failureCount,timeSinceLastStateChange:e.timeSinceLastStateChange}))}})}function ie(){return t.Effect.gen(function*(){let e=yield*n.DeadLetterQueueService.optional;if(t.Option.isNone(e))return;let r=e.value,i=yield*t.Effect.either(r.getStats());if(i._tag===`Left`)return{status:`degraded`,pendingItems:0,exhaustedItems:0};let a=i.right,o=`healthy`;return a.byStatus.exhausted>0&&(o=`degraded`),{status:o,pendingItems:a.byStatus.pending,exhaustedItems:a.byStatus.exhausted,oldestItem:a.oldestItem?.toISOString()}})}function ae(e={}){let n={...r.DEFAULT_HEALTH_CHECK_CONFIG,...e};return t.Effect.gen(function*(){let t={};return n.checkStorage&&(t.storage=yield*H(n)),n.checkKvStore&&(t.kvStore=yield*U(n)),n.checkEventBroadcaster&&(t.eventBroadcaster=yield*W(n)),{status:V(t),timestamp:B(),version:e.version,uptime:z(),components:t}})}function oe(e={}){let n={...r.DEFAULT_HEALTH_CHECK_CONFIG,...e};return t.Effect.gen(function*(){let t={};n.checkStorage&&(t.storage=yield*H(n)),n.checkKvStore&&(t.kvStore=yield*U(n)),n.checkEventBroadcaster&&(t.eventBroadcaster=yield*W(n));let r=yield*re();r&&(t.circuitBreaker=r);let i=yield*ie();return i&&(t.deadLetterQueue=i),{status:V(t),timestamp:B(),version:e.version,uptime:z(),components:t}})}const se=(e,n)=>t.Effect.sync(()=>{let t=ne(n);return(0,r.getHealthResponseFormat)(e.acceptHeader)===`text`?{type:`health`,status:200,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health`,status:200,headers:{"Content-Type":`application/json`},body:t}}),ce=(e,n)=>t.Effect.gen(function*(){let t=yield*ae(n),i=(0,r.getHealthResponseFormat)(e.acceptHeader),a=t.status===`unhealthy`?503:200;return i===`text`?{type:`health-ready`,status:a,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health-ready`,status:a,headers:{"Content-Type":`application/json`},body:t}}),G=(e,n)=>t.Effect.gen(function*(){let t=yield*oe(n);return(0,r.getHealthResponseFormat)(e.acceptHeader)===`text`?{type:`health-components`,status:200,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health-components`,status:200,headers:{"Content-Type":`application/json`},body:t}});var K=class extends Error{constructor(e,t=500,n=`INTERNAL_ERROR`){super(e),this.statusCode=t,this.errorCode=n,this.name=`AdapterError`}},q=class extends K{constructor(e){super(e,400,`VALIDATION_ERROR`),this.name=`ValidationError`}},le=class extends K{constructor(e){super(`${e} not found`,404,`NOT_FOUND`),this.name=`NotFoundError`}},ue=class extends K{constructor(e){super(e,400,`BAD_REQUEST`),this.name=`BadRequestError`}};const de=e=>({error:e.message,code:e.errorCode,timestamp:new Date().toISOString()}),fe=e=>{let t={error:e.body,code:e.code,timestamp:new Date().toISOString()};return e.details!==void 0&&(t.details=e.details),t},pe=(e=`Internal server error`)=>({error:e,code:`INTERNAL_ERROR`,timestamp:new Date().toISOString()}),me=e=>t.Effect.gen(function*(){let n=yield*c.UploadServer,a=yield*C,o=yield*u,s=yield*a.getClientId();s&&(yield*t.Effect.logInfo(`[Upload] Creating upload for client: ${s}`));let l=yield*t.Effect.sync(()=>r.inputFileSchema.safeParse(e.data));if(!l.success)return yield*t.Effect.fail(new q(`Invalid input file schema`));if(l.data.checksumAlgorithm&&!(0,i.isSupportedAlgorithm)(l.data.checksumAlgorithm))return yield*t.Effect.fail(new q(`Unsupported checksum algorithm: ${l.data.checksumAlgorithm}. Supported algorithms: sha256`));let d=yield*n.createUpload(l.data,s),f=yield*a.getAuthContext();return f&&(yield*o.set(d.id,f)),s&&(yield*t.Effect.logInfo(`[Upload] Upload created: ${d.id} for client: ${s}`)),{status:200,body:d}}),he=({storageId:e})=>t.Effect.gen(function*(){let t=yield*c.UploadServer,n=yield*(yield*C).getClientId();return{status:200,body:{storageId:e,capabilities:yield*t.getCapabilities(e,n),timestamp:new Date().toISOString()}}}),ge=({uploadId:e})=>t.Effect.gen(function*(){return{status:200,body:yield*(yield*c.UploadServer).getUpload(e)}}),_e=e=>t.Effect.gen(function*(){let n=yield*c.UploadServer,r=yield*C,i=yield*u,a=yield*s.MetricsService,{uploadId:o,data:l}=e,d=yield*r.getClientId(),f=yield*r.getMetadata();if(!d){let e=yield*i.get(o);d=e?.clientId??null,f=e?.metadata??{}}d&&(yield*t.Effect.logInfo(`[Upload] Uploading chunk for upload: ${o}, client: ${d}`));let p=yield*n.uploadChunk(o,d,l);return p.size&&p.offset>=p.size&&(yield*i.delete(o),d&&(yield*t.Effect.logInfo(`[Upload] Upload completed, cleared auth cache: ${o}`)),d&&p.size?(yield*t.Effect.logInfo(`[Upload] Recording metrics for org: ${d}, size: ${p.size}`),yield*t.Effect.forkDaemon(a.recordUpload(d,p.size,f))):yield*t.Effect.logWarning(`[Upload] Cannot record metrics - missing organizationId or size`)),d&&(yield*t.Effect.logInfo(`[Upload] Chunk uploaded for upload: ${o}, client: ${d}`)),{status:200,body:p}}),ve=(e,n)=>t.Effect.gen(function*(){switch(e.type){case`create-upload`:return yield*me(e);case`get-capabilities`:return yield*he(e);case`get-upload`:return yield*ge(e);case`upload-chunk`:return yield*_e(e);case`get-flow`:return yield*P(e);case`run-flow`:return yield*F(e);case`job-status`:return yield*I(e);case`resume-flow`:return yield*L(e);case`pause-flow`:return yield*R(e);case`cancel-flow`:return yield*ee(e);case`dlq-list`:return yield*E(e);case`dlq-get`:return yield*D(e);case`dlq-retry`:return yield*O(e);case`dlq-retry-all`:return yield*k(e);case`dlq-delete`:return yield*A(e);case`dlq-resolve`:return yield*j(e);case`dlq-cleanup`:return yield*M(e);case`dlq-stats`:return yield*N(e);case`health`:return yield*se(e,n?.healthCheckConfig);case`health-ready`:return yield*ce(e,n?.healthCheckConfig);case`health-components`:return yield*G(e,n?.healthCheckConfig);case`not-found`:return{status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}};case`bad-request`:return{status:400,body:{error:`Bad request`,message:e.message}};case`method-not-allowed`:return{status:405,headers:{"Content-Type":`application/json`},body:{error:`Method not allowed`}};case`unsupported-content-type`:return{status:415,headers:{"Content-Type":`application/json`},body:{error:`Unsupported content type`}}}}),J=async({flows:e,dataStore:c,kvStore:l,plugins:u=[],eventEmitter:f,eventBroadcaster:p=a.memoryEventBroadcaster,withTracing:m=!1,baseUrl:h=`uploadista`,generateId:g=i.GenerateIdLive,metricsLayer:v,bufferedDataStore:y,adapter:b,authCacheConfig:C,circuitBreaker:T=!0,deadLetterQueue:E=!1,healthCheck:D})=>{let O=f??(0,o.webSocketEventEmitter)(p),k=h.endsWith(`/`)?h.slice(0,-1):h,A=t.Layer.effect(n.FlowProvider,t.Effect.succeed({getFlow:(t,n)=>e(t,n)}));if(!O)throw Error(`eventEmitter is required. Provide an event emitter layer in the configuration.`);let j=x({kvStore:l,eventEmitter:O,dataStore:await(0,r.createDataStoreLayer)(c),bufferedDataStore:y,generateId:g}),M=S({kvStore:l,eventEmitter:O,flowProvider:A,uploadServer:j}),N=d(C),P=v??s.NoOpMetricsServiceLive,F=T?n.kvCircuitBreakerStoreLayer.pipe(t.Layer.provide(l)):null,I=E?n.deadLetterQueueService.pipe(t.Layer.provide(r.deadLetterQueueKvStore),t.Layer.provide(l)):null,L=t.Layer.mergeAll(j,M,P,N,...u,...F?[F]:[],...I?[I]:[]),R=t.ManagedRuntime.make(L);return{handler:async e=>{let r=t.Effect.gen(function*(){let r=yield*b.extractRequest(e,{baseUrl:k}),i=null;if(b.runAuthMiddleware){let n=yield*b.runAuthMiddleware(e).pipe(t.Effect.timeout(`5 seconds`),t.Effect.catchAll(()=>(console.error(`Auth middleware timeout exceeded (5 seconds)`),t.Effect.succeed({_tag:`TimeoutError`}))),t.Effect.catchAllCause(e=>(console.error(`Auth middleware error:`,e),t.Effect.succeed({_tag:`AuthError`,error:e}))));if(n&&typeof n==`object`&&`_tag`in n&&n._tag===`TimeoutError`)return yield*b.sendResponse({status:503,headers:{"Content-Type":`application/json`},body:{error:`Authentication service unavailable`,message:`Authentication took too long to respond. Please try again.`}},e);if(n&&typeof n==`object`&&`_tag`in n&&n._tag===`AuthError`)return yield*b.sendResponse({status:500,headers:{"Content-Type":`application/json`},body:{error:`Internal Server Error`,message:`An error occurred during authentication`}},e);if(n===null)return yield*b.sendResponse({status:401,headers:{"Content-Type":`application/json`},body:{error:`Unauthorized`,message:`Invalid credentials`}},e);i=n}let a=w(i),o=[];if(b.extractWaitUntil){let r=b.extractWaitUntil(e);r&&o.push(t.Layer.succeed(n.FlowWaitUntil,r))}let s=t.Layer.mergeAll(a,N,P,...u,...o),c=F?t.Layer.merge(s,F):s,l=I?t.Layer.merge(c,I):c;if(r.type===`not-found`)return yield*b.sendResponse({type:`not-found`,status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}},e);let d=yield*ve(r,{healthCheckConfig:D}).pipe(t.Effect.provide(l));return yield*b.sendResponse(d,e)}).pipe(t.Effect.catchAll(t=>{let n=_(t),r={code:n.code,message:n.message};n.details!==void 0&&(r.details=n.details);let i={status:n.status,headers:{"Content-Type":`application/json`},body:r};return b.sendResponse(i,e)}));return m?R.runPromise(r.pipe(t.Effect.provide(s.NodeSdkLive))):R.runPromise(r)},websocketHandler:await R.runPromise(b.webSocketHandler({baseUrl:k})),baseUrl:k,dispose:()=>R.dispose()}};async function Y(e){return J(e)}function ye(e){return e}function be(e){return e}const X={ImagePlugin:{packageName:`@uploadista/flow-images-sharp`,variableName:`sharpImagePlugin`},ImageAiPlugin:{packageName:`@uploadista/flow-images-replicate`,variableName:`replicateImagePlugin`},ZipPlugin:{packageName:`@uploadista/flow-utility-zipjs`,variableName:`zipPlugin`},CredentialProvider:{packageName:`@uploadista/core`,variableName:`credentialProviderLayer`}};function xe(e){try{let t=e;if(t._tag)return t._tag;if(t.constructor?.name)return t.constructor.name;if(t.context?.services){let e=Array.from(t.context.services.keys());if(e.length>0){let t=e[0];if(t.key)return t.key}}return null}catch{return null}}function Z(e){return e.map(e=>xe(e)).filter(e=>e!==null)}function Q(e){let{plugins:t,expectedServices:n=[]}=e,r=Z(t),i=n.filter(e=>!r.includes(e));return i.length===0?{success:!0}:{success:!1,required:n,provided:r,missing:i,suggestions:i.map(e=>{let t=X[e];return t?{name:e,packageName:t.packageName,importStatement:`import { ${t.variableName} } from '${t.packageName}';`}:null}).filter(e=>e!==null)}}function $(e){let t=[`Server initialization failed: Missing required plugins`,``,`Required: ${e.required.join(`, `)}`,`Provided: ${e.provided.length>0?e.provided.join(`, `):`(none)`}`,`Missing: ${e.missing.join(`, `)}`,``];if(e.suggestions.length>0){t.push(`Add the missing plugins to your configuration:`),t.push(``);for(let n of e.suggestions)t.push(` ${n.importStatement}`);t.push(``),t.push(` const server = await createUploadistaServer({`),t.push(` plugins: [${[...e.provided,...e.missing.map(e=>X[e]?.variableName||e)].join(`, `)}],`),t.push(` // ...`),t.push(` });`)}else t.push(`Note: Could not determine package names for missing plugins.`),t.push(`Please ensure all required plugin layers are provided.`);return t.join(`
2
- `)}function Se(e){return t.Effect.sync(()=>{let t=Q(e);if(!t.success){let e=$(t);throw Error(e)}})}function Ce(e){let t=Q(e);if(!t.success){let e=$(t);throw Error(e)}}const we=(e,n,r)=>t.Effect.gen(function*(){if(!n){yield*t.Effect.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Job ID is required for flow event subscription`,code:`MISSING_JOB_ID`}))});return}yield*e.subscribeToFlowEvents(n,r)}),Te=(e,n)=>t.Effect.gen(function*(){n&&(yield*e.unsubscribeFromFlowEvents(n))}),Ee=(e,n,r)=>t.Effect.gen(function*(){if(!n){yield*t.Effect.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Upload ID is required for upload event subscription`,code:`MISSING_UPLOAD_ID`}))});return}yield*e.subscribeToUploadEvents(n,r)}),De=(e,n)=>t.Effect.gen(function*(){n&&(yield*e.unsubscribeFromUploadEvents(n))}),Oe=(e,n,r)=>{let{connection:i,isFlowRoute:a,isUploadRoute:o,jobId:s,uploadId:c,eventId:u}=e;return t.Effect.gen(function*(){a&&(yield*we(r,s,i)),o&&(yield*Ee(n,c,i)),i.send(JSON.stringify({type:`connection`,message:`Uploadista WebSocket connected`,id:u,jobId:s,uploadId:c,timestamp:new Date().toISOString()}))}).pipe(t.Effect.catchAll(e=>t.Effect.sync(()=>{console.error(`Error subscribing to events:`,e);let t=e instanceof l.UploadistaError?e.body:`Failed to subscribe to events`;i.send(JSON.stringify({type:`error`,message:t,code:e instanceof l.UploadistaError?e.code:`SUBSCRIPTION_ERROR`}))})))},ke=(e,n)=>t.Effect.sync(()=>{try{JSON.parse(e).type===`ping`&&n.send(JSON.stringify({type:`pong`,timestamp:new Date().toISOString()}))}catch(e){console.error(`Error handling WebSocket message:`,e),n.send(JSON.stringify({type:`error`,message:`Invalid message format`}))}}),Ae=(e,n,r)=>{let{isFlowRoute:i,isUploadRoute:a,jobId:o,uploadId:s}=e;return t.Effect.gen(function*(){i&&(yield*Te(r,o)),a&&(yield*De(n,s))}).pipe(t.Effect.catchAll(e=>t.Effect.sync(()=>{console.error(`Error unsubscribing from events:`,e instanceof l.UploadistaError?e.body:e)})))},je=(e,n)=>t.Effect.sync(()=>{console.error(`WebSocket error for event ${n}:`,e)});exports.AdapterError=K,exports.AuthCacheService=u,exports.AuthCacheServiceLive=d,exports.AuthContextService=C,exports.AuthContextServiceLive=w,exports.BadRequestError=ue,exports.NoAuthCacheServiceLive=f,exports.NoAuthContextServiceLive=T,exports.NotFoundError=le,exports.ValidationError=q,exports.createErrorResponseBody=de,exports.createFlowServerLayer=S,exports.createGenericErrorResponseBody=pe,exports.createTypeSafeServer=Y,exports.createUploadServerLayer=x,exports.createUploadistaErrorResponseBody=fe,exports.createUploadistaServer=J,exports.defineFlow=ye,exports.defineSimpleFlow=be,exports.extractFlowAndStorageId=b,exports.extractJobAndNodeId=y,exports.extractJobIdFromStatus=v,exports.extractServiceIdentifiers=Z,exports.formatPluginValidationError=$,exports.getAuthCredentials=e.t,exports.getLastSegment=m,exports.getRouteSegments=g,exports.handleFlowError=_,exports.handleWebSocketClose=Ae,exports.handleWebSocketError=je,exports.handleWebSocketMessage=ke,exports.handleWebSocketOpen=Oe,exports.hasBasePath=h,exports.parseUrlSegments=p,exports.validatePluginRequirements=Q,exports.validatePluginRequirementsEffect=Se,exports.validatePluginsOrThrow=Ce;
1
+ const e=require(`./auth-Ck4gisA2.cjs`);let t=require(`effect`),n=require(`@uploadista/core/flow`),r=require(`@uploadista/core/types`),i=require(`@uploadista/core/utils`),a=require(`@uploadista/event-broadcaster-memory`),o=require(`@uploadista/event-emitter-websocket`),s=require(`@uploadista/observability`),c=require(`@uploadista/core/upload`),l=require(`@uploadista/core/errors`);var u=class extends t.Context.Tag(`AuthCacheService`)(){};const d=(e={})=>{let n=e.maxSize??1e4,r=e.ttl??36e5,i=new Map,a=()=>{let e=Date.now();for(let[t,n]of i.entries())e-n.timestamp>r&&i.delete(t)},o=()=>{if(i.size<=n)return;let e=null,t=1/0;for(let[n,r]of i.entries())r.timestamp<t&&(t=r.timestamp,e=n);e&&i.delete(e)};return t.Layer.succeed(u,{set:(e,n)=>t.Effect.sync(()=>{i.size%100==0&&a(),i.set(e,{authContext:n,timestamp:Date.now()}),o()}),get:e=>t.Effect.sync(()=>{let t=i.get(e);return t?Date.now()-t.timestamp>r?(i.delete(e),null):t.authContext:null}),delete:e=>t.Effect.sync(()=>{i.delete(e)}),clear:()=>t.Effect.sync(()=>{i.clear()}),size:()=>t.Effect.sync(()=>i.size)})},f=t.Layer.succeed(u,{set:()=>t.Effect.void,get:()=>t.Effect.succeed(null),delete:()=>t.Effect.void,clear:()=>t.Effect.void,size:()=>t.Effect.succeed(0)}),p=e=>e.split(`/`).filter(Boolean),m=e=>{let t=p(e);return t[t.length-1]},h=(e,t)=>e.includes(`${t}/api/`),g=(e,t)=>e.replace(`${t}/api/`,``).split(`/`).filter(Boolean),_=e=>{let t=500,n=`UNKNOWN_ERROR`,r=`Internal server error`,i;if(typeof e==`object`&&e){let a=e;if(`code`in a&&typeof a.code==`string`&&(n=a.code),`message`in a&&typeof a.message==`string`?r=a.message:`body`in a&&typeof a.body==`string`&&(r=a.body),`details`in a&&(i=a.details),`status`in a&&typeof a.status==`number`)t=a.status;else if(`code`in a)switch(a.code){case`FILE_NOT_FOUND`:case`FLOW_JOB_NOT_FOUND`:case`UPLOAD_ID_NOT_FOUND`:t=404;break;case`FLOW_JOB_ERROR`:case`VALIDATION_ERROR`:case`INVALID_METADATA`:case`INVALID_LENGTH`:case`ABORTED`:case`INVALID_TERMINATION`:t=400;break;case`INVALID_OFFSET`:t=409;break;case`ERR_SIZE_EXCEEDED`:case`ERR_MAX_SIZE_EXCEEDED`:t=413;break;case`FILE_NO_LONGER_EXISTS`:t=410;break;case`MISSING_OFFSET`:case`INVALID_CONTENT_TYPE`:t=403;break;default:t=500}`message`in a&&a.message===`Invalid JSON body`&&(t=400,n=`VALIDATION_ERROR`)}let a={status:t,code:n,message:r};return i!==void 0&&(a.details=i),a},ee=e=>e[e.length-2],te=e=>({jobId:e[e.length-3],nodeId:e[e.length-1]}),v=e=>({storageId:e.pop(),flowId:e.pop()}),y=({kvStore:e,eventEmitter:n,dataStore:i,bufferedDataStore:a,generateId:o})=>{let s=t.Layer.provide(r.uploadFileKvStore,e),l=t.Layer.provide(i,s),u=a?t.Layer.provide(a,s):t.Layer.empty,d=t.Layer.provide(r.uploadEventEmitter,n),f=t.Layer.mergeAll(l,s,d,...o?[o]:[],u);return t.Layer.provide(c.uploadServer,f)},ne=({kvStore:e,eventEmitter:i,flowProvider:a,uploadServer:o})=>{let s=t.Layer.provide(r.flowJobKvStore,e),c=t.Layer.provide(r.flowEventEmitter,i),l=t.Layer.mergeAll(a,c,s,o);return t.Layer.provide(n.flowServer,l)},b={ALL:`engine:*`,HEALTH:`engine:health`,READINESS:`engine:readiness`,METRICS:`engine:metrics`,DLQ:`engine:dlq`,DLQ_READ:`engine:dlq:read`,DLQ_WRITE:`engine:dlq:write`},x={ALL:`flow:*`,EXECUTE:`flow:execute`,CANCEL:`flow:cancel`,STATUS:`flow:status`},S={ALL:`upload:*`,CREATE:`upload:create`,READ:`upload:read`,CANCEL:`upload:cancel`},C={ENGINE:b,FLOW:x,UPLOAD:S},re={ADMIN:[b.ALL],ORGANIZATION_OWNER:[x.ALL,S.ALL],ORGANIZATION_MEMBER:[x.ALL,S.ALL],API_KEY:[x.EXECUTE,S.CREATE]},w={[b.DLQ]:[b.DLQ_READ,b.DLQ_WRITE]},T=(e,t)=>{if(e===t)return!0;if(e.endsWith(`:*`)){let n=e.slice(0,-1);if(t.startsWith(n))return!0}return!!w[e]?.includes(t)},E=(e,t)=>e.some(e=>T(e,t)),D=(e,t)=>t.some(t=>E(e,t)),O=(e,t)=>t.every(t=>E(e,t)),k=e=>{let t=[e],n=w[e];return n&&t.push(...n),t};var A=class extends Error{constructor(e,t=500,n=`INTERNAL_ERROR`){super(e),this.statusCode=t,this.errorCode=n,this.name=`AdapterError`}},j=class extends A{constructor(e){super(e,400,`VALIDATION_ERROR`),this.name=`ValidationError`}},M=class extends A{constructor(e){super(`${e} not found`,404,`NOT_FOUND`),this.name=`NotFoundError`}},N=class extends A{constructor(e){super(e,400,`BAD_REQUEST`),this.name=`BadRequestError`}};const P=e=>({error:e.message,code:e.errorCode,timestamp:new Date().toISOString()}),F=e=>{let t={error:e.body,code:e.code,timestamp:new Date().toISOString()};return e.details!==void 0&&(t.details=e.details),t},I=(e=`Internal server error`)=>({error:e,code:`INTERNAL_ERROR`,timestamp:new Date().toISOString()});var L=class extends A{requiredPermission;constructor(e,t){super(t??`Permission denied: ${e} required`,403,`PERMISSION_DENIED`),this.name=`AuthorizationError`,this.requiredPermission=e}},R=class extends A{constructor(e=`Authentication required`){super(e,401,`AUTHENTICATION_REQUIRED`),this.name=`AuthenticationRequiredError`}},z=class extends A{constructor(e=`Access denied: resource belongs to another organization`){super(e,403,`ORGANIZATION_MISMATCH`),this.name=`OrganizationMismatchError`}},B=class extends A{constructor(e=`Quota exceeded`,t=`QUOTA_EXCEEDED`){super(e,402,t),this.name=`QuotaExceededError`}};const ie=e=>({error:e.message,code:e.errorCode,requiredPermission:e.requiredPermission,timestamp:new Date().toISOString()});var V=class extends t.Context.Tag(`AuthContextService`)(){};const H=(e,n)=>{let r=e?.permissions??[],i=n?.bypassAuth??!1;return t.Layer.succeed(V,{getClientId:()=>t.Effect.succeed(e?.clientId??null),getMetadata:()=>t.Effect.succeed(e?.metadata??{}),hasPermission:e=>i?t.Effect.succeed(!0):t.Effect.succeed(E(r,e)),hasAnyPermission:e=>i?t.Effect.succeed(!0):t.Effect.succeed(D(r,e)),requirePermission:n=>t.Effect.gen(function*(){if(i){yield*t.Effect.logDebug(`[Auth] Bypass mode: permission '${n}' auto-granted`);return}if(!e)return yield*t.Effect.logDebug(`[Auth] Permission check failed: authentication required for '${n}'`),yield*t.Effect.fail(new R);if(!E(r,n))return yield*t.Effect.logDebug(`[Auth] Permission denied: '${n}' for client '${e.clientId}'`),yield*t.Effect.fail(new L(n));yield*t.Effect.logDebug(`[Auth] Permission granted: '${n}' for client '${e.clientId}'`)}),requireAuthentication:()=>e?t.Effect.succeed(e):t.Effect.fail(new R),getPermissions:()=>t.Effect.succeed(r),getAuthContext:()=>t.Effect.succeed(e)})},ae=H(null),U=()=>({action:`continue`}),oe=(e,t)=>({action:`abort`,reason:e,code:t}),W=5e3;var G=class extends t.Context.Tag(`UsageHookService`)(){};const K=e=>{let n=e?.hooks,r=e?.timeout??W;return t.Layer.succeed(G,{onUploadStart:e=>n?.onUploadStart?n.onUploadStart(e).pipe(t.Effect.timeout(r),t.Effect.map(e=>e??U()),t.Effect.catchAll(e=>t.Effect.gen(function*(){return yield*t.Effect.logWarning(`onUploadStart hook failed: ${e}. Proceeding with upload.`),U()}))):t.Effect.succeed(U()),onUploadComplete:e=>n?.onUploadComplete?n.onUploadComplete(e).pipe(t.Effect.timeout(r),t.Effect.asVoid,t.Effect.catchAll(e=>t.Effect.logWarning(`onUploadComplete hook failed: ${e}. Upload already completed.`))):t.Effect.void,onFlowStart:e=>n?.onFlowStart?n.onFlowStart(e).pipe(t.Effect.timeout(r),t.Effect.map(e=>e??U()),t.Effect.catchAll(e=>t.Effect.gen(function*(){return yield*t.Effect.logWarning(`onFlowStart hook failed: ${e}. Proceeding with flow.`),U()}))):t.Effect.succeed(U()),onFlowComplete:e=>n?.onFlowComplete?n.onFlowComplete(e).pipe(t.Effect.timeout(r),t.Effect.asVoid,t.Effect.catchAll(e=>t.Effect.logWarning(`onFlowComplete hook failed: ${e}. Flow already completed.`))):t.Effect.void})},se=K(),ce=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_READ);let t=yield*(yield*n.DeadLetterQueueService).list(e.options);return{type:`dlq-list`,status:200,headers:{"Content-Type":`application/json`},body:t}}),le=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_READ);let t=yield*(yield*n.DeadLetterQueueService).get(e.itemId);return{type:`dlq-get`,status:200,headers:{"Content-Type":`application/json`},body:t}}),ue=e=>t.Effect.gen(function*(){return yield*(yield*V).requirePermission(C.ENGINE.DLQ_WRITE),yield*(yield*n.DeadLetterQueueService).markRetrying(e.itemId),{type:`dlq-retry`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),de=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_WRITE);let r=yield*n.DeadLetterQueueService,{items:i}=yield*r.list({status:e.options?.status,flowId:e.options?.flowId}),a=0,o=0;for(let e of i)(yield*t.Effect.either(r.markRetrying(e.id)))._tag===`Right`?a++:o++;return{type:`dlq-retry-all`,status:200,headers:{"Content-Type":`application/json`},body:{retried:i.length,succeeded:a,failed:o}}}),fe=e=>t.Effect.gen(function*(){return yield*(yield*V).requirePermission(C.ENGINE.DLQ_WRITE),yield*(yield*n.DeadLetterQueueService).delete(e.itemId),{type:`dlq-delete`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),pe=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_WRITE);let t=yield*(yield*n.DeadLetterQueueService).markResolved(e.itemId);return{type:`dlq-resolve`,status:200,headers:{"Content-Type":`application/json`},body:t}}),me=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_WRITE);let t=yield*(yield*n.DeadLetterQueueService).cleanup(e.options);return{type:`dlq-cleanup`,status:200,headers:{"Content-Type":`application/json`},body:t}}),he=e=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.DLQ_READ);let e=yield*(yield*n.DeadLetterQueueService).getStats();return{type:`dlq-stats`,status:200,headers:{"Content-Type":`application/json`},body:e}}),ge=({flowId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*V,a=yield*i.getClientId();return yield*i.requirePermission(C.FLOW.STATUS),a&&(yield*t.Effect.logInfo(`[Flow] Getting flow data: ${e}, client: ${a}`)),{status:200,body:yield*r.getFlowData(e,a)}}),_e=({flowId:e,storageId:r,inputs:i})=>t.Effect.gen(function*(){let a=yield*n.FlowServer,o=yield*V,s=yield*u,c=yield*G,l=yield*o.getClientId();if(yield*o.requirePermission(C.FLOW.EXECUTE),l?(yield*t.Effect.logInfo(`[Flow] Executing flow: ${e}, storage: ${r}, client: ${l}`),yield*t.Effect.logInfo(JSON.stringify(i,null,2))):(yield*t.Effect.logInfo(`[Flow] Executing flow: ${e}, storage: ${r}`),yield*t.Effect.logInfo(`[Flow] Inputs: ${JSON.stringify(i,null,2)}`)),l){let n=yield*c.onFlowStart({clientId:l,operation:`flow`,metadata:{flowId:e}});if(n.action===`abort`)return yield*t.Effect.fail(new B(n.reason,n.code??`SUBSCRIPTION_REQUIRED`))}yield*t.Effect.logInfo(`[Flow] Calling flowServer.runFlow...`);let d=yield*a.runFlow({flowId:e,storageId:r,clientId:l,inputs:i}).pipe(t.Effect.tap(()=>t.Effect.logInfo(`[Flow] runFlow completed successfully`)),t.Effect.tapError(e=>t.Effect.logError(`[Flow] runFlow failed with error: ${e}`))),f=yield*o.getAuthContext();return f&&(yield*s.set(d.id,f)),yield*t.Effect.logInfo(`[Flow] Flow started with jobId: ${d.id}`),{status:200,body:d}}),ve=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*V,a=yield*u,o=yield*i.getClientId();if(yield*i.requirePermission(C.FLOW.STATUS),!e)throw Error(`No job id`);o&&(yield*t.Effect.logInfo(`[Flow] Getting job status: ${e}, client: ${o}`));let s=yield*r.getJobStatus(e);return(s.status===`completed`||s.status===`failed`)&&(yield*a.delete(e),o&&(yield*t.Effect.logInfo(`[Flow] Flow ${s.status}, cleared auth cache: ${e}`))),{status:200,body:s}}),ye=({jobId:e,nodeId:r,newData:i})=>t.Effect.gen(function*(){let a=yield*n.FlowServer,o=yield*V,s=yield*u;yield*o.requirePermission(C.FLOW.EXECUTE);let c=yield*o.getClientId();if(c||=(yield*s.get(e))?.clientId??null,c&&(yield*t.Effect.logInfo(`[Flow] Continuing flow: jobId=${e}, nodeId=${r}, client: ${c}`)),i===void 0)throw Error(`Missing newData`);let l=yield*a.resumeFlow({jobId:e,nodeId:r,newData:i,clientId:c});return(l.status===`completed`||l.status===`failed`)&&(yield*s.delete(e),c&&(yield*t.Effect.logInfo(`[Flow] Flow ${l.status}, cleared auth cache: ${e}`))),{status:200,body:l}}),be=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*V,a=yield*u;yield*i.requirePermission(C.FLOW.CANCEL);let o=yield*i.getClientId();o||=(yield*a.get(e))?.clientId??null,o&&(yield*t.Effect.logInfo(`[Flow] Pausing flow: jobId=${e}, client: ${o}`));let s=yield*r.pauseFlow(e,o);return o&&(yield*t.Effect.logInfo(`[Flow] Flow paused: ${e}, status: ${s.status}`)),{status:200,body:s}}),xe=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowServer,i=yield*V,a=yield*u,o=yield*G;if(yield*i.requirePermission(C.FLOW.CANCEL),!e)throw Error(`No job id`);let s=yield*i.getClientId();s||=(yield*a.get(e))?.clientId??null,s&&(yield*t.Effect.logInfo(`[Flow] Cancelling flow: jobId=${e}, client: ${s}`));let c=yield*r.cancelFlow(e,s);return yield*a.delete(e),s&&(yield*t.Effect.logInfo(`[Flow] Flow cancelled, cleared auth cache: ${e}`),yield*t.Effect.forkDaemon(o.onFlowComplete({clientId:s,operation:`flow`,metadata:{jobId:e,status:`cancelled`}}))),{status:200,body:c}}),Se=Date.now();function q(){return Date.now()-Se}function J(){return new Date().toISOString()}function Ce(e){return{status:`healthy`,timestamp:J(),version:e?.version,uptime:q()}}function Y(e){let t=[];if(e.storage&&t.push(e.storage.status),e.kvStore&&t.push(e.kvStore.status),t.includes(`unhealthy`))return`unhealthy`;let n=[...t];return e.eventBroadcaster&&n.push(e.eventBroadcaster.status),e.circuitBreaker&&n.push(e.circuitBreaker.status),e.deadLetterQueue&&n.push(e.deadLetterQueue.status),n.includes(`degraded`)?`degraded`:`healthy`}function X(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Storage backend configured`,lastCheck:J()})}function Z(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`KV store configured`,lastCheck:J()})}function we(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Event broadcaster configured`,lastCheck:J()})}function Te(){return t.Effect.gen(function*(){let e=yield*t.Effect.serviceOption(r.CircuitBreakerStoreService);if(t.Option.isNone(e))return;let n=e.value,i=yield*t.Effect.either(n.getAllStats());if(i._tag===`Left`)return{status:`degraded`,openCircuits:0,totalCircuits:0};let a=i.right,o=Array.from(a.values()),s=o.filter(e=>e.state===`open`).length,c=o.length,l=`healthy`;return s>0&&(l=`degraded`),{status:l,openCircuits:s,totalCircuits:c,circuits:o.map(e=>({nodeType:e.nodeType,state:e.state,failureCount:e.failureCount,timeSinceLastStateChange:e.timeSinceLastStateChange}))}})}function Ee(){return t.Effect.gen(function*(){let e=yield*n.DeadLetterQueueService.optional;if(t.Option.isNone(e))return;let r=e.value,i=yield*t.Effect.either(r.getStats());if(i._tag===`Left`)return{status:`degraded`,pendingItems:0,exhaustedItems:0};let a=i.right,o=`healthy`;return a.byStatus.exhausted>0&&(o=`degraded`),{status:o,pendingItems:a.byStatus.pending,exhaustedItems:a.byStatus.exhausted,oldestItem:a.oldestItem?.toISOString()}})}function De(e={}){let n={...r.DEFAULT_HEALTH_CHECK_CONFIG,...e};return t.Effect.gen(function*(){let t={};return n.checkStorage&&(t.storage=yield*X(n)),n.checkKvStore&&(t.kvStore=yield*Z(n)),n.checkEventBroadcaster&&(t.eventBroadcaster=yield*we(n)),{status:Y(t),timestamp:J(),version:e.version,uptime:q(),components:t}})}function Oe(e={}){let n={...r.DEFAULT_HEALTH_CHECK_CONFIG,...e};return t.Effect.gen(function*(){let t={};n.checkStorage&&(t.storage=yield*X(n)),n.checkKvStore&&(t.kvStore=yield*Z(n)),n.checkEventBroadcaster&&(t.eventBroadcaster=yield*we(n));let r=yield*Te();r&&(t.circuitBreaker=r);let i=yield*Ee();return i&&(t.deadLetterQueue=i),{status:Y(t),timestamp:J(),version:e.version,uptime:q(),components:t}})}const ke=(e,n)=>t.Effect.sync(()=>{let t=Ce(n);return(0,r.getHealthResponseFormat)(e.acceptHeader)===`text`?{type:`health`,status:200,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health`,status:200,headers:{"Content-Type":`application/json`},body:t}}),Ae=(e,n)=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.READINESS);let t=yield*De(n),i=(0,r.getHealthResponseFormat)(e.acceptHeader),a=t.status===`unhealthy`?503:200;return i===`text`?{type:`health-ready`,status:a,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health-ready`,status:a,headers:{"Content-Type":`application/json`},body:t}}),je=(e,n)=>t.Effect.gen(function*(){yield*(yield*V).requirePermission(C.ENGINE.READINESS);let t=yield*Oe(n);return(0,r.getHealthResponseFormat)(e.acceptHeader)===`text`?{type:`health-components`,status:200,headers:{"Content-Type":`text/plain`},body:(0,r.formatHealthAsText)(t.status)}:{type:`health-components`,status:200,headers:{"Content-Type":`application/json`},body:t}}),Me=e=>t.Effect.gen(function*(){let n=yield*c.UploadServer,a=yield*V,o=yield*u,s=yield*G,l=yield*a.getClientId();yield*a.requirePermission(C.UPLOAD.CREATE),l&&(yield*t.Effect.logInfo(`[Upload] Creating upload for client: ${l}`));let d=yield*t.Effect.sync(()=>r.inputFileSchema.safeParse(e.data));if(!d.success)return yield*t.Effect.fail(new j(`Invalid input file schema`));if(d.data.checksumAlgorithm&&!(0,i.isSupportedAlgorithm)(d.data.checksumAlgorithm))return yield*t.Effect.fail(new j(`Unsupported checksum algorithm: ${d.data.checksumAlgorithm}. Supported algorithms: sha256`));if(l){let e=yield*s.onUploadStart({clientId:l,operation:`upload`,metadata:{fileSize:d.data.size,mimeType:d.data.type,fileName:d.data.fileName}});if(e.action===`abort`)return yield*t.Effect.fail(new B(e.reason,e.code??`QUOTA_EXCEEDED`))}let f=yield*n.createUpload(d.data,l),p=yield*a.getAuthContext();return p&&(yield*o.set(f.id,p)),l&&(yield*t.Effect.logInfo(`[Upload] Upload created: ${f.id} for client: ${l}`)),{status:200,body:f}}),Ne=({storageId:e})=>t.Effect.gen(function*(){let t=yield*c.UploadServer,n=yield*V,r=yield*n.getClientId();return yield*n.requirePermission(C.UPLOAD.READ),{status:200,body:{storageId:e,capabilities:yield*t.getCapabilities(e,r),timestamp:new Date().toISOString()}}}),Pe=({uploadId:e})=>t.Effect.gen(function*(){let t=yield*c.UploadServer;return yield*(yield*V).requirePermission(C.UPLOAD.READ),{status:200,body:yield*t.getUpload(e)}}),Fe=e=>t.Effect.gen(function*(){let n=yield*c.UploadServer,r=yield*V,i=yield*u,a=yield*s.MetricsService,o=yield*G,{uploadId:l,data:d}=e;yield*r.requirePermission(C.UPLOAD.CREATE);let f=yield*r.getClientId(),p=yield*r.getMetadata();if(!f){let e=yield*i.get(l);f=e?.clientId??null,p=e?.metadata??{}}f&&(yield*t.Effect.logInfo(`[Upload] Uploading chunk for upload: ${l}, client: ${f}`));let m=Date.now(),h=yield*n.uploadChunk(l,f,d);if(h.size&&h.offset>=h.size)if(yield*i.delete(l),f&&(yield*t.Effect.logInfo(`[Upload] Upload completed, cleared auth cache: ${l}`)),f&&h.size){yield*t.Effect.logInfo(`[Upload] Recording metrics for org: ${f}, size: ${h.size}`),yield*t.Effect.forkDaemon(a.recordUpload(f,h.size,p));let e=Date.now()-m;yield*t.Effect.forkDaemon(o.onUploadComplete({clientId:f,operation:`upload`,metadata:{uploadId:l,fileSize:h.size,duration:e}}))}else yield*t.Effect.logWarning(`[Upload] Cannot record metrics - missing organizationId or size`);return f&&(yield*t.Effect.logInfo(`[Upload] Chunk uploaded for upload: ${l}, client: ${f}`)),{status:200,body:h}}),Ie=(e,n)=>t.Effect.gen(function*(){switch(e.type){case`create-upload`:return yield*Me(e);case`get-capabilities`:return yield*Ne(e);case`get-upload`:return yield*Pe(e);case`upload-chunk`:return yield*Fe(e);case`get-flow`:return yield*ge(e);case`run-flow`:return yield*_e(e);case`job-status`:return yield*ve(e);case`resume-flow`:return yield*ye(e);case`pause-flow`:return yield*be(e);case`cancel-flow`:return yield*xe(e);case`dlq-list`:return yield*ce(e);case`dlq-get`:return yield*le(e);case`dlq-retry`:return yield*ue(e);case`dlq-retry-all`:return yield*de(e);case`dlq-delete`:return yield*fe(e);case`dlq-resolve`:return yield*pe(e);case`dlq-cleanup`:return yield*me(e);case`dlq-stats`:return yield*he(e);case`health`:return yield*ke(e,n?.healthCheckConfig);case`health-ready`:return yield*Ae(e,n?.healthCheckConfig);case`health-components`:return yield*je(e,n?.healthCheckConfig);case`not-found`:return{status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}};case`bad-request`:return{status:400,body:{error:`Bad request`,message:e.message}};case`method-not-allowed`:return{status:405,headers:{"Content-Type":`application/json`},body:{error:`Method not allowed`}};case`unsupported-content-type`:return{status:415,headers:{"Content-Type":`application/json`},body:{error:`Unsupported content type`}}}}),Le=async({flows:e,dataStore:c,kvStore:l,plugins:u=[],eventEmitter:f,eventBroadcaster:p=a.memoryEventBroadcaster,withTracing:m=!1,observabilityLayer:h,baseUrl:g=`uploadista`,generateId:ee=i.GenerateIdLive,metricsLayer:te,bufferedDataStore:v,adapter:b,authCacheConfig:x,circuitBreaker:S=!0,deadLetterQueue:C=!1,healthCheck:re,usageHooks:w})=>{let T=f??(0,o.webSocketEventEmitter)(p),E=g.endsWith(`/`)?g.slice(0,-1):g,D=t.Layer.effect(n.FlowProvider,t.Effect.succeed({getFlow:(t,n)=>e(t,n)}));if(!T)throw Error(`eventEmitter is required. Provide an event emitter layer in the configuration.`);let O=y({kvStore:l,eventEmitter:T,dataStore:await(0,r.createDataStoreLayer)(c),bufferedDataStore:v,generateId:ee}),k=ne({kvStore:l,eventEmitter:T,flowProvider:D,uploadServer:O}),A=d(x),j=te??s.NoOpMetricsServiceLive,M=S?n.kvCircuitBreakerStoreLayer.pipe(t.Layer.provide(l)):null,N=C?n.deadLetterQueueService.pipe(t.Layer.provide(r.deadLetterQueueKvStore),t.Layer.provide(l)):null,P=K(w),F=t.Layer.mergeAll(O,k,j,A,P,...u,...M?[M]:[],...N?[N]:[]),I=m?h??s.NodeSdkLive:null,L=F,R=I?t.Layer.merge(L,I):L,z=t.ManagedRuntime.make(R);return{handler:async e=>{let r=t.Effect.gen(function*(){let r=yield*b.extractRequest(e,{baseUrl:E}),i=null;if(b.runAuthMiddleware){let n=yield*b.runAuthMiddleware(e).pipe(t.Effect.timeout(`5 seconds`),t.Effect.catchAll(()=>(console.error(`Auth middleware timeout exceeded (5 seconds)`),t.Effect.succeed({_tag:`TimeoutError`}))),t.Effect.catchAllCause(e=>(console.error(`Auth middleware error:`,e),t.Effect.succeed({_tag:`AuthError`,error:e}))));if(n&&typeof n==`object`&&`_tag`in n&&n._tag===`TimeoutError`)return yield*b.sendResponse({status:503,headers:{"Content-Type":`application/json`},body:{error:`Authentication service unavailable`,message:`Authentication took too long to respond. Please try again.`}},e);if(n&&typeof n==`object`&&`_tag`in n&&n._tag===`AuthError`)return yield*b.sendResponse({status:500,headers:{"Content-Type":`application/json`},body:{error:`Internal Server Error`,message:`An error occurred during authentication`}},e);if(n===null)return yield*b.sendResponse({status:401,headers:{"Content-Type":`application/json`},body:{error:`Unauthorized`,message:`Invalid credentials`}},e);i=n}let a=H(i,{bypassAuth:!b.runAuthMiddleware}),o=[];if(b.extractWaitUntil){let r=b.extractWaitUntil(e);r&&o.push(t.Layer.succeed(n.FlowWaitUntil,r))}let s=t.Layer.mergeAll(a,A,j,P,...u,...o),c=M?t.Layer.merge(s,M):s,l=N?t.Layer.merge(c,N):c;if(r.type===`not-found`)return yield*b.sendResponse({type:`not-found`,status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}},e);let d=yield*Ie(r,{healthCheckConfig:re}).pipe(t.Effect.provide(l));return yield*b.sendResponse(d,e)}).pipe(t.Effect.catchAll(t=>{let n=_(t),r={code:n.code,message:n.message};n.details!==void 0&&(r.details=n.details);let i={status:n.status,headers:{"Content-Type":`application/json`},body:r};return b.sendResponse(i,e)}));return z.runPromise(r)},websocketHandler:await z.runPromise(b.webSocketHandler({baseUrl:E})),baseUrl:E,dispose:()=>z.dispose()}};async function Re(e){return Le(e)}function ze(e){return e}function Be(e){return e}const Ve={ImagePlugin:{packageName:`@uploadista/flow-images-sharp`,variableName:`sharpImagePlugin`},ImageAiPlugin:{packageName:`@uploadista/flow-images-replicate`,variableName:`replicateImagePlugin`},ZipPlugin:{packageName:`@uploadista/flow-utility-zipjs`,variableName:`zipPlugin`},CredentialProvider:{packageName:`@uploadista/core`,variableName:`credentialProviderLayer`}};function He(e){try{let t=e;if(t._tag)return t._tag;if(t.constructor?.name)return t.constructor.name;if(t.context?.services){let e=Array.from(t.context.services.keys());if(e.length>0){let t=e[0];if(t.key)return t.key}}return null}catch{return null}}function Ue(e){return e.map(e=>He(e)).filter(e=>e!==null)}function Q(e){let{plugins:t,expectedServices:n=[]}=e,r=Ue(t),i=n.filter(e=>!r.includes(e));return i.length===0?{success:!0}:{success:!1,required:n,provided:r,missing:i,suggestions:i.map(e=>{let t=Ve[e];return t?{name:e,packageName:t.packageName,importStatement:`import { ${t.variableName} } from '${t.packageName}';`}:null}).filter(e=>e!==null)}}function $(e){let t=[`Server initialization failed: Missing required plugins`,``,`Required: ${e.required.join(`, `)}`,`Provided: ${e.provided.length>0?e.provided.join(`, `):`(none)`}`,`Missing: ${e.missing.join(`, `)}`,``];if(e.suggestions.length>0){t.push(`Add the missing plugins to your configuration:`),t.push(``);for(let n of e.suggestions)t.push(` ${n.importStatement}`);t.push(``),t.push(` const server = await createUploadistaServer({`),t.push(` plugins: [${[...e.provided,...e.missing.map(e=>Ve[e]?.variableName||e)].join(`, `)}],`),t.push(` // ...`),t.push(` });`)}else t.push(`Note: Could not determine package names for missing plugins.`),t.push(`Please ensure all required plugin layers are provided.`);return t.join(`
2
+ `)}function We(e){return t.Effect.sync(()=>{let t=Q(e);if(!t.success){let e=$(t);throw Error(e)}})}function Ge(e){let t=Q(e);if(!t.success){let e=$(t);throw Error(e)}}const Ke=(e,n,r)=>t.Effect.gen(function*(){if(!n){yield*t.Effect.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Job ID is required for flow event subscription`,code:`MISSING_JOB_ID`}))});return}yield*e.subscribeToFlowEvents(n,r)}),qe=(e,n)=>t.Effect.gen(function*(){n&&(yield*e.unsubscribeFromFlowEvents(n))}),Je=(e,n,r)=>t.Effect.gen(function*(){if(!n){yield*t.Effect.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Upload ID is required for upload event subscription`,code:`MISSING_UPLOAD_ID`}))});return}yield*e.subscribeToUploadEvents(n,r)}),Ye=(e,n)=>t.Effect.gen(function*(){n&&(yield*e.unsubscribeFromUploadEvents(n))}),Xe=(e,n,r)=>{let{connection:i,isFlowRoute:a,isUploadRoute:o,jobId:s,uploadId:c,eventId:u}=e;return t.Effect.gen(function*(){a&&(yield*Ke(r,s,i)),o&&(yield*Je(n,c,i)),i.send(JSON.stringify({type:`connection`,message:`Uploadista WebSocket connected`,id:u,jobId:s,uploadId:c,timestamp:new Date().toISOString()}))}).pipe(t.Effect.catchAll(e=>t.Effect.sync(()=>{console.error(`Error subscribing to events:`,e);let t=e instanceof l.UploadistaError?e.body:`Failed to subscribe to events`;i.send(JSON.stringify({type:`error`,message:t,code:e instanceof l.UploadistaError?e.code:`SUBSCRIPTION_ERROR`}))})))},Ze=(e,n)=>t.Effect.sync(()=>{try{JSON.parse(e).type===`ping`&&n.send(JSON.stringify({type:`pong`,timestamp:new Date().toISOString()}))}catch(e){console.error(`Error handling WebSocket message:`,e),n.send(JSON.stringify({type:`error`,message:`Invalid message format`}))}}),Qe=(e,n,r)=>{let{isFlowRoute:i,isUploadRoute:a,jobId:o,uploadId:s}=e;return t.Effect.gen(function*(){i&&(yield*qe(r,o)),a&&(yield*Ye(n,s))}).pipe(t.Effect.catchAll(e=>t.Effect.sync(()=>{console.error(`Error unsubscribing from events:`,e instanceof l.UploadistaError?e.body:e)})))},$e=(e,n)=>t.Effect.sync(()=>{console.error(`WebSocket error for event ${n}:`,e)});exports.AdapterError=A,exports.AuthCacheService=u,exports.AuthCacheServiceLive=d,exports.AuthContextService=V,exports.AuthContextServiceLive=H,exports.AuthenticationRequiredError=R,exports.AuthorizationError=L,exports.BadRequestError=N,exports.DEFAULT_USAGE_HOOK_TIMEOUT=W,exports.ENGINE_PERMISSIONS=b,exports.FLOW_PERMISSIONS=x,exports.NoAuthCacheServiceLive=f,exports.NoAuthContextServiceLive=ae,exports.NoUsageHookServiceLive=se,exports.NotFoundError=M,exports.OrganizationMismatchError=z,exports.PERMISSIONS=C,exports.PERMISSION_HIERARCHY=w,exports.PERMISSION_SETS=re,exports.QuotaExceededError=B,exports.UPLOAD_PERMISSIONS=S,exports.UsageHookService=G,exports.UsageHookServiceLive=K,exports.ValidationError=j,exports.abortResult=oe,exports.continueResult=U,exports.createAuthorizationErrorResponseBody=ie,exports.createErrorResponseBody=P,exports.createFlowServerLayer=ne,exports.createGenericErrorResponseBody=I,exports.createTypeSafeServer=Re,exports.createUploadServerLayer=y,exports.createUploadistaErrorResponseBody=F,exports.createUploadistaServer=Le,exports.defineFlow=ze,exports.defineSimpleFlow=Be,exports.expandPermission=k,exports.extractFlowAndStorageId=v,exports.extractJobAndNodeId=te,exports.extractJobIdFromStatus=ee,exports.extractServiceIdentifiers=Ue,exports.formatPluginValidationError=$,exports.getAuthCredentials=e.t,exports.getLastSegment=m,exports.getRouteSegments=g,exports.handleFlowError=_,exports.handleWebSocketClose=Qe,exports.handleWebSocketError=$e,exports.handleWebSocketMessage=Ze,exports.handleWebSocketOpen=Xe,exports.hasAllPermissions=O,exports.hasAnyPermission=D,exports.hasBasePath=h,exports.hasPermission=E,exports.matchesPermission=T,exports.parseUrlSegments=p,exports.validatePluginRequirements=Q,exports.validatePluginRequirementsEffect=We,exports.validatePluginsOrThrow=Ge;