@uploadista/server 0.0.7 → 0.0.9

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/auth/index.d.mts +2 -0
  3. package/dist/auth/index.mjs +1 -0
  4. package/dist/{auth-C77S4vQd.js → auth-BqArZeGK.mjs} +1 -1
  5. package/dist/auth-BqArZeGK.mjs.map +1 -0
  6. package/dist/{index-CvDNB1lJ.d.ts → index--Lny6VJP.d.mts} +1 -1
  7. package/dist/index--Lny6VJP.d.mts.map +1 -0
  8. package/dist/index.cjs +1 -1
  9. package/dist/index.d.cts +735 -12
  10. package/dist/index.d.cts.map +1 -1
  11. package/dist/index.d.mts +1343 -0
  12. package/dist/index.d.mts.map +1 -0
  13. package/dist/index.mjs +2 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/package.json +10 -7
  16. package/src/adapter/index.ts +10 -0
  17. package/src/adapter/types.ts +229 -0
  18. package/src/core/http-handlers/flow-http-handlers.ts +245 -0
  19. package/src/core/http-handlers/http-handlers.ts +72 -0
  20. package/src/core/http-handlers/upload-http-handlers.ts +168 -0
  21. package/src/core/index.ts +12 -0
  22. package/src/core/routes.ts +188 -0
  23. package/src/core/server.ts +327 -0
  24. package/src/core/types.ts +322 -0
  25. package/src/core/websocket-handlers/flow-websocket-handlers.ts +47 -0
  26. package/src/core/websocket-handlers/upload-websocket-handlers.ts +47 -0
  27. package/src/core/websocket-handlers/websocket-handlers.ts +151 -0
  28. package/src/core/websocket-routes.ts +136 -0
  29. package/src/index.ts +2 -0
  30. package/dist/auth/index.d.ts +0 -2
  31. package/dist/auth/index.js +0 -1
  32. package/dist/auth-C77S4vQd.js.map +0 -1
  33. package/dist/index-CvDNB1lJ.d.ts.map +0 -1
  34. package/dist/index.d.ts +0 -620
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/index.js +0 -2
  37. package/dist/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/routes.ts","../src/types.ts","../src/adapter/types.ts","../src/cache.ts","../src/core/types.ts","../src/core/server.ts","../src/core/websocket-routes.ts","../src/core/websocket-handlers/websocket-handlers.ts","../src/error-types.ts","../src/http-utils.ts","../src/layer-utils.ts","../src/plugins-typing.ts","../src/service.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./auth-BqArZeGK.mjs";import{Context as t,Effect as n,Layer as r,ManagedRuntime as i}from"effect";import{FlowProvider as a,FlowServer as o,FlowWaitUntil as s,flowServer as c}from"@uploadista/core/flow";import{createDataStoreLayer as l,flowEventEmitter as u,flowJobKvStore as d,inputFileSchema as f,uploadEventEmitter as p,uploadFileKvStore as m}from"@uploadista/core/types";import{GenerateIdLive as ee,isSupportedAlgorithm as h}from"@uploadista/core/utils";import{memoryEventBroadcaster as g}from"@uploadista/event-broadcaster-memory";import{webSocketEventEmitter as _}from"@uploadista/event-emitter-websocket";import{MetricsService as v,NoOpMetricsServiceLive as y,NodeSdkLive as b}from"@uploadista/observability";import{UploadServer as x,uploadServer as S}from"@uploadista/core/upload";import{UploadistaError as C}from"@uploadista/core/errors";var w=class extends t.Tag(`AuthCacheService`)(){};const T=(e={})=>{let t=e.maxSize??1e4,i=e.ttl??36e5,a=new Map,o=()=>{let e=Date.now();for(let[t,n]of a.entries())e-n.timestamp>i&&a.delete(t)},s=()=>{if(a.size<=t)return;let e=null,n=1/0;for(let[t,r]of a.entries())r.timestamp<n&&(n=r.timestamp,e=t);e&&a.delete(e)};return r.succeed(w,{set:(e,t)=>n.sync(()=>{a.size%100==0&&o(),a.set(e,{authContext:t,timestamp:Date.now()}),s()}),get:e=>n.sync(()=>{let t=a.get(e);return t?Date.now()-t.timestamp>i?(a.delete(e),null):t.authContext:null}),delete:e=>n.sync(()=>{a.delete(e)}),clear:()=>n.sync(()=>{a.clear()}),size:()=>n.sync(()=>a.size)})},E=r.succeed(w,{set:()=>n.void,get:()=>n.succeed(null),delete:()=>n.void,clear:()=>n.void,size:()=>n.succeed(0)}),D=e=>e.split(`/`).filter(Boolean),O=e=>{let t=D(e);return t[t.length-1]},k=(e,t)=>e.includes(`${t}/api/`),A=(e,t)=>e.replace(`${t}/api/`,``).split(`/`).filter(Boolean),j=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},M=e=>e[e.length-2],N=e=>({jobId:e[e.length-3],nodeId:e[e.length-1]}),P=e=>({storageId:e.pop(),flowId:e.pop()}),F=({kvStore:e,eventEmitter:t,dataStore:n,bufferedDataStore:i,generateId:a})=>{let o=r.provide(m,e),s=r.provide(n,o),c=i?r.provide(i,o):r.empty,l=r.provide(p,t),u=r.mergeAll(s,o,l,...a?[a]:[],c);return r.provide(S,u)},I=({kvStore:e,eventEmitter:t,flowProvider:n,uploadServer:i})=>{let a=r.provide(d,e),o=r.provide(u,t),s=r.mergeAll(n,o,a,i);return r.provide(c,s)};var L=class extends t.Tag(`AuthContextService`)(){};const R=e=>r.succeed(L,{getClientId:()=>n.succeed(e?.clientId??null),getMetadata:()=>n.succeed(e?.metadata??{}),hasPermission:t=>n.succeed(e?.permissions?.includes(t)??!1),getAuthContext:()=>n.succeed(e)}),z=R(null),B=({flowId:e})=>n.gen(function*(){let t=yield*o,r=yield*(yield*L).getClientId();return r&&(yield*n.logInfo(`[Flow] Getting flow data: ${e}, client: ${r}`)),{status:200,body:yield*t.getFlowData(e,r)}}),V=({flowId:e,storageId:t,inputs:r})=>n.gen(function*(){let i=yield*o,a=yield*L,s=yield*w,c=yield*a.getClientId();c?(yield*n.logInfo(`[Flow] Executing flow: ${e}, storage: ${t}, client: ${c}`),yield*n.logInfo(JSON.stringify(r,null,2))):(yield*n.logInfo(`[Flow] Executing flow: ${e}, storage: ${t}`),yield*n.logInfo(`[Flow] Inputs: ${JSON.stringify(r,null,2)}`)),yield*n.logInfo(`[Flow] Calling flowServer.runFlow...`);let l=yield*i.runFlow({flowId:e,storageId:t,clientId:c,inputs:r}).pipe(n.tap(()=>n.logInfo(`[Flow] runFlow completed successfully`)),n.tapError(e=>n.logError(`[Flow] runFlow failed with error: ${e}`))),u=yield*a.getAuthContext();return u&&(yield*s.set(l.id,u)),yield*n.logInfo(`[Flow] Flow started with jobId: ${l.id}`),{status:200,body:l}}),H=({jobId:e})=>n.gen(function*(){let t=yield*o,r=yield*L,i=yield*w,a=yield*r.getClientId();if(!e)throw Error(`No job id`);a&&(yield*n.logInfo(`[Flow] Getting job status: ${e}, client: ${a}`));let s=yield*t.getJobStatus(e);return(s.status===`completed`||s.status===`failed`)&&(yield*i.delete(e),a&&(yield*n.logInfo(`[Flow] Flow ${s.status}, cleared auth cache: ${e}`))),{status:200,body:s}}),U=({jobId:e,nodeId:t,newData:r})=>n.gen(function*(){let i=yield*o,a=yield*L,s=yield*w,c=yield*a.getClientId();if(c||=(yield*s.get(e))?.clientId??null,c&&(yield*n.logInfo(`[Flow] Continuing flow: jobId=${e}, nodeId=${t}, client: ${c}`)),r===void 0)throw Error(`Missing newData`);let l=yield*i.resumeFlow({jobId:e,nodeId:t,newData:r,clientId:c});return(l.status===`completed`||l.status===`failed`)&&(yield*s.delete(e),c&&(yield*n.logInfo(`[Flow] Flow ${l.status}, cleared auth cache: ${e}`))),{status:200,body:l}}),W=({jobId:e})=>n.gen(function*(){let t=yield*o,r=yield*L,i=yield*w,a=yield*r.getClientId();a||=(yield*i.get(e))?.clientId??null,a&&(yield*n.logInfo(`[Flow] Pausing flow: jobId=${e}, client: ${a}`));let s=yield*t.pauseFlow(e,a);return a&&(yield*n.logInfo(`[Flow] Flow paused: ${e}, status: ${s.status}`)),{status:200,body:s}}),G=({jobId:e})=>n.gen(function*(){let t=yield*o,r=yield*L,i=yield*w;if(!e)throw Error(`No job id`);let a=yield*r.getClientId();a||=(yield*i.get(e))?.clientId??null,a&&(yield*n.logInfo(`[Flow] Cancelling flow: jobId=${e}, client: ${a}`));let s=yield*t.cancelFlow(e,a);return yield*i.delete(e),a&&(yield*n.logInfo(`[Flow] Flow cancelled, cleared auth cache: ${e}`)),{status:200,body:s}});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`}},J=class extends K{constructor(e){super(`${e} not found`,404,`NOT_FOUND`),this.name=`NotFoundError`}},Y=class extends K{constructor(e){super(e,400,`BAD_REQUEST`),this.name=`BadRequestError`}};const X=e=>({error:e.message,code:e.errorCode,timestamp:new Date().toISOString()}),Z=e=>{let t={error:e.body,code:e.code,timestamp:new Date().toISOString()};return e.details!==void 0&&(t.details=e.details),t},Q=(e=`Internal server error`)=>({error:e,code:`INTERNAL_ERROR`,timestamp:new Date().toISOString()}),te=e=>n.gen(function*(){let t=yield*x,r=yield*L,i=yield*w,a=yield*r.getClientId();a&&(yield*n.logInfo(`[Upload] Creating upload for client: ${a}`));let o=yield*n.sync(()=>f.safeParse(e.data));if(!o.success)return yield*n.fail(new q(`Invalid input file schema`));if(o.data.checksumAlgorithm&&!h(o.data.checksumAlgorithm))return yield*n.fail(new q(`Unsupported checksum algorithm: ${o.data.checksumAlgorithm}. Supported algorithms: sha256`));let s=yield*t.createUpload(o.data,a),c=yield*r.getAuthContext();return c&&(yield*i.set(s.id,c)),a&&(yield*n.logInfo(`[Upload] Upload created: ${s.id} for client: ${a}`)),{status:200,body:s}}),ne=({storageId:e})=>n.gen(function*(){let t=yield*x,n=yield*(yield*L).getClientId();return{status:200,body:{storageId:e,capabilities:yield*t.getCapabilities(e,n),timestamp:new Date().toISOString()}}}),re=({uploadId:e})=>n.gen(function*(){return{status:200,body:yield*(yield*x).getUpload(e)}}),ie=e=>n.gen(function*(){let t=yield*x,r=yield*L,i=yield*w,a=yield*v,{uploadId:o,data:s}=e,c=yield*r.getClientId(),l=yield*r.getMetadata();if(!c){let e=yield*i.get(o);c=e?.clientId??null,l=e?.metadata??{}}c&&(yield*n.logInfo(`[Upload] Uploading chunk for upload: ${o}, client: ${c}`));let u=yield*t.uploadChunk(o,c,s);return u.size&&u.offset>=u.size&&(yield*i.delete(o),c&&(yield*n.logInfo(`[Upload] Upload completed, cleared auth cache: ${o}`)),c&&u.size?(yield*n.logInfo(`[Upload] Recording metrics for org: ${c}, size: ${u.size}`),yield*n.forkDaemon(a.recordUpload(c,u.size,l))):yield*n.logWarning(`[Upload] Cannot record metrics - missing organizationId or size`)),c&&(yield*n.logInfo(`[Upload] Chunk uploaded for upload: ${o}, client: ${c}`)),{status:200,body:u}}),ae=e=>n.gen(function*(){switch(e.type){case`create-upload`:return yield*te(e);case`get-capabilities`:return yield*ne(e);case`get-upload`:return yield*re(e);case`upload-chunk`:return yield*ie(e);case`get-flow`:return yield*B(e);case`run-flow`:return yield*V(e);case`job-status`:return yield*H(e);case`resume-flow`:return yield*U(e);case`pause-flow`:return yield*W(e);case`cancel-flow`:return yield*G(e);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`}}}}),$=async({flows:e,dataStore:t,kvStore:o,plugins:c=[],eventEmitter:u,eventBroadcaster:d=g,withTracing:f=!1,baseUrl:p=`uploadista`,generateId:m=ee,metricsLayer:h,bufferedDataStore:v,adapter:x,authCacheConfig:S})=>{let C=u??_(d),w=p.endsWith(`/`)?p.slice(0,-1):p,E=r.effect(a,n.succeed({getFlow:(t,n)=>e(t,n)}));if(!C)throw Error(`eventEmitter is required. Provide an event emitter layer in the configuration.`);let D=F({kvStore:o,eventEmitter:C,dataStore:await l(t),bufferedDataStore:v,generateId:m}),O=I({kvStore:o,eventEmitter:C,flowProvider:E,uploadServer:D}),k=T(S),A=h??y,M=r.mergeAll(D,O,A,k,...c),N=i.make(M);return{handler:async e=>{let t=n.gen(function*(){let t=yield*x.extractRequest(e,{baseUrl:w}),i=null;if(x.runAuthMiddleware){let t=yield*x.runAuthMiddleware(e).pipe(n.timeout(`5 seconds`),n.catchAll(()=>(console.error(`Auth middleware timeout exceeded (5 seconds)`),n.succeed({_tag:`TimeoutError`}))),n.catchAllCause(e=>(console.error(`Auth middleware error:`,e),n.succeed({_tag:`AuthError`,error:e}))));if(t&&typeof t==`object`&&`_tag`in t&&t._tag===`TimeoutError`)return yield*x.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(t&&typeof t==`object`&&`_tag`in t&&t._tag===`AuthError`)return yield*x.sendResponse({status:500,headers:{"Content-Type":`application/json`},body:{error:`Internal Server Error`,message:`An error occurred during authentication`}},e);if(t===null)return yield*x.sendResponse({status:401,headers:{"Content-Type":`application/json`},body:{error:`Unauthorized`,message:`Invalid credentials`}},e);i=t}let a=R(i),o=[];if(x.extractWaitUntil){let t=x.extractWaitUntil(e);t&&o.push(r.succeed(s,t))}let l=r.mergeAll(a,k,A,...c,...o);if(t.type===`not-found`)return yield*x.sendResponse({type:`not-found`,status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}},e);let u=yield*ae(t).pipe(n.provide(l));return yield*x.sendResponse(u,e)}).pipe(n.catchAll(t=>{let n=j(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 x.sendResponse(i,e)}));return f?N.runPromise(t.pipe(n.provide(b))):N.runPromise(t)},websocketHandler:await N.runPromise(x.webSocketHandler({baseUrl:w})),baseUrl:w,dispose:()=>N.dispose()}},oe=(e,t,r)=>n.gen(function*(){if(!t){yield*n.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Job ID is required for flow event subscription`,code:`MISSING_JOB_ID`}))});return}yield*e.subscribeToFlowEvents(t,r)}),se=(e,t)=>n.gen(function*(){t&&(yield*e.unsubscribeFromFlowEvents(t))}),ce=(e,t,r)=>n.gen(function*(){if(!t){yield*n.sync(()=>{r.send(JSON.stringify({type:`error`,message:`Upload ID is required for upload event subscription`,code:`MISSING_UPLOAD_ID`}))});return}yield*e.subscribeToUploadEvents(t,r)}),le=(e,t)=>n.gen(function*(){t&&(yield*e.unsubscribeFromUploadEvents(t))}),ue=(e,t,r)=>{let{connection:i,isFlowRoute:a,isUploadRoute:o,jobId:s,uploadId:c,eventId:l}=e;return n.gen(function*(){a&&(yield*oe(r,s,i)),o&&(yield*ce(t,c,i)),i.send(JSON.stringify({type:`connection`,message:`Uploadista WebSocket connected`,id:l,jobId:s,uploadId:c,timestamp:new Date().toISOString()}))}).pipe(n.catchAll(e=>n.sync(()=>{console.error(`Error subscribing to events:`,e);let t=e instanceof C?e.body:`Failed to subscribe to events`;i.send(JSON.stringify({type:`error`,message:t,code:e instanceof C?e.code:`SUBSCRIPTION_ERROR`}))})))},de=(e,t)=>n.sync(()=>{try{JSON.parse(e).type===`ping`&&t.send(JSON.stringify({type:`pong`,timestamp:new Date().toISOString()}))}catch(e){console.error(`Error handling WebSocket message:`,e),t.send(JSON.stringify({type:`error`,message:`Invalid message format`}))}}),fe=(e,t,r)=>{let{isFlowRoute:i,isUploadRoute:a,jobId:o,uploadId:s}=e;return n.gen(function*(){i&&(yield*se(r,o)),a&&(yield*le(t,s))}).pipe(n.catchAll(e=>n.sync(()=>{console.error(`Error unsubscribing from events:`,e instanceof C?e.body:e)})))},pe=(e,t)=>n.sync(()=>{console.error(`WebSocket error for event ${t}:`,e)});export{K as AdapterError,w as AuthCacheService,T as AuthCacheServiceLive,L as AuthContextService,R as AuthContextServiceLive,Y as BadRequestError,E as NoAuthCacheServiceLive,z as NoAuthContextServiceLive,J as NotFoundError,q as ValidationError,X as createErrorResponseBody,I as createFlowServerLayer,Q as createGenericErrorResponseBody,F as createUploadServerLayer,Z as createUploadistaErrorResponseBody,$ as createUploadistaServer,P as extractFlowAndStorageId,N as extractJobAndNodeId,M as extractJobIdFromStatus,e as getAuthCredentials,O as getLastSegment,A as getRouteSegments,j as handleFlowError,fe as handleWebSocketClose,pe as handleWebSocketError,de as handleWebSocketMessage,ue as handleWebSocketOpen,k as hasBasePath,D as parseUrlSegments};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["oldestKey: string | null","NoAuthCacheServiceLive: Layer.Layer<AuthCacheService>","details: unknown","result: {\n status: number;\n code: string;\n message: string;\n details?: unknown;\n }","uploadServer","NoAuthContextServiceLive: Layer.Layer<AuthContextService>","flowServer","statusCode: number","errorCode: string","response: {\n error: string;\n code: string;\n timestamp: string;\n details?: unknown;\n }","authContext: AuthContext | null","authResult:\n | AuthContext\n | null\n | { _tag: \"TimeoutError\" }\n | { _tag: \"AuthError\"; error: unknown }","waitUntilLayers: Layer.Layer<any, never, never>[]","errorBody: Record<string, unknown>","errorResponse: StandardResponse","flowServer","uploadServer","flowServer","uploadServer"],"sources":["../src/cache.ts","../src/http-utils.ts","../src/layer-utils.ts","../src/service.ts","../src/core/http-handlers/flow-http-handlers.ts","../src/error-types.ts","../src/core/http-handlers/upload-http-handlers.ts","../src/core/http-handlers/http-handlers.ts","../src/core/server.ts","../src/core/websocket-handlers/flow-websocket-handlers.ts","../src/core/websocket-handlers/upload-websocket-handlers.ts","../src/core/websocket-handlers/websocket-handlers.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\nimport type { AuthContext } from \"./types\";\n\n/**\n * Configuration options for the auth cache.\n */\nexport type AuthCacheConfig = {\n /**\n * Maximum number of entries in the cache.\n * When exceeded, oldest entries are removed (LRU eviction).\n * @default 10000\n */\n maxSize?: number;\n\n /**\n * Time-to-live for cache entries in milliseconds.\n * Entries older than this will be automatically evicted.\n * @default 3600000 (1 hour)\n */\n ttl?: number;\n};\n\n/**\n * Cache entry with auth context and timestamp.\n */\ntype CacheEntry = {\n authContext: AuthContext;\n timestamp: number;\n};\n\n/**\n * Auth Cache Service\n *\n * Provides caching of authentication contexts for upload and flow jobs.\n * This allows subsequent operations (chunk uploads, flow continuations)\n * to reuse the auth context from the initial request without re-authenticating.\n *\n * @example\n * ```typescript\n * import { Effect } from \"effect\";\n * import { AuthCacheService } from \"@uploadista/server\";\n *\n * const handler = Effect.gen(function* () {\n * const authCache = yield* AuthCacheService;\n * const authContext = { userId: \"user-123\" };\n *\n * // Cache auth for upload\n * yield* authCache.set(\"upload-abc\", authContext);\n *\n * // Retrieve cached auth later\n * const cached = yield* authCache.get(\"upload-abc\");\n * console.log(cached?.userId); // \"user-123\"\n *\n * // Clear when done\n * yield* authCache.delete(\"upload-abc\");\n * });\n * ```\n */\nexport class AuthCacheService extends Context.Tag(\"AuthCacheService\")<\n AuthCacheService,\n {\n /**\n * Store an auth context for a job ID.\n */\n readonly set: (\n jobId: string,\n authContext: AuthContext,\n ) => Effect.Effect<void>;\n\n /**\n * Retrieve a cached auth context by job ID.\n * Returns null if not found or expired.\n */\n readonly get: (jobId: string) => Effect.Effect<AuthContext | null>;\n\n /**\n * Delete a cached auth context by job ID.\n */\n readonly delete: (jobId: string) => Effect.Effect<void>;\n\n /**\n * Clear all cached auth contexts.\n */\n readonly clear: () => Effect.Effect<void>;\n\n /**\n * Get the current number of cached entries.\n */\n readonly size: () => Effect.Effect<number>;\n }\n>() {}\n\n/**\n * Creates an AuthCacheService Layer with in-memory storage.\n *\n * @param config - Optional configuration for cache behavior\n * @returns Effect Layer providing AuthCacheService\n */\nexport const AuthCacheServiceLive = (\n config: AuthCacheConfig = {},\n): Layer.Layer<AuthCacheService> => {\n const maxSize = config.maxSize ?? 10000;\n const ttl = config.ttl ?? 3600000; // 1 hour default\n\n // In-memory cache storage\n const cache = new Map<string, CacheEntry>();\n\n /**\n * Evict expired entries based on TTL.\n */\n const evictExpired = (): void => {\n const now = Date.now();\n for (const [jobId, entry] of cache.entries()) {\n if (now - entry.timestamp > ttl) {\n cache.delete(jobId);\n }\n }\n };\n\n /**\n * Enforce max size limit using LRU eviction.\n * Removes oldest entry when cache exceeds max size.\n */\n const enforceSizeLimit = (): void => {\n if (cache.size <= maxSize) return;\n\n // Find and remove oldest entry\n let oldestKey: string | null = null;\n let oldestTime = Number.POSITIVE_INFINITY;\n\n for (const [jobId, entry] of cache.entries()) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldestKey = jobId;\n }\n }\n\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n };\n\n return Layer.succeed(AuthCacheService, {\n set: (jobId: string, authContext: AuthContext) =>\n Effect.sync(() => {\n // Evict expired entries periodically\n if (cache.size % 100 === 0) {\n evictExpired();\n }\n\n cache.set(jobId, {\n authContext,\n timestamp: Date.now(),\n });\n\n // Enforce size limit after adding\n enforceSizeLimit();\n }),\n\n get: (jobId: string) =>\n Effect.sync(() => {\n const entry = cache.get(jobId);\n if (!entry) return null;\n\n // Check if expired\n const now = Date.now();\n if (now - entry.timestamp > ttl) {\n cache.delete(jobId);\n return null;\n }\n\n return entry.authContext;\n }),\n\n delete: (jobId: string) =>\n Effect.sync(() => {\n cache.delete(jobId);\n }),\n\n clear: () =>\n Effect.sync(() => {\n cache.clear();\n }),\n\n size: () =>\n Effect.sync(() => {\n return cache.size;\n }),\n });\n};\n\n/**\n * No-op implementation of AuthCacheService.\n * Does not cache anything - all operations are no-ops.\n * Used when caching is disabled or not needed.\n */\nexport const NoAuthCacheServiceLive: Layer.Layer<AuthCacheService> =\n Layer.succeed(AuthCacheService, {\n set: () => Effect.void,\n get: () => Effect.succeed(null),\n delete: () => Effect.void,\n clear: () => Effect.void,\n size: () => Effect.succeed(0),\n });\n","/**\n * Shared HTTP utilities for server adapters\n *\n * This module provides routing and error handling utilities used across\n * Hono, Express, and Fastify adapters for request parsing and response formatting.\n */\n\n/**\n * Parses URL segments from a pathname, filtering out empty segments.\n * Useful for extracting route components from request paths.\n *\n * @param pathname - The URL pathname (e.g., \"/uploadista/api/upload/abc123\")\n * @returns Array of non-empty path segments\n *\n * @example\n * ```typescript\n * const segments = parseUrlSegments(\"/uploadista/api/upload/abc123\");\n * // => [\"uploadista\", \"api\", \"upload\", \"abc123\"]\n * ```\n */\nexport const parseUrlSegments = (pathname: string): string[] => {\n return pathname.split(\"/\").filter(Boolean);\n};\n\n/**\n * Extracts the last segment from a URL pathname.\n *\n * @param pathname - The URL pathname to parse\n * @returns The last non-empty segment, or undefined if none exists\n *\n * @example\n * ```typescript\n * const id = getLastSegment(\"/uploadista/api/upload/abc123\");\n * // => \"abc123\"\n * ```\n */\nexport const getLastSegment = (pathname: string): string | undefined => {\n const segments = parseUrlSegments(pathname);\n return segments[segments.length - 1];\n};\n\n/**\n * Checks if a pathname includes a specific base path and API prefix.\n * Used to determine if a request should be handled by the Uploadista adapter.\n *\n * @param pathname - The request pathname\n * @param basePath - The base path configured for the adapter (e.g., \"uploadista\")\n * @returns true if the path includes `{basePath}/api/`\n *\n * @example\n * ```typescript\n * const isUploadistaPath = hasBasePath(\"/uploadista/api/upload\", \"uploadista\");\n * // => true\n * ```\n */\nexport const hasBasePath = (pathname: string, basePath: string): boolean => {\n return pathname.includes(`${basePath}/api/`);\n};\n\n/**\n * Removes the base path prefix and returns clean route segments.\n * Transforms \"/uploadista/api/upload/abc123\" → [\"upload\", \"abc123\"]\n *\n * @param pathname - The full request pathname\n * @param basePath - The base path to remove (e.g., \"uploadista\")\n * @returns Array of route segments without base path prefix\n *\n * @example\n * ```typescript\n * const route = getRouteSegments(\"/uploadista/api/upload/abc123\", \"uploadista\");\n * // => [\"upload\", \"abc123\"]\n * ```\n */\nexport const getRouteSegments = (\n pathname: string,\n basePath: string,\n): string[] => {\n return pathname.replace(`${basePath}/api/`, \"\").split(\"/\").filter(Boolean);\n};\n\n/**\n * Standard error handler for flow and job operations.\n * Maps application errors to appropriate HTTP status codes and error formats.\n *\n * Supports errors with `code`, `message`, `status`, and `details` properties.\n * Maps error codes to HTTP status codes (e.g., NOT_FOUND → 404, VALIDATION_ERROR → 400).\n *\n * @param error - The error object to handle (can be any type)\n * @returns Standardized error response with status, code, message, and optional details\n *\n * @example\n * ```typescript\n * import { handleFlowError } from \"@uploadista/server\";\n *\n * const response = handleFlowError({\n * code: \"FLOW_JOB_NOT_FOUND\",\n * message: \"Job not found\",\n * });\n * // => { status: 404, code: \"FLOW_JOB_NOT_FOUND\", message: \"Job not found\" }\n * ```\n */\nexport const handleFlowError = (\n error: unknown,\n): { status: number; code: string; message: string; details?: unknown } => {\n let status = 500;\n let code = \"UNKNOWN_ERROR\";\n let message = \"Internal server error\";\n let details: unknown;\n\n if (typeof error === \"object\" && error !== null) {\n const errorObj = error as Record<string, unknown>;\n\n // Extract error code\n if (\"code\" in errorObj && typeof errorObj.code === \"string\") {\n code = errorObj.code;\n }\n\n // Extract message\n if (\"message\" in errorObj && typeof errorObj.message === \"string\") {\n message = errorObj.message;\n } else if (\"body\" in errorObj && typeof errorObj.body === \"string\") {\n // Support UploadistaError's body property\n message = errorObj.body;\n }\n\n // Extract details if present\n if (\"details\" in errorObj) {\n details = errorObj.details;\n }\n\n // Map error codes to HTTP status codes\n if (\"status\" in errorObj && typeof errorObj.status === \"number\") {\n status = errorObj.status;\n } else if (\"code\" in errorObj) {\n // Fallback: derive status from common error codes\n switch (errorObj.code) {\n case \"FILE_NOT_FOUND\":\n case \"FLOW_JOB_NOT_FOUND\":\n case \"UPLOAD_ID_NOT_FOUND\":\n status = 404;\n break;\n case \"FLOW_JOB_ERROR\":\n case \"VALIDATION_ERROR\":\n case \"INVALID_METADATA\":\n case \"INVALID_LENGTH\":\n case \"ABORTED\":\n case \"INVALID_TERMINATION\":\n status = 400;\n break;\n case \"INVALID_OFFSET\":\n status = 409;\n break;\n case \"ERR_SIZE_EXCEEDED\":\n case \"ERR_MAX_SIZE_EXCEEDED\":\n status = 413;\n break;\n case \"FILE_NO_LONGER_EXISTS\":\n status = 410;\n break;\n case \"MISSING_OFFSET\":\n case \"INVALID_CONTENT_TYPE\":\n status = 403;\n break;\n default:\n status = 500;\n }\n }\n\n // Special handling for specific error messages\n if (\"message\" in errorObj && errorObj.message === \"Invalid JSON body\") {\n status = 400;\n code = \"VALIDATION_ERROR\";\n }\n }\n\n const result: {\n status: number;\n code: string;\n message: string;\n details?: unknown;\n } = {\n status,\n code,\n message,\n };\n\n if (details !== undefined) {\n result.details = details;\n }\n\n return result;\n};\n\n/**\n * Extracts job ID from URL segments for job status endpoint.\n * Expected URL format: `/uploadista/api/jobs/:jobId/status`\n *\n * @param urlSegments - Parsed URL segments (without base path)\n * @returns The job ID if found, or undefined\n *\n * @example\n * ```typescript\n * const jobId = extractJobIdFromStatus([\"jobs\", \"job-123\", \"status\"]);\n * // => \"job-123\"\n * ```\n */\nexport const extractJobIdFromStatus = (\n urlSegments: string[],\n): string | undefined => {\n return urlSegments[urlSegments.length - 2];\n};\n\n/**\n * Extracts job ID and node ID from URL segments for resume flow endpoint.\n * Expected URL format: `/uploadista/api/jobs/:jobId/resume/:nodeId`\n *\n * @param urlSegments - Parsed URL segments (without base path)\n * @returns Object with extracted jobId and nodeId (either can be undefined if not found)\n *\n * @example\n * ```typescript\n * const { jobId, nodeId } = extractJobAndNodeId([\n * \"jobs\",\n * \"job-123\",\n * \"resume\",\n * \"node-456\",\n * ]);\n * // => { jobId: \"job-123\", nodeId: \"node-456\" }\n * ```\n */\nexport const extractJobAndNodeId = (\n urlSegments: string[],\n): { jobId: string | undefined; nodeId: string | undefined } => {\n return {\n jobId: urlSegments[urlSegments.length - 3],\n nodeId: urlSegments[urlSegments.length - 1],\n };\n};\n\n/**\n * Extracts flow ID and storage ID from URL segments.\n * Expected URL format: `/uploadista/api/flow/:flowId/:storageId`\n *\n * Mutates the input array (removes last 2 elements).\n *\n * @param urlSegments - Parsed URL segments (will be mutated)\n * @returns Object with extracted flowId and storageId\n *\n * @example\n * ```typescript\n * const segments = [\"flow\", \"flow-123\", \"storage-456\"];\n * const { flowId, storageId } = extractFlowAndStorageId(segments);\n * // => { flowId: \"flow-123\", storageId: \"storage-456\" }\n * // segments is now [\"flow\"]\n * ```\n */\nexport const extractFlowAndStorageId = (\n urlSegments: string[],\n): { flowId: string | undefined; storageId: string | undefined } => {\n return {\n storageId: urlSegments.pop(),\n flowId: urlSegments.pop(),\n };\n};\n","import type { FlowProvider } from \"@uploadista/core/flow\";\nimport { flowServer } from \"@uploadista/core/flow\";\nimport {\n type BaseEventEmitterService,\n type BaseKvStoreService,\n flowEventEmitter,\n flowJobKvStore,\n type UploadFileDataStore,\n type UploadFileDataStores,\n type UploadFileKVStore,\n uploadEventEmitter,\n uploadFileKvStore,\n} from \"@uploadista/core/types\";\nimport { type UploadServer, uploadServer } from \"@uploadista/core/upload\";\nimport type { GenerateId } from \"@uploadista/core/utils\";\nimport { Layer } from \"effect\";\n\n/**\n * Configuration for creating upload server layers.\n * Specifies all dependencies needed by the upload server Effect Layer.\n *\n * @property kvStore - Key-value store for upload metadata\n * @property eventEmitter - Event emitter for upload progress events\n * @property dataStore - File data storage implementation\n * @property bufferedDataStore - Optional buffered storage for performance optimization\n * @property generateId - Optional custom ID generator (uses default if omitted)\n *\n * @example\n * ```typescript\n * import { createUploadServerLayer } from \"@uploadista/server\";\n *\n * const uploadLayerConfig: UploadServerLayerConfig = {\n * kvStore: redisKvStore,\n * eventEmitter: webSocketEventEmitter,\n * dataStore: s3DataStore,\n * };\n * ```\n */\nexport interface UploadServerLayerConfig {\n kvStore: Layer.Layer<BaseKvStoreService>;\n eventEmitter: Layer.Layer<BaseEventEmitterService>;\n dataStore: Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;\n bufferedDataStore?: Layer.Layer<\n UploadFileDataStore,\n never,\n UploadFileKVStore\n >;\n generateId?: Layer.Layer<GenerateId>;\n}\n\n/**\n * Configuration for creating flow server layers.\n * Specifies all dependencies needed by the flow processing server.\n *\n * @property kvStore - Key-value store for flow job metadata\n * @property eventEmitter - Event emitter for flow progress events\n * @property flowProvider - Factory function for creating flows\n * @property uploadServer - Upload server layer (used by flows for uploads)\n *\n * @example\n * ```typescript\n * import { createFlowServerLayer } from \"@uploadista/server\";\n *\n * const flowLayerConfig: FlowServerLayerConfig = {\n * kvStore: redisKvStore,\n * eventEmitter: webSocketEventEmitter,\n * flowProvider: createFlowsEffect,\n * uploadServer: uploadServerLayer,\n * };\n * ```\n */\nexport interface FlowServerLayerConfig {\n kvStore: Layer.Layer<BaseKvStoreService>;\n eventEmitter: Layer.Layer<BaseEventEmitterService>;\n flowProvider: Layer.Layer<FlowProvider>;\n uploadServer: Layer.Layer<UploadServer>;\n}\n\n/**\n * Creates the upload server layer with all dependencies composed.\n * This layer handles file uploads with chunked transfer, resumption, and metadata tracking.\n *\n * The created layer includes:\n * - Upload KV store (metadata tracking)\n * - Data store (file storage)\n * - Event emitter (progress notifications)\n * - Optional buffered data store (performance optimization)\n * - Optional custom ID generator\n *\n * @param config - Upload server layer configuration\n * @returns Effect Layer providing UploadServer\n *\n * @example\n * ```typescript\n * import { createUploadServerLayer } from \"@uploadista/server\";\n * import { Layer } from \"effect\";\n *\n * const uploadServerLayer = createUploadServerLayer({\n * kvStore: redisKvStore,\n * eventEmitter: webSocketEventEmitter,\n * dataStore: s3DataStore,\n * });\n *\n * // Use in application\n * const app = Layer.provide(appLogic, uploadServerLayer);\n * ```\n */\nexport const createUploadServerLayer = ({\n kvStore,\n eventEmitter,\n dataStore,\n bufferedDataStore,\n generateId,\n}: UploadServerLayerConfig) => {\n // Set up upload server dependencies\n const uploadFileKVStoreLayer = Layer.provide(uploadFileKvStore, kvStore);\n const uploadDataStoreLayer = Layer.provide(dataStore, uploadFileKVStoreLayer);\n const uploadBufferedDataStoreLayer = bufferedDataStore\n ? Layer.provide(bufferedDataStore, uploadFileKVStoreLayer)\n : Layer.empty;\n const uploadEventEmitterLayer = Layer.provide(\n uploadEventEmitter,\n eventEmitter,\n );\n\n const uploadServerLayers = Layer.mergeAll(\n uploadDataStoreLayer,\n uploadFileKVStoreLayer,\n uploadEventEmitterLayer,\n ...(generateId ? [generateId] : []),\n uploadBufferedDataStoreLayer,\n );\n\n return Layer.provide(uploadServer, uploadServerLayers);\n};\n\n/**\n * Creates the flow server layer with all dependencies composed.\n * This layer handles file processing workflows with multi-stage pipelines.\n *\n * The created layer includes:\n * - Flow job KV store (job metadata and state)\n * - Event emitter (progress notifications)\n * - Flow provider (flow definitions)\n * - Upload server (for uploads within flows)\n *\n * @param config - Flow server layer configuration\n * @returns Effect Layer providing FlowServer\n *\n * @example\n * ```typescript\n * import { createFlowServerLayer } from \"@uploadista/server\";\n * import { Layer } from \"effect\";\n *\n * const flowServerLayer = createFlowServerLayer({\n * kvStore: redisKvStore,\n * eventEmitter: webSocketEventEmitter,\n * flowProvider: createFlowsEffect,\n * uploadServer: uploadServerLayer,\n * });\n *\n * // Use in application\n * const app = Layer.provide(appLogic, flowServerLayer);\n * ```\n */\nexport const createFlowServerLayer = ({\n kvStore,\n eventEmitter,\n flowProvider,\n uploadServer,\n}: FlowServerLayerConfig) => {\n // Set up flow server dependencies\n const flowJobKVStoreLayer = Layer.provide(flowJobKvStore, kvStore);\n const flowEventEmitterLayer = Layer.provide(flowEventEmitter, eventEmitter);\n\n const flowServerLayers = Layer.mergeAll(\n flowProvider,\n flowEventEmitterLayer,\n flowJobKVStoreLayer,\n uploadServer,\n );\n\n return Layer.provide(flowServer, flowServerLayers);\n};\n","import { Context, Effect, Layer } from \"effect\";\nimport type { AuthContext } from \"./types\";\n\n/**\n * Authentication Context Service\n *\n * Provides access to the current authentication context throughout\n * the upload and flow processing pipeline. The service is provided\n * via Effect Layer and can be accessed using Effect.service().\n *\n * @example\n * ```typescript\n * import { Effect } from \"effect\";\n * import { AuthContextService } from \"@uploadista/server\";\n *\n * const uploadHandler = Effect.gen(function* () {\n * const authService = yield* AuthContextService;\n * const clientId = yield* authService.getClientId();\n * if (clientId) {\n * console.log(`Processing upload for client: ${clientId}`);\n * }\n * });\n * ```\n */\nexport class AuthContextService extends Context.Tag(\"AuthContextService\")<\n AuthContextService,\n {\n /**\n * Get the current client ID from auth context.\n * Returns null if no authentication context is available.\n */\n readonly getClientId: () => Effect.Effect<string | null>;\n\n /**\n * Get the current auth metadata.\n * Returns empty object if no authentication context or no metadata.\n */\n readonly getMetadata: () => Effect.Effect<Record<string, unknown>>;\n\n /**\n * Check if the current client has a specific permission.\n * Returns false if no authentication context or permission not found.\n */\n readonly hasPermission: (permission: string) => Effect.Effect<boolean>;\n\n /**\n * Get the full authentication context if available.\n * Returns null if no authentication context is available.\n */\n readonly getAuthContext: () => Effect.Effect<AuthContext | null>;\n }\n>() {}\n\n/**\n * Creates an AuthContextService Layer from an AuthContext.\n * This is typically called by adapters after successful authentication.\n *\n * @param authContext - The authentication context from middleware\n * @returns Effect Layer providing AuthContextService\n */\nexport const AuthContextServiceLive = (\n authContext: AuthContext | null,\n): Layer.Layer<AuthContextService> =>\n Layer.succeed(AuthContextService, {\n getClientId: () => Effect.succeed(authContext?.clientId ?? null),\n getMetadata: () => Effect.succeed(authContext?.metadata ?? {}),\n hasPermission: (permission: string) =>\n Effect.succeed(authContext?.permissions?.includes(permission) ?? false),\n getAuthContext: () => Effect.succeed(authContext),\n });\n\n/**\n * No-auth implementation of AuthContextService.\n * Returns null/empty values for all operations.\n * Used when no authentication middleware is configured (backward compatibility).\n */\nexport const NoAuthContextServiceLive: Layer.Layer<AuthContextService> =\n AuthContextServiceLive(null);\n","import { FlowServer } from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\nimport { AuthCacheService } from \"../../cache\";\nimport { AuthContextService } from \"../../service\";\nimport type {\n CancelFlowRequest,\n CancelFlowResponse,\n GetFlowRequest,\n GetFlowResponse,\n GetJobStatusRequest,\n GetJobStatusResponse,\n PauseFlowRequest,\n PauseFlowResponse,\n ResumeFlowRequest,\n ResumeFlowResponse,\n RunFlowRequest,\n RunFlowResponse,\n} from \"../routes\";\n\nexport const handleGetFlow = ({ flowId }: GetFlowRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Access auth context if available\n const authService = yield* AuthContextService;\n const clientId = yield* authService.getClientId();\n\n if (clientId) {\n yield* Effect.logInfo(`[Flow] Getting flow data: ${flowId}, client: ${clientId}`);\n }\n\n const flowData = yield* flowServer.getFlowData(flowId, clientId);\n\n return {\n status: 200,\n body: flowData,\n } as GetFlowResponse;\n });\n};\n\nexport const handleRunFlow = <TRequirements>({\n flowId,\n storageId,\n inputs,\n}: RunFlowRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Access auth context if available\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n const clientId = yield* authService.getClientId();\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Flow] Executing flow: ${flowId}, storage: ${storageId}, client: ${clientId}`,\n );\n yield* Effect.logInfo(JSON.stringify(inputs, null, 2));\n } else {\n yield* Effect.logInfo(`[Flow] Executing flow: ${flowId}, storage: ${storageId}`);\n yield* Effect.logInfo(`[Flow] Inputs: ${JSON.stringify(inputs, null, 2)}`);\n }\n\n // Run flow returns immediately with jobId\n yield* Effect.logInfo(`[Flow] Calling flowServer.runFlow...`);\n const result = yield* flowServer.runFlow<TRequirements>({\n flowId,\n storageId,\n clientId,\n inputs,\n }).pipe(\n Effect.tap(() => Effect.logInfo(`[Flow] runFlow completed successfully`)),\n Effect.tapError((error) =>\n Effect.logError(`[Flow] runFlow failed with error: ${error}`)\n ),\n );\n\n // Cache auth context for subsequent flow operations (continue, status)\n const authContext = yield* authService.getAuthContext();\n if (authContext) {\n yield* authCache.set(result.id, authContext);\n }\n\n yield* Effect.logInfo(`[Flow] Flow started with jobId: ${result.id}`);\n\n return {\n status: 200,\n body: result,\n } as RunFlowResponse;\n });\n};\n\nexport const handleJobStatus = ({ jobId }: GetJobStatusRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Access auth context if available\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n const clientId = yield* authService.getClientId();\n\n if (!jobId) {\n throw new Error(\"No job id\");\n }\n\n if (clientId) {\n yield* Effect.logInfo(`[Flow] Getting job status: ${jobId}, client: ${clientId}`);\n }\n\n const result = yield* flowServer.getJobStatus(jobId);\n\n // Clear cache if flow is completed or failed\n if (result.status === \"completed\" || result.status === \"failed\") {\n yield* authCache.delete(jobId);\n if (clientId) {\n yield* Effect.logInfo(\n `[Flow] Flow ${result.status}, cleared auth cache: ${jobId}`,\n );\n }\n }\n\n return {\n status: 200,\n body: result,\n } as GetJobStatusResponse;\n });\n};\n\nexport const handleResumeFlow = <TRequirements>({\n jobId,\n nodeId,\n newData,\n}: ResumeFlowRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Try to get auth from current request or cached auth\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n\n // Try current auth first, fallback to cached auth\n let clientId = yield* authService.getClientId();\n if (!clientId) {\n const cachedAuth = yield* authCache.get(jobId);\n clientId = cachedAuth?.clientId ?? null;\n }\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Flow] Continuing flow: jobId=${jobId}, nodeId=${nodeId}, client: ${clientId}`,\n );\n }\n\n if (newData === undefined) {\n throw new Error(\"Missing newData\");\n }\n\n const result = yield* flowServer.resumeFlow<TRequirements>({\n jobId,\n nodeId,\n newData,\n clientId,\n });\n\n // Clear cache if flow is completed or failed\n if (result.status === \"completed\" || result.status === \"failed\") {\n yield* authCache.delete(jobId);\n if (clientId) {\n yield* Effect.logInfo(\n `[Flow] Flow ${result.status}, cleared auth cache: ${jobId}`,\n );\n }\n }\n\n return {\n status: 200,\n body: result,\n } as ResumeFlowResponse;\n });\n};\nexport const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Try to get auth from current request or cached auth\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n\n // Try current auth first, fallback to cached auth\n let clientId = yield* authService.getClientId();\n if (!clientId) {\n const cachedAuth = yield* authCache.get(jobId);\n clientId = cachedAuth?.clientId ?? null;\n }\n\n if (clientId) {\n yield* Effect.logInfo(`[Flow] Pausing flow: jobId=${jobId}, client: ${clientId}`);\n }\n\n const result = yield* flowServer.pauseFlow(jobId, clientId);\n\n if (clientId) {\n yield* Effect.logInfo(`[Flow] Flow paused: ${jobId}, status: ${result.status}`);\n }\n\n return {\n status: 200,\n body: result,\n } as PauseFlowResponse;\n });\n};\n\nexport const handleCancelFlow = ({ jobId }: CancelFlowRequest) => {\n return Effect.gen(function* () {\n const flowServer = yield* FlowServer;\n // Try to get auth from current request or cached auth\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n\n if (!jobId) {\n throw new Error(\"No job id\");\n }\n\n // Try current auth first, fallback to cached auth\n let clientId = yield* authService.getClientId();\n if (!clientId) {\n const cachedAuth = yield* authCache.get(jobId);\n clientId = cachedAuth?.clientId ?? null;\n }\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Flow] Cancelling flow: jobId=${jobId}, client: ${clientId}`,\n );\n }\n\n const result = yield* flowServer.cancelFlow(jobId, clientId);\n\n // Clear cache since flow is cancelled\n yield* authCache.delete(jobId);\n if (clientId) {\n yield* Effect.logInfo(`[Flow] Flow cancelled, cleared auth cache: ${jobId}`);\n }\n\n return {\n status: 200,\n body: result,\n } as CancelFlowResponse;\n });\n};\n","import type { UploadistaError } from \"@uploadista/core/errors\";\n\n/**\n * Base adapter error class for HTTP adapters.\n * All adapter-specific errors should extend this class or one of its subclasses.\n *\n * @example\n * ```typescript\n * throw new AdapterError(\"Something went wrong\", 500, \"INTERNAL_ERROR\");\n * ```\n */\nexport class AdapterError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n public readonly errorCode: string = \"INTERNAL_ERROR\",\n ) {\n super(message);\n this.name = \"AdapterError\";\n }\n}\n\n/**\n * Validation error - indicates invalid request data or parameters.\n * Returns HTTP 400 Bad Request status.\n *\n * @example\n * ```typescript\n * if (!isValidUploadId(id)) {\n * throw new ValidationError(\"Invalid upload ID format\");\n * }\n * ```\n */\nexport class ValidationError extends AdapterError {\n constructor(message: string) {\n super(message, 400, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Not found error - indicates a requested resource does not exist.\n * Returns HTTP 404 Not Found status.\n *\n * @example\n * ```typescript\n * if (!upload) {\n * throw new NotFoundError(\"Upload\");\n * }\n * ```\n */\nexport class NotFoundError extends AdapterError {\n constructor(resource: string) {\n super(`${resource} not found`, 404, \"NOT_FOUND\");\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Bad request error - indicates a malformed request.\n * Returns HTTP 400 Bad Request status.\n * Similar to ValidationError but for request structure issues.\n *\n * @example\n * ```typescript\n * try {\n * const data = JSON.parse(body);\n * } catch {\n * throw new BadRequestError(\"Invalid JSON body\");\n * }\n * ```\n */\nexport class BadRequestError extends AdapterError {\n constructor(message: string) {\n super(message, 400, \"BAD_REQUEST\");\n this.name = \"BadRequestError\";\n }\n}\n\n/**\n * Creates a standardized error response object for AdapterError.\n * Includes error message, error code, and ISO timestamp.\n *\n * @param error - The AdapterError to format\n * @returns Standardized error response body\n *\n * @example\n * ```typescript\n * import { createErrorResponseBody } from \"@uploadista/server\";\n *\n * try {\n * // ... operation\n * } catch (err) {\n * const errorResponse = createErrorResponseBody(err);\n * res.status(err.statusCode).json(errorResponse);\n * }\n * ```\n */\nexport const createErrorResponseBody = (error: AdapterError) => ({\n error: error.message,\n code: error.errorCode,\n timestamp: new Date().toISOString(),\n});\n\n/**\n * Creates a standardized error response body from UploadistaError.\n * Formats core library errors for HTTP responses with optional details.\n *\n * @param error - The UploadistaError to format\n * @returns Standardized error response body with error, code, timestamp, and optional details\n *\n * @example\n * ```typescript\n * import { createUploadistaErrorResponseBody } from \"@uploadista/server\";\n *\n * try {\n * const result = yield* uploadServer.handleUpload(input);\n * } catch (err) {\n * if (err instanceof UploadistaError) {\n * const errorResponse = createUploadistaErrorResponseBody(err);\n * res.status(400).json(errorResponse);\n * }\n * }\n * ```\n */\nexport const createUploadistaErrorResponseBody = (error: UploadistaError) => {\n const response: {\n error: string;\n code: string;\n timestamp: string;\n details?: unknown;\n } = {\n error: error.body,\n code: error.code,\n timestamp: new Date().toISOString(),\n };\n\n if (error.details !== undefined) {\n response.details = error.details;\n }\n\n return response;\n};\n\n/**\n * Creates a generic error response body for unknown/unexpected errors.\n * Used as a fallback when error type cannot be determined.\n *\n * @param message - Error message to include in response (defaults to \"Internal server error\")\n * @returns Standardized error response body with generic INTERNAL_ERROR code\n *\n * @example\n * ```typescript\n * import { createGenericErrorResponseBody } from \"@uploadista/server\";\n *\n * try {\n * // ... operation\n * } catch (err) {\n * const errorResponse = createGenericErrorResponseBody(\n * err instanceof Error ? err.message : \"Unknown error\"\n * );\n * res.status(500).json(errorResponse);\n * }\n * ```\n */\nexport const createGenericErrorResponseBody = (\n message = \"Internal server error\",\n) => ({\n error: message,\n code: \"INTERNAL_ERROR\",\n timestamp: new Date().toISOString(),\n});\n","import { inputFileSchema } from \"@uploadista/core/types\";\nimport { UploadServer } from \"@uploadista/core/upload\";\nimport { isSupportedAlgorithm } from \"@uploadista/core/utils\";\nimport { MetricsService } from \"@uploadista/observability\";\nimport { Effect } from \"effect\";\nimport { AuthCacheService } from \"../../cache\";\nimport { ValidationError } from \"../../error-types\";\nimport { AuthContextService } from \"../../service\";\nimport type {\n CreateUploadRequest,\n CreateUploadResponse,\n GetCapabilitiesRequest,\n GetCapabilitiesResponse,\n GetUploadRequest,\n GetUploadResponse,\n UploadChunkRequest,\n UploadChunkResponse,\n} from \"../routes\";\n\nexport const handleCreateUpload = (req: CreateUploadRequest) =>\n Effect.gen(function* () {\n const server = yield* UploadServer;\n // Access auth context if available\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n const clientId = yield* authService.getClientId();\n\n if (clientId) {\n yield* Effect.logInfo(`[Upload] Creating upload for client: ${clientId}`);\n }\n\n const parsedInputFile = yield* Effect.sync(() =>\n inputFileSchema.safeParse(req.data),\n );\n\n if (!parsedInputFile.success) {\n return yield* Effect.fail(\n new ValidationError(\"Invalid input file schema\"),\n );\n }\n\n // Validate checksum algorithm if provided\n if (\n parsedInputFile.data.checksumAlgorithm &&\n !isSupportedAlgorithm(parsedInputFile.data.checksumAlgorithm)\n ) {\n return yield* Effect.fail(\n new ValidationError(\n `Unsupported checksum algorithm: ${parsedInputFile.data.checksumAlgorithm}. Supported algorithms: sha256`,\n ),\n );\n }\n\n const fileCreated = yield* server.createUpload(\n parsedInputFile.data,\n clientId,\n );\n\n // Cache auth context for subsequent chunk uploads\n const authContext = yield* authService.getAuthContext();\n if (authContext) {\n yield* authCache.set(fileCreated.id, authContext);\n }\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Upload] Upload created: ${fileCreated.id} for client: ${clientId}`,\n );\n }\n\n return {\n status: 200,\n body: fileCreated,\n } as CreateUploadResponse;\n });\n\nexport const handleGetCapabilities = ({ storageId }: GetCapabilitiesRequest) =>\n Effect.gen(function* () {\n const server = yield* UploadServer;\n const authService = yield* AuthContextService;\n const clientId = yield* authService.getClientId();\n\n const capabilities = yield* server.getCapabilities(storageId, clientId);\n\n return {\n status: 200,\n body: {\n storageId,\n capabilities,\n timestamp: new Date().toISOString(),\n },\n } as GetCapabilitiesResponse;\n });\n\nexport const handleGetUpload = ({ uploadId }: GetUploadRequest) =>\n Effect.gen(function* () {\n const server = yield* UploadServer;\n const fileResult = yield* server.getUpload(uploadId);\n\n return {\n status: 200,\n body: fileResult,\n } as GetUploadResponse;\n });\n\nexport const handleUploadChunk = (req: UploadChunkRequest) =>\n Effect.gen(function* () {\n const server = yield* UploadServer;\n // Try to get auth from current request or cached auth\n const authService = yield* AuthContextService;\n const authCache = yield* AuthCacheService;\n const metricsService = yield* MetricsService;\n\n const { uploadId, data } = req;\n\n // Try current auth first, fallback to cached auth\n let clientId = yield* authService.getClientId();\n let authMetadata = yield* authService.getMetadata();\n if (!clientId) {\n const cachedAuth = yield* authCache.get(uploadId);\n clientId = cachedAuth?.clientId ?? null;\n authMetadata = cachedAuth?.metadata ?? {};\n }\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Upload] Uploading chunk for upload: ${uploadId}, client: ${clientId}`,\n );\n }\n\n const fileResult = yield* server.uploadChunk(uploadId, clientId, data);\n\n // Clear cache and record metrics if upload is complete\n if (fileResult.size && fileResult.offset >= fileResult.size) {\n yield* authCache.delete(uploadId);\n if (clientId) {\n yield* Effect.logInfo(\n `[Upload] Upload completed, cleared auth cache: ${uploadId}`,\n );\n }\n\n // Record upload metrics if we have organization ID\n\n if (clientId && fileResult.size) {\n yield* Effect.logInfo(\n `[Upload] Recording metrics for org: ${clientId}, size: ${fileResult.size}`,\n );\n yield* Effect.forkDaemon(\n metricsService.recordUpload(clientId, fileResult.size, authMetadata),\n );\n } else {\n yield* Effect.logWarning(\n `[Upload] Cannot record metrics - missing organizationId or size`,\n );\n }\n }\n\n if (clientId) {\n yield* Effect.logInfo(\n `[Upload] Chunk uploaded for upload: ${uploadId}, client: ${clientId}`,\n );\n }\n\n return {\n status: 200,\n body: fileResult,\n } as UploadChunkResponse;\n });\n","import { Effect } from \"effect\";\nimport type { UploadistaRequest, UploadistaResponse } from \"../routes\";\nimport {\n handleCancelFlow,\n handleGetFlow,\n handleJobStatus,\n handlePauseFlow,\n handleResumeFlow,\n handleRunFlow,\n} from \"./flow-http-handlers\";\nimport {\n handleCreateUpload,\n handleGetCapabilities,\n handleGetUpload,\n handleUploadChunk,\n} from \"./upload-http-handlers\";\n\nexport type { UploadistaRequest, UploadistaResponse } from \"../routes\";\n\nexport const handleUploadistaRequest = <TRequirements>(\n req: UploadistaRequest,\n) => {\n return Effect.gen(function* () {\n switch (req.type) {\n case \"create-upload\":\n return (yield* handleCreateUpload(req)) as UploadistaResponse;\n case \"get-capabilities\":\n return (yield* handleGetCapabilities(req)) as UploadistaResponse;\n case \"get-upload\":\n return (yield* handleGetUpload(req)) as UploadistaResponse;\n case \"upload-chunk\":\n return (yield* handleUploadChunk(req)) as UploadistaResponse;\n case \"get-flow\":\n return (yield* handleGetFlow(req)) as UploadistaResponse;\n case \"run-flow\":\n return (yield* handleRunFlow<TRequirements>(req)) as UploadistaResponse;\n case \"job-status\":\n return (yield* handleJobStatus(req)) as UploadistaResponse;\n case \"resume-flow\":\n return (yield* handleResumeFlow<TRequirements>(\n req,\n )) as UploadistaResponse;\n case \"pause-flow\":\n return (yield* handlePauseFlow(req)) as UploadistaResponse;\n case \"cancel-flow\":\n return (yield* handleCancelFlow(req)) as UploadistaResponse;\n case \"not-found\":\n return {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n body: { error: \"Not found\" },\n } as UploadistaResponse;\n case \"bad-request\":\n return {\n status: 400,\n body: { error: \"Bad request\", message: req.message },\n } as UploadistaResponse;\n case \"method-not-allowed\":\n return {\n status: 405,\n headers: { \"Content-Type\": \"application/json\" },\n body: { error: \"Method not allowed\" },\n } as UploadistaResponse;\n case \"unsupported-content-type\":\n return {\n status: 415,\n headers: { \"Content-Type\": \"application/json\" },\n body: { error: \"Unsupported content type\" },\n } as UploadistaResponse;\n }\n });\n};\n","import type { UploadistaError } from \"@uploadista/core\";\nimport { type Flow, FlowProvider, FlowWaitUntil } from \"@uploadista/core/flow\";\nimport {\n createDataStoreLayer,\n type UploadFileDataStores,\n type UploadFileKVStore,\n} from \"@uploadista/core/types\";\nimport { GenerateIdLive } from \"@uploadista/core/utils\";\nimport { memoryEventBroadcaster } from \"@uploadista/event-broadcaster-memory\";\nimport { webSocketEventEmitter } from \"@uploadista/event-emitter-websocket\";\nimport { NodeSdkLive, NoOpMetricsServiceLive } from \"@uploadista/observability\";\nimport { Effect, Layer, ManagedRuntime } from \"effect\";\nimport type { z } from \"zod\";\nimport type { StandardResponse } from \"../adapter\";\nimport { AuthCacheServiceLive } from \"../cache\";\nimport { handleFlowError } from \"../http-utils\";\nimport { createFlowServerLayer, createUploadServerLayer } from \"../layer-utils\";\nimport { AuthContextServiceLive } from \"../service\";\nimport type { AuthContext } from \"../types\";\nimport { handleUploadistaRequest } from \"./http-handlers/http-handlers\";\nimport type { NotFoundResponse } from \"./routes\";\nimport type { UploadistaServer, UploadistaServerConfig } from \"./types\";\n\n/**\n * Creates the unified Uploadista server with framework-specific adapter.\n *\n * This function composes all layers (upload server, flow server, auth, metrics)\n * and returns a handler that works with any framework via the provided adapter.\n *\n * The core server handles:\n * - Route parsing and matching\n * - Auth middleware execution with timeout protection\n * - Layer composition (upload/flow servers, auth cache, metrics)\n * - Error handling and response formatting\n * - Effect program execution with optional tracing\n *\n * @param config - Server configuration including adapter and business logic\n * @returns Object with handler function, optional WebSocket handler, and base URL\n *\n * @example\n * ```typescript\n * import { createUploadistaServer, honoAdapter } from \"@uploadista/server\";\n *\n * const server = await createUploadistaServer({\n * flows: getFlowById,\n * dataStore: { type: \"s3\", config: { bucket: \"uploads\" } },\n * kvStore: redisKvStore,\n * adapter: honoAdapter({\n * authMiddleware: async (c) => ({ clientId: \"user-123\" })\n * })\n * });\n *\n * // Use with Hono\n * app.all(\"/uploadista/*\", server.handler);\n * ```\n */\nexport const createUploadistaServer = async <\n TContext,\n TResponse,\n TWebSocketHandler = unknown,\n>({\n flows,\n dataStore,\n kvStore,\n plugins = [],\n eventEmitter,\n eventBroadcaster = memoryEventBroadcaster,\n withTracing = false,\n baseUrl: configBaseUrl = \"uploadista\",\n generateId = GenerateIdLive,\n metricsLayer,\n bufferedDataStore,\n adapter,\n authCacheConfig,\n}: UploadistaServerConfig<TContext, TResponse, TWebSocketHandler>): Promise<\n UploadistaServer<TContext, TResponse, TWebSocketHandler>\n> => {\n // Default eventEmitter to webSocketEventEmitter with the provided eventBroadcaster\n const finalEventEmitter =\n eventEmitter ?? webSocketEventEmitter(eventBroadcaster);\n\n // Normalize baseUrl (remove trailing slash)\n const baseUrl = configBaseUrl.endsWith(\"/\")\n ? configBaseUrl.slice(0, -1)\n : configBaseUrl;\n\n // Create flow provider layer from flows function\n const flowProviderLayer = Layer.effect(\n FlowProvider,\n Effect.succeed({\n getFlow: (flowId: string, clientId: string | null) => {\n // Cast the flows function to match FlowProvider expectations\n // The context requirements will be provided at the layer level\n return flows(flowId, clientId) as Effect.Effect<\n Flow<z.ZodSchema<unknown>, z.ZodSchema<unknown>, unknown>,\n UploadistaError,\n never\n >;\n },\n }),\n );\n\n // Validate that eventEmitter is provided (required for upload/flow servers)\n if (!finalEventEmitter) {\n throw new Error(\n \"eventEmitter is required. Provide an event emitter layer in the configuration.\",\n );\n }\n\n // Create data store layer\n const dataStoreLayer: Layer.Layer<\n UploadFileDataStores,\n never,\n UploadFileKVStore\n > = await createDataStoreLayer(dataStore);\n\n // Create upload server layer\n const uploadServerLayer = createUploadServerLayer({\n kvStore,\n eventEmitter: finalEventEmitter,\n dataStore: dataStoreLayer,\n bufferedDataStore,\n generateId,\n });\n\n // Create flow server layer\n const flowServerLayer = createFlowServerLayer({\n kvStore,\n eventEmitter: finalEventEmitter,\n flowProvider: flowProviderLayer,\n uploadServer: uploadServerLayer,\n });\n\n // Create auth cache layer (always present, even if auth is not enabled)\n const authCacheLayer = AuthCacheServiceLive(authCacheConfig);\n\n // Metrics layer (defaults to NoOp if not provided)\n const effectiveMetricsLayer = metricsLayer ?? NoOpMetricsServiceLive;\n\n const serverLayer = Layer.mergeAll(\n uploadServerLayer,\n flowServerLayer,\n effectiveMetricsLayer,\n authCacheLayer,\n ...plugins,\n );\n\n // Create a shared managed runtime from the server layer\n // This ensures all requests use the same layer instances (including event broadcaster)\n // ManagedRuntime properly handles scoped resources and provides convenient run methods\n const managedRuntime = ManagedRuntime.make(serverLayer);\n\n /**\n * Main request handler that processes HTTP requests through the adapter.\n * Delegates to adapter's httpHandler if provided, otherwise uses standard flow.\n */\n const handler = async <TRequirements>(ctx: TContext) => {\n // Fallback: Standard routing logic (for adapters without httpHandler)\n const program = Effect.gen(function* () {\n // Extract standard request from framework-specific request\n const uploadistaRequest = yield* adapter.extractRequest(ctx, { baseUrl });\n\n // Run auth middleware if provided\n let authContext: AuthContext | null = null;\n if (adapter.runAuthMiddleware) {\n const authMiddlewareWithTimeout = adapter.runAuthMiddleware(ctx).pipe(\n Effect.timeout(\"5 seconds\"),\n Effect.catchAll(() => {\n // Timeout error\n console.error(\"Auth middleware timeout exceeded (5 seconds)\");\n return Effect.succeed({\n _tag: \"TimeoutError\" as const,\n } as const);\n }),\n Effect.catchAllCause((cause) => {\n // Other errors\n console.error(\"Auth middleware error:\", cause);\n return Effect.succeed({\n _tag: \"AuthError\" as const,\n error: cause,\n } as const);\n }),\n );\n\n const authResult:\n | AuthContext\n | null\n | { _tag: \"TimeoutError\" }\n | { _tag: \"AuthError\"; error: unknown } =\n yield* authMiddlewareWithTimeout;\n\n // Handle timeout\n if (\n authResult &&\n typeof authResult === \"object\" &&\n \"_tag\" in authResult &&\n authResult._tag === \"TimeoutError\"\n ) {\n const errorResponse: StandardResponse = {\n status: 503,\n headers: { \"Content-Type\": \"application/json\" },\n body: {\n error: \"Authentication service unavailable\",\n message:\n \"Authentication took too long to respond. Please try again.\",\n },\n };\n return yield* adapter.sendResponse(errorResponse, ctx);\n }\n\n // Handle auth error\n if (\n authResult &&\n typeof authResult === \"object\" &&\n \"_tag\" in authResult &&\n authResult._tag === \"AuthError\"\n ) {\n const errorResponse: StandardResponse = {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n body: {\n error: \"Internal Server Error\",\n message: \"An error occurred during authentication\",\n },\n };\n return yield* adapter.sendResponse(errorResponse, ctx);\n }\n\n // Handle authentication failure (null result)\n if (authResult === null) {\n const errorResponse: StandardResponse = {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n body: {\n error: \"Unauthorized\",\n message: \"Invalid credentials\",\n },\n };\n return yield* adapter.sendResponse(errorResponse, ctx);\n }\n\n authContext = authResult;\n }\n\n // Create auth context layer for this request\n const authContextLayer = AuthContextServiceLive(authContext);\n\n // Extract waitUntil callback if available (for Cloudflare Workers)\n // This must be extracted per-request since it comes from the framework context\n const waitUntilLayers: Layer.Layer<any, never, never>[] = [];\n if (adapter.extractWaitUntil) {\n const waitUntilCallback = adapter.extractWaitUntil(ctx);\n if (waitUntilCallback) {\n waitUntilLayers.push(Layer.succeed(FlowWaitUntil, waitUntilCallback));\n }\n }\n\n // Combine auth context, auth cache, metrics layers, plugins, and waitUntil\n // This ensures that flow nodes have access to all required services\n const requestContextLayer = Layer.mergeAll(\n authContextLayer,\n authCacheLayer,\n effectiveMetricsLayer,\n ...plugins,\n ...waitUntilLayers,\n );\n\n // Check for baseUrl/api/ prefix\n if (uploadistaRequest.type === \"not-found\") {\n const notFoundResponse: NotFoundResponse = {\n type: \"not-found\",\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n body: { error: \"Not found\" },\n };\n return yield* adapter.sendResponse(notFoundResponse, ctx);\n }\n\n // Handle the request\n const response = yield* handleUploadistaRequest<TRequirements>(\n uploadistaRequest,\n ).pipe(Effect.provide(requestContextLayer));\n\n return yield* adapter.sendResponse(response, ctx);\n }).pipe(\n // Catch all errors and format them appropriately\n Effect.catchAll((error: unknown) => {\n const errorInfo = handleFlowError(error);\n const errorBody: Record<string, unknown> = {\n code: errorInfo.code,\n message: errorInfo.message,\n };\n if (errorInfo.details !== undefined) {\n errorBody.details = errorInfo.details;\n }\n const errorResponse: StandardResponse = {\n status: errorInfo.status,\n headers: { \"Content-Type\": \"application/json\" },\n body: errorBody,\n };\n return adapter.sendResponse(errorResponse, ctx);\n }),\n );\n\n // Use the shared managed runtime instead of creating a new one per request\n if (withTracing) {\n return managedRuntime.runPromise(\n program.pipe(Effect.provide(NodeSdkLive)),\n );\n }\n return managedRuntime.runPromise(program);\n };\n\n // Create WebSocket handler using the shared managed runtime\n const websocketHandler = await managedRuntime.runPromise(\n adapter.webSocketHandler({\n baseUrl,\n }),\n );\n\n return {\n handler,\n websocketHandler,\n baseUrl,\n dispose: () => managedRuntime.dispose(),\n };\n};\n","import type { FlowServerShape } from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\nimport type { WebSocketConnection } from \"../websocket-routes\";\n\n/**\n * Handles subscription to flow events\n * Subscribes the WebSocket connection to receive real-time flow execution events\n */\nexport const handleSubscribeToFlowEvents = (\n flowServer: FlowServerShape,\n jobId: string | undefined,\n connection: WebSocketConnection,\n) => {\n return Effect.gen(function* () {\n if (!jobId) {\n yield* Effect.sync(() => {\n connection.send(\n JSON.stringify({\n type: \"error\",\n message: \"Job ID is required for flow event subscription\",\n code: \"MISSING_JOB_ID\",\n }),\n );\n });\n return;\n }\n\n yield* flowServer.subscribeToFlowEvents(jobId, connection);\n });\n};\n\n/**\n * Handles unsubscription from flow events\n * Removes the WebSocket connection from receiving flow events\n */\nexport const handleUnsubscribeFromFlowEvents = (\n flowServer: FlowServerShape,\n jobId: string | undefined,\n) => {\n return Effect.gen(function* () {\n if (!jobId) {\n return;\n }\n\n yield* flowServer.unsubscribeFromFlowEvents(jobId);\n });\n};\n","import type { UploadServerShape } from \"@uploadista/core/upload\";\nimport { Effect } from \"effect\";\nimport type { WebSocketConnection } from \"../websocket-routes\";\n\n/**\n * Handles subscription to upload events\n * Subscribes the WebSocket connection to receive real-time upload progress events\n */\nexport const handleSubscribeToUploadEvents = (\n uploadServer: UploadServerShape,\n uploadId: string | undefined,\n connection: WebSocketConnection,\n) => {\n return Effect.gen(function* () {\n if (!uploadId) {\n yield* Effect.sync(() => {\n connection.send(\n JSON.stringify({\n type: \"error\",\n message: \"Upload ID is required for upload event subscription\",\n code: \"MISSING_UPLOAD_ID\",\n }),\n );\n });\n return;\n }\n\n yield* uploadServer.subscribeToUploadEvents(uploadId, connection);\n });\n};\n\n/**\n * Handles unsubscription from upload events\n * Removes the WebSocket connection from receiving upload events\n */\nexport const handleUnsubscribeFromUploadEvents = (\n uploadServer: UploadServerShape,\n uploadId: string | undefined,\n) => {\n return Effect.gen(function* () {\n if (!uploadId) {\n return;\n }\n\n yield* uploadServer.unsubscribeFromUploadEvents(uploadId);\n });\n};\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport type { FlowServerShape } from \"@uploadista/core/flow\";\nimport type { UploadServerShape } from \"@uploadista/core/upload\";\nimport { Effect } from \"effect\";\nimport type {\n WebSocketConnection,\n WebSocketConnectionRequest,\n} from \"../websocket-routes\";\nimport {\n handleSubscribeToFlowEvents,\n handleUnsubscribeFromFlowEvents,\n} from \"./flow-websocket-handlers\";\nimport {\n handleSubscribeToUploadEvents,\n handleUnsubscribeFromUploadEvents,\n} from \"./upload-websocket-handlers\";\n\nexport type {\n WebSocketConnection,\n WebSocketConnectionRequest,\n} from \"../websocket-routes\";\n\n/**\n * Handles WebSocket connection opening\n * Subscribes to the appropriate events based on the connection request\n */\nexport const handleWebSocketOpen = (\n request: WebSocketConnectionRequest,\n uploadServer: UploadServerShape,\n flowServer: FlowServerShape,\n) => {\n const { connection, isFlowRoute, isUploadRoute, jobId, uploadId, eventId } =\n request;\n\n return Effect.gen(function* () {\n // Subscribe to flow events if this is a flow route\n if (isFlowRoute) {\n yield* handleSubscribeToFlowEvents(flowServer, jobId, connection);\n }\n\n // Subscribe to upload events if this is an upload route\n if (isUploadRoute) {\n yield* handleSubscribeToUploadEvents(uploadServer, uploadId, connection);\n }\n\n // Send connection confirmation\n connection.send(\n JSON.stringify({\n type: \"connection\",\n message: \"Uploadista WebSocket connected\",\n id: eventId,\n jobId,\n uploadId,\n timestamp: new Date().toISOString(),\n }),\n );\n }).pipe(\n Effect.catchAll((error) =>\n Effect.sync(() => {\n console.error(\"Error subscribing to events:\", error);\n const errorMessage =\n error instanceof UploadistaError\n ? error.body\n : \"Failed to subscribe to events\";\n connection.send(\n JSON.stringify({\n type: \"error\",\n message: errorMessage,\n code:\n error instanceof UploadistaError\n ? error.code\n : \"SUBSCRIPTION_ERROR\",\n }),\n );\n }),\n ),\n );\n};\n\n/**\n * Handles incoming WebSocket messages\n * Currently supports ping/pong for connection keep-alive\n */\nexport const handleWebSocketMessage = (\n message: string,\n connection: WebSocketConnection,\n) => {\n return Effect.sync(() => {\n try {\n const parsed = JSON.parse(message);\n if (parsed.type === \"ping\") {\n connection.send(\n JSON.stringify({\n type: \"pong\",\n timestamp: new Date().toISOString(),\n }),\n );\n }\n } catch (error) {\n console.error(\"Error handling WebSocket message:\", error);\n connection.send(\n JSON.stringify({\n type: \"error\",\n message: \"Invalid message format\",\n }),\n );\n }\n });\n};\n\n/**\n * Handles WebSocket connection closing\n * Unsubscribes from all events and cleans up resources\n */\nexport const handleWebSocketClose = (\n request: WebSocketConnectionRequest,\n uploadServer: UploadServerShape,\n flowServer: FlowServerShape,\n) => {\n const { isFlowRoute, isUploadRoute, jobId, uploadId } = request;\n\n return Effect.gen(function* () {\n // Unsubscribe from flow events if this was a flow route\n if (isFlowRoute) {\n yield* handleUnsubscribeFromFlowEvents(flowServer, jobId);\n }\n\n // Unsubscribe from upload events if this was an upload route\n if (isUploadRoute) {\n yield* handleUnsubscribeFromUploadEvents(uploadServer, uploadId);\n }\n }).pipe(\n Effect.catchAll((error) =>\n Effect.sync(() => {\n console.error(\n \"Error unsubscribing from events:\",\n error instanceof UploadistaError ? error.body : error,\n );\n }),\n ),\n );\n};\n\n/**\n * Handles WebSocket errors\n */\nexport const handleWebSocketError = (error: unknown, eventId?: string) => {\n return Effect.sync(() => {\n console.error(`WebSocket error for event ${eventId}:`, error);\n });\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/server",
3
3
  "type": "module",
4
- "version": "0.0.7",
4
+ "version": "0.0.9",
5
5
  "description": "Core Server package for Uploadista",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -18,18 +18,21 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
- "effect": "3.18.4",
21
+ "effect": "3.19.0",
22
22
  "zod": "4.1.12",
23
- "@uploadista/core": "0.0.7"
23
+ "@uploadista/observability": "0.0.9",
24
+ "@uploadista/core": "0.0.9",
25
+ "@uploadista/event-emitter-websocket": "0.0.9",
26
+ "@uploadista/event-broadcaster-memory": "0.0.9"
24
27
  },
