@uploadista/server 0.0.20-beta.6 → 0.0.20-beta.8
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/README.md +16 -16
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +188 -188
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +188 -188
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/adapter/types.ts +3 -3
- package/src/core/http-handlers/flow-http-handlers.ts +14 -14
- package/src/core/http-handlers/upload-http-handlers.ts +16 -9
- package/src/core/plugin-types.ts +10 -10
- package/src/core/routes.ts +4 -1
- package/src/core/server.ts +7 -9
- package/src/core/websocket-handlers/flow-websocket-handlers.ts +5 -5
- package/src/core/websocket-handlers/upload-websocket-handlers.ts +5 -5
- package/src/core/websocket-handlers/websocket-handlers.ts +10 -10
- package/src/error-types.ts +1 -1
- package/src/layer-utils.ts +24 -24
- package/src/permissions/errors.ts +3 -1
- package/src/permissions/index.ts +2 -2
- package/src/permissions/types.ts +3 -12
- package/src/plugins-typing.ts +15 -13
- package/src/service.ts +9 -4
- package/src/usage-hooks/index.ts +1 -1
- package/src/usage-hooks/service.ts +51 -59
- package/src/usage-hooks/types.ts +2 -4
package/README.md
CHANGED
|
@@ -77,13 +77,13 @@ if (response.isValid) {
|
|
|
77
77
|
### 3. Create Upload Server Layer
|
|
78
78
|
|
|
79
79
|
```typescript
|
|
80
|
-
import {
|
|
80
|
+
import { createUploadEngineLayer } from "@uploadista/server";
|
|
81
81
|
import { redisKvStore } from "@uploadista/kv-store-redis";
|
|
82
82
|
import { s3DataStore } from "@uploadista/data-store-s3";
|
|
83
83
|
import { webSocketEventEmitter } from "@uploadista/event-emitter-websocket";
|
|
84
84
|
import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
|
|
85
85
|
|
|
86
|
-
const
|
|
86
|
+
const uploadEngineLayer = createUploadEngineLayer({
|
|
87
87
|
kvStore: redisKvStore,
|
|
88
88
|
eventEmitter: webSocketEventEmitter,
|
|
89
89
|
dataStore: s3DataStore,
|
|
@@ -239,12 +239,12 @@ const cacheLayer = AuthCacheServiceLive({
|
|
|
239
239
|
|
|
240
240
|
### Layer Composition
|
|
241
241
|
|
|
242
|
-
#### `
|
|
242
|
+
#### `UploadEngineLayerConfig`
|
|
243
243
|
|
|
244
244
|
Configuration for creating upload server layer.
|
|
245
245
|
|
|
246
246
|
```typescript
|
|
247
|
-
interface
|
|
247
|
+
interface UploadEngineLayerConfig {
|
|
248
248
|
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
249
249
|
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
250
250
|
dataStore: Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
|
|
@@ -255,43 +255,43 @@ interface UploadServerLayerConfig {
|
|
|
255
255
|
|
|
256
256
|
#### `createUploadServerLayer(config)`
|
|
257
257
|
|
|
258
|
-
Compose upload
|
|
258
|
+
Compose upload engine with all dependencies.
|
|
259
259
|
|
|
260
260
|
```typescript
|
|
261
|
-
import {
|
|
261
|
+
import { createUploadEngineLayer } from "@uploadista/server";
|
|
262
262
|
|
|
263
|
-
const
|
|
263
|
+
const uploadEngineLayer = createUploadEngineLayer({
|
|
264
264
|
kvStore: redisKvStore,
|
|
265
265
|
eventEmitter: webSocketEventEmitter,
|
|
266
266
|
dataStore: s3DataStore,
|
|
267
267
|
});
|
|
268
268
|
```
|
|
269
269
|
|
|
270
|
-
#### `
|
|
270
|
+
#### `FlowEngineLayerConfig`
|
|
271
271
|
|
|
272
|
-
Configuration for creating flow
|
|
272
|
+
Configuration for creating flow engine layer.
|
|
273
273
|
|
|
274
274
|
```typescript
|
|
275
|
-
interface
|
|
275
|
+
interface FlowEngineLayerConfig {
|
|
276
276
|
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
277
277
|
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
278
278
|
flowProvider: Layer.Layer<FlowProvider>;
|
|
279
|
-
|
|
279
|
+
uploadEngine: Layer.Layer<UploadEngine>;
|
|
280
280
|
}
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
-
#### `
|
|
283
|
+
#### `createFlowEngineLayer(config)`
|
|
284
284
|
|
|
285
|
-
Compose flow
|
|
285
|
+
Compose flow engine with all dependencies.
|
|
286
286
|
|
|
287
287
|
```typescript
|
|
288
|
-
import {
|
|
288
|
+
import { createFlowEngineLayer } from "@uploadista/server";
|
|
289
289
|
|
|
290
|
-
const flowLayer =
|
|
290
|
+
const flowLayer = createFlowEngineLayer({
|
|
291
291
|
kvStore: redisKvStore,
|
|
292
292
|
eventEmitter: webSocketEventEmitter,
|
|
293
293
|
flowProvider: createFlowsEffect,
|
|
294
|
-
|
|
294
|
+
uploadEngine: uploadEngineLayer,
|
|
295
295
|
});
|
|
296
296
|
```
|
|
297
297
|
|
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},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=
|
|
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.uploadEngine,f)},S=({kvStore:e,eventEmitter:i,flowProvider:a,uploadEngine: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.flowEngine,l)};var C=class extends Error{constructor(e,t=500,n=`INTERNAL_ERROR`){super(e),this.statusCode=t,this.errorCode=n,this.name=`AdapterError`}},w=class extends C{constructor(e){super(e,400,`VALIDATION_ERROR`),this.name=`ValidationError`}},T=class extends C{constructor(e){super(`${e} not found`,404,`NOT_FOUND`),this.name=`NotFoundError`}},E=class extends C{constructor(e){super(e,400,`BAD_REQUEST`),this.name=`BadRequestError`}};const D=e=>({error:e.message,code:e.errorCode,timestamp:new Date().toISOString()}),O=e=>{let t={error:e.body,code:e.code,timestamp:new Date().toISOString()};return e.details!==void 0&&(t.details=e.details),t},k=(e=`Internal server error`)=>({error:e,code:`INTERNAL_ERROR`,timestamp:new Date().toISOString()});var A=class extends C{requiredPermission;constructor(e,t){super(t??`Permission denied: ${e} required`,403,`PERMISSION_DENIED`),this.name=`AuthorizationError`,this.requiredPermission=e}},j=class extends C{constructor(e=`Authentication required`){super(e,401,`AUTHENTICATION_REQUIRED`),this.name=`AuthenticationRequiredError`}},M=class extends C{constructor(e=`Access denied: resource belongs to another organization`){super(e,403,`ORGANIZATION_MISMATCH`),this.name=`OrganizationMismatchError`}},N=class extends C{constructor(e=`Quota exceeded`,t=`QUOTA_EXCEEDED`){super(e,402,t),this.name=`QuotaExceededError`}};const P=e=>({error:e.message,code:e.errorCode,requiredPermission:e.requiredPermission,timestamp:new Date().toISOString()}),F={ALL:`engine:*`,HEALTH:`engine:health`,READINESS:`engine:readiness`,METRICS:`engine:metrics`,DLQ:`engine:dlq`,DLQ_READ:`engine:dlq:read`,DLQ_WRITE:`engine:dlq:write`},I={ALL:`flow:*`,EXECUTE:`flow:execute`,CANCEL:`flow:cancel`,STATUS:`flow:status`},L={ALL:`upload:*`,CREATE:`upload:create`,READ:`upload:read`,CANCEL:`upload:cancel`},R={ENGINE:F,FLOW:I,UPLOAD:L},z={ADMIN:[F.ALL],ORGANIZATION_OWNER:[I.ALL,L.ALL],ORGANIZATION_MEMBER:[I.ALL,L.ALL],API_KEY:[I.EXECUTE,L.CREATE]},B={[F.DLQ]:[F.DLQ_READ,F.DLQ_WRITE]},V=(e,t)=>{if(e===t)return!0;if(e.endsWith(`:*`)){let n=e.slice(0,-1);if(t.startsWith(n))return!0}return!!B[e]?.includes(t)},H=(e,t)=>e.some(e=>V(e,t)),U=(e,t)=>t.some(t=>H(e,t)),ee=(e,t)=>t.every(t=>H(e,t)),te=e=>{let t=[e],n=B[e];return n&&t.push(...n),t};var W=class extends t.Context.Tag(`AuthContextService`)(){};const G=(e,n)=>{let r=e?.permissions??[],i=n?.bypassAuth??!1;return t.Layer.succeed(W,{getClientId:()=>t.Effect.succeed(e?.clientId??null),getMetadata:()=>t.Effect.succeed(e?.metadata??{}),hasPermission:e=>i?t.Effect.succeed(!0):t.Effect.succeed(H(r,e)),hasAnyPermission:e=>i?t.Effect.succeed(!0):t.Effect.succeed(U(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 j);if(!H(r,n))return yield*t.Effect.logDebug(`[Auth] Permission denied: '${n}' for client '${e.clientId}'`),yield*t.Effect.fail(new A(n));yield*t.Effect.logDebug(`[Auth] Permission granted: '${n}' for client '${e.clientId}'`)}),requireAuthentication:()=>e?t.Effect.succeed(e):t.Effect.fail(new j),getPermissions:()=>t.Effect.succeed(r),getAuthContext:()=>t.Effect.succeed(e)})},ne=G(null),K=()=>({action:`continue`}),re=(e,t)=>({action:`abort`,reason:e,code:t}),q=5e3;var J=class extends t.Context.Tag(`UsageHookService`)(){};const Y=e=>{let n=e?.hooks,r=e?.timeout??q;return t.Layer.succeed(J,{onUploadStart:e=>n?.onUploadStart?n.onUploadStart(e).pipe(t.Effect.timeout(r),t.Effect.map(e=>e??K()),t.Effect.catchAll(e=>t.Effect.gen(function*(){return yield*t.Effect.logWarning(`onUploadStart hook failed: ${e}. Proceeding with upload.`),K()}))):t.Effect.succeed(K()),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??K()),t.Effect.catchAll(e=>t.Effect.gen(function*(){return yield*t.Effect.logWarning(`onFlowStart hook failed: ${e}. Proceeding with flow.`),K()}))):t.Effect.succeed(K()),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})},ie=Y(),ae=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.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}}),oe=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.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}}),se=e=>t.Effect.gen(function*(){return yield*(yield*W).requirePermission(R.ENGINE.DLQ_WRITE),yield*(yield*n.DeadLetterQueueService).markRetrying(e.itemId),{type:`dlq-retry`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),ce=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.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}}}),le=e=>t.Effect.gen(function*(){return yield*(yield*W).requirePermission(R.ENGINE.DLQ_WRITE),yield*(yield*n.DeadLetterQueueService).delete(e.itemId),{type:`dlq-delete`,status:200,headers:{"Content-Type":`application/json`},body:{success:!0}}}),ue=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.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}}),de=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.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}}),fe=e=>t.Effect.gen(function*(){yield*(yield*W).requirePermission(R.ENGINE.DLQ_READ);let e=yield*(yield*n.DeadLetterQueueService).getStats();return{type:`dlq-stats`,status:200,headers:{"Content-Type":`application/json`},body:e}}),pe=({flowId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowEngine,i=yield*W,a=yield*i.getClientId();return yield*i.requirePermission(R.FLOW.STATUS),a&&(yield*t.Effect.logInfo(`[Flow] Getting flow data: ${e}, client: ${a}`)),{status:200,body:yield*r.getFlowData(e,a)}}),me=({flowId:e,storageId:r,inputs:i})=>t.Effect.gen(function*(){let a=yield*n.FlowEngine,o=yield*W,s=yield*u,c=yield*J,l=yield*o.getClientId();if(yield*o.requirePermission(R.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 N(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}}),he=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowEngine,i=yield*W,a=yield*u,o=yield*i.getClientId();if(yield*i.requirePermission(R.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}}),ge=({jobId:e,nodeId:r,newData:i})=>t.Effect.gen(function*(){let a=yield*n.FlowEngine,o=yield*W,s=yield*u;yield*o.requirePermission(R.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}}),_e=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowEngine,i=yield*W,a=yield*u;yield*i.requirePermission(R.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}}),ve=({jobId:e})=>t.Effect.gen(function*(){let r=yield*n.FlowEngine,i=yield*W,a=yield*u,o=yield*J;if(yield*i.requirePermission(R.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}}),ye=Date.now();function X(){return Date.now()-ye}function Z(){return new Date().toISOString()}function be(e){return{status:`healthy`,timestamp:Z(),version:e?.version,uptime:X()}}function xe(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 Se(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Storage backend configured`,lastCheck:Z()})}function Ce(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`KV store configured`,lastCheck:Z()})}function we(e){let n=Date.now();return t.Effect.succeed({status:`healthy`,latency:Date.now()-n,message:`Event broadcaster configured`,lastCheck:Z()})}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*Se(n)),n.checkKvStore&&(t.kvStore=yield*Ce(n)),n.checkEventBroadcaster&&(t.eventBroadcaster=yield*we(n)),{status:xe(t),timestamp:Z(),version:e.version,uptime:X(),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*Se(n)),n.checkKvStore&&(t.kvStore=yield*Ce(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:xe(t),timestamp:Z(),version:e.version,uptime:X(),components:t}})}const ke=(e,n)=>t.Effect.sync(()=>{let t=be(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*W).requirePermission(R.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*W).requirePermission(R.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.UploadEngine,a=yield*W,o=yield*u,s=yield*J,l=yield*a.getClientId();yield*a.requirePermission(R.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 w(`Invalid input file schema`));if(d.data.checksumAlgorithm&&!(0,i.isSupportedAlgorithm)(d.data.checksumAlgorithm))return yield*t.Effect.fail(new w(`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 N(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.UploadEngine,n=yield*W,r=yield*n.getClientId();return yield*n.requirePermission(R.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.UploadEngine;return yield*(yield*W).requirePermission(R.UPLOAD.READ),{status:200,body:yield*t.getUpload(e)}}),Fe=e=>t.Effect.gen(function*(){let n=yield*c.UploadEngine,r=yield*W,i=yield*u,a=yield*s.MetricsService,o=yield*J,{uploadId:l,data:d}=e;yield*r.requirePermission(R.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*pe(e);case`run-flow`:return yield*me(e);case`job-status`:return yield*he(e);case`resume-flow`:return yield*ge(e);case`pause-flow`:return yield*_e(e);case`cancel-flow`:return yield*ve(e);case`dlq-list`:return yield*ae(e);case`dlq-get`:return yield*oe(e);case`dlq-retry`:return yield*se(e);case`dlq-retry-all`:return yield*ce(e);case`dlq-delete`:return yield*le(e);case`dlq-resolve`:return yield*ue(e);case`dlq-cleanup`:return yield*de(e);case`dlq-stats`:return yield*fe(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:v=i.GenerateIdLive,metricsLayer:y,bufferedDataStore:b,adapter:C,authCacheConfig:w,circuitBreaker:T=!0,deadLetterQueue:E=!1,healthCheck:D,usageHooks:O})=>{let k=f??(0,o.webSocketEventEmitter)(p),A=g.endsWith(`/`)?g.slice(0,-1):g,j=t.Layer.effect(n.FlowProvider,t.Effect.succeed({getFlow:(t,n)=>e(t,n)}));if(!k)throw Error(`eventEmitter is required. Provide an event emitter layer in the configuration.`);let M=x({kvStore:l,eventEmitter:k,dataStore:await(0,r.createDataStoreLayer)(c),bufferedDataStore:b,generateId:v}),N=S({kvStore:l,eventEmitter:k,flowProvider:j,uploadEngine:M}),P=d(w),F=y??s.NoOpMetricsServiceLive,I=T?n.kvCircuitBreakerStoreLayer.pipe(t.Layer.provide(l)):null,L=E?n.deadLetterQueueService.pipe(t.Layer.provide(r.deadLetterQueueKvStore),t.Layer.provide(l)):null,R=Y(O),z=t.Layer.mergeAll(M,N,F,P,R,...u,...I?[I]:[],...L?[L]:[]),B=m?h??s.NodeSdkLive:null,V=z,H=B?t.Layer.merge(V,B):V,U=t.ManagedRuntime.make(H);return{handler:async e=>{let r=t.Effect.gen(function*(){let r=yield*C.extractRequest(e,{baseUrl:A}),i=null;if(C.runAuthMiddleware){let n=yield*C.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*C.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*C.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*C.sendResponse({status:401,headers:{"Content-Type":`application/json`},body:{error:`Unauthorized`,message:`Invalid credentials`}},e);i=n}let a=G(i,{bypassAuth:!C.runAuthMiddleware}),o=[];if(C.extractWaitUntil){let r=C.extractWaitUntil(e);r&&o.push(t.Layer.succeed(n.FlowWaitUntil,r))}let s=t.Layer.mergeAll(a,P,F,R,...u,...o),c=I?t.Layer.merge(s,I):s,l=L?t.Layer.merge(c,L):c;if(r.type===`not-found`)return yield*C.sendResponse({type:`not-found`,status:404,headers:{"Content-Type":`application/json`},body:{error:`Not found`}},e);let d=yield*Ie(r,{healthCheckConfig:D}).pipe(t.Effect.provide(l));return yield*C.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 C.sendResponse(i,e)}));return U.runPromise(r)},websocketHandler:await U.runPromise(C.webSocketHandler({baseUrl:A})),baseUrl:A,dispose:()=>U.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=C,exports.AuthCacheService=u,exports.AuthCacheServiceLive=d,exports.AuthContextService=W,exports.AuthContextServiceLive=G,exports.AuthenticationRequiredError=j,exports.AuthorizationError=A,exports.BadRequestError=E,exports.DEFAULT_USAGE_HOOK_TIMEOUT=q,exports.ENGINE_PERMISSIONS=F,exports.FLOW_PERMISSIONS=I,exports.NoAuthCacheServiceLive=f,exports.NoAuthContextServiceLive=ne,exports.NoUsageHookServiceLive=ie,exports.NotFoundError=T,exports.OrganizationMismatchError=M,exports.PERMISSIONS=R,exports.PERMISSION_HIERARCHY=B,exports.PERMISSION_SETS=z,exports.QuotaExceededError=N,exports.UPLOAD_PERMISSIONS=L,exports.UsageHookService=J,exports.UsageHookServiceLive=Y,exports.ValidationError=w,exports.abortResult=re,exports.continueResult=K,exports.createAuthorizationErrorResponseBody=P,exports.createErrorResponseBody=D,exports.createFlowEngineLayer=S,exports.createGenericErrorResponseBody=k,exports.createTypeSafeServer=Re,exports.createUploadEngineLayer=x,exports.createUploadistaErrorResponseBody=O,exports.createUploadistaServer=Le,exports.defineFlow=ze,exports.defineSimpleFlow=Be,exports.expandPermission=te,exports.extractFlowAndStorageId=b,exports.extractJobAndNodeId=y,exports.extractJobIdFromStatus=v,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=ee,exports.hasAnyPermission=U,exports.hasBasePath=h,exports.hasPermission=H,exports.matchesPermission=V,exports.parseUrlSegments=p,exports.validatePluginRequirements=Q,exports.validatePluginRequirementsEffect=We,exports.validatePluginsOrThrow=Ge;
|