25
28
  "devDependencies": {
26
29
  "@cloudflare/workers-types": "4.20251014.0",
27
30
  "@types/express": "^5.0.0",
28
- "@types/node": "24.9.1",
29
- "tsdown": "0.15.9",
31
+ "@types/node": "24.10.0",
32
+ "tsdown": "0.16.0",
30
33
  "typescript": "5.9.3",
31
- "vitest": "3.2.4",
32
- "@uploadista/typescript-config": "0.0.7"
34
+ "vitest": "4.0.7",
35
+ "@uploadista/typescript-config": "0.0.9"
33
36
  },
34
37
  "peerDependencies": {
35
38
  "express": "^4.0.0 || ^5.0.0",
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adapter module for framework-agnostic server implementation.
3
+ *
4
+ * This module defines the ServerAdapter interface that allows the core
5
+ * Uploadista server to work with any HTTP framework (Hono, Express, Fastify, etc.)
6
+ * by providing a thin translation layer between framework-specific types
7
+ * and standard request/response representations.
8
+ */
9
+
10
+ export * from "./types";
@@ -0,0 +1,229 @@
1
+ import type { FlowServer, UploadServer } from "@uploadista/core";
2
+ import type { Effect } from "effect";
3
+ import type { UploadistaRequest, UploadistaResponse } from "../core/routes";
4
+ import type { AuthResult } from "../types";
5
+
6
+ /**
7
+ * Standard request representation extracted from framework-specific request objects.
8
+ *
9
+ * This interface provides a framework-agnostic way to represent HTTP requests,
10
+ * allowing the core server logic to work uniformly across Hono, Express, Fastify,
11
+ * and other frameworks.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const standardRequest: StandardRequest = {
16
+ * method: "POST",
17
+ * url: new URL("https://example.com/uploadista/api/upload"),
18
+ * headers: { "content-type": "application/json" },
19
+ * body: { file: "data" }
20
+ * };
21
+ * ```
22
+ */
23
+ export interface StandardRequest {
24
+ /**
25
+ * HTTP method (GET, POST, PATCH, etc.)
26
+ */
27
+ method: string;
28
+
29
+ /**
30
+ * Full URL of the request including protocol, host, path, and query parameters
31
+ */
32
+ url: URL;
33
+
34
+ /**
35
+ * Request headers as key-value pairs
36
+ */
37
+ headers: Record<string, string>;
38
+
39
+ /**
40
+ * Optional request body (parsed or raw)
41
+ */
42
+ body?: unknown;
43
+ }
44
+
45
+ /**
46
+ * Standard response representation to be sent by framework-specific adapters.
47
+ *
48
+ * The core server produces StandardResponse objects, which adapters then
49
+ * translate into framework-specific response formats.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const standardResponse: StandardResponse = {
54
+ * status: 200,
55
+ * headers: { "content-type": "application/json" },
56
+ * body: { uploadId: "abc123" }
57
+ * };
58
+ * ```
59
+ */
60
+ export interface StandardResponse {
61
+ /**
62
+ * HTTP status code (200, 404, 500, etc.)
63
+ */
64
+ status: number;
65
+
66
+ /**
67
+ * Optional response headers as key-value pairs
68
+ */
69
+ headers?: Record<string, string>;
70
+
71
+ /**
72
+ * Optional response body (will be JSON-stringified if object)
73
+ */
74
+ body?: unknown;
75
+ }
76
+
77
+ /**
78
+ * WebSocket handler interface for framework-agnostic WebSocket management.
79
+ *
80
+ * This interface allows the core server to interact with WebSocket connections
81
+ * without needing to know about framework-specific WebSocket APIs.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const wsHandler: WebSocketHandler = {
86
+ * onMessage: (message) => console.log("Received:", message),
87
+ * onClose: () => console.log("Connection closed"),
88
+ * onError: (error) => console.error("WebSocket error:", error)
89
+ * };
90
+ * ```
91
+ */
92
+ export interface WebSocketHandler {
93
+ /**
94
+ * Callback invoked when a message is received from the client
95
+ *
96
+ * @param message - The message string received
97
+ */
98
+ onMessage: (message: string) => void;
99
+
100
+ /**
101
+ * Callback invoked when the WebSocket connection is closed
102
+ */
103
+ onClose: () => void;
104
+
105
+ /**
106
+ * Callback invoked when a WebSocket error occurs
107
+ *
108
+ * @param error - The error that occurred
109
+ */
110
+ onError: (error: Error) => void;
111
+ }
112
+
113
+ /**
114
+ * ServerAdapter interface that framework adapters must implement.
115
+ *
116
+ * This interface defines the contract between the core server (framework-agnostic)
117
+ * and framework-specific adapters (Hono, Express, Fastify, etc.).
118
+ *
119
+ * Each adapter translates between framework-specific request/response types
120
+ * and the standard types used by the core server.
121
+ *
122
+ * @template TRequest - Framework-specific request type (e.g., Context for Hono, Request for Express)
123
+ * @template TResponse - Framework-specific response type (e.g., Context for Hono, Response for Express)
124
+ * @template TWebSocket - Framework-specific WebSocket type (optional, defaults to unknown)
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // Hono adapter example
129
+ * const honoAdapter: ServerAdapter<Context, Context, WSEvents> = {
130
+ * extractRequest: (c) => Effect.succeed({
131
+ * method: c.req.raw.method,
132
+ * url: new URL(c.req.raw.url),
133
+ * headers: Object.fromEntries(c.req.raw.headers.entries()),
134
+ * body: c.req.raw.body
135
+ * }),
136
+ * sendResponse: (c, response) => Effect.sync(() =>
137
+ * new Response(JSON.stringify(response.body), {
138
+ * status: response.status,
139
+ * headers: response.headers
140
+ * })
141
+ * ),
142
+ * runAuthMiddleware: (c) => Effect.tryPromise(() => authMiddleware(c)),
143
+ * createWebSocketHandler: (ws) => ({ ... })
144
+ * };
145
+ * ```
146
+ */
147
+ export interface ServerAdapter<
148
+ TContext,
149
+ TResponse,
150
+ TWebSocketHandler = unknown,
151
+ > {
152
+ /**
153
+ * Extract standard request details from framework-specific request.
154
+ *
155
+ * This method converts the framework's native request object into a
156
+ * UploadistaRequest that the core server can process uniformly.
157
+ *
158
+ * @param req - Framework-specific request object
159
+ * @returns Effect that produces UploadistaRequest on success
160
+ */
161
+ extractRequest(
162
+ req: TContext,
163
+ { baseUrl }: { baseUrl: string },
164
+ ): Effect.Effect<UploadistaRequest, never, never>;
165
+
166
+ /**
167
+ * Send standard response using framework-specific response object.
168
+ *
169
+ * This method converts a UploadistaResponse from the core server into
170
+ * the format required by the framework (e.g., Web API Response, Express res.json()).
171
+ *
172
+ * @param response - Standard response to send
173
+ * @returns Effect that completes when response is sent
174
+ */
175
+ sendResponse(
176
+ response: UploadistaResponse,
177
+ context: TContext,
178
+ ): Effect.Effect<TResponse, never, never>;
179
+
180
+ /**
181
+ * Optional: Run framework-specific auth middleware.
182
+ *
183
+ * If provided, this method is called before each request is processed.
184
+ * It should execute the framework's authentication middleware and return
185
+ * an AuthResult (AuthContext on success, null on failure).
186
+ *
187
+ * If not provided, the adapter assumes no authentication is required.
188
+ *
189
+ * @param ctx - Framework-specific context object
190
+ * @param res - Framework-specific response object
191
+ * @returns Effect that produces AuthResult (AuthContext or null)
192
+ */
193
+ runAuthMiddleware?(ctx: TContext): Effect.Effect<AuthResult, never, never>;
194
+
195
+ /**
196
+ * Optional: Create WebSocket handler for real-time updates.
197
+ *
198
+ * Only needed if the framework supports WebSocket connections for
199
+ * real-time upload progress and flow status updates.
200
+ *
201
+ * @param ws - Framework-specific WebSocket object
202
+ * @param ctx - Framework-specific context object (for initial handshake)
203
+ * @param context - Server context with baseUrl, uploadServer, and flowServer
204
+ * @returns WebSocketHandler with callbacks for message, close, and error events
205
+ */
206
+ webSocketHandler(context: {
207
+ baseUrl: string;
208
+ }): Effect.Effect<TWebSocketHandler, never, UploadServer | FlowServer>;
209
+
210
+ /**
211
+ * Optional: Extract waitUntil callback from the framework context.
212
+ *
213
+ * When provided, allows flows to execute beyond the HTTP response lifecycle.
214
+ * This function is called per-request to extract the waitUntil callback from
215
+ * the framework-specific context.
216
+ *
217
+ * @param ctx - Framework-specific context object
218
+ * @returns The waitUntil callback or undefined if not available
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Cloudflare Workers with Hono:
223
+ * extractWaitUntil: (c) => c.executionCtx.waitUntil.bind(c.executionCtx)
224
+ * ```
225
+ */
226
+ extractWaitUntil?: (
227
+ ctx: TContext,
228
+ ) => ((promise: Promise<unknown>) => void) | undefined;
229
+ }