@uploadista/core 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.
Files changed (46) hide show
  1. package/dist/flow/index.cjs +1 -1
  2. package/dist/flow/index.d.cts +2 -2
  3. package/dist/flow/index.d.mts +2 -2
  4. package/dist/flow/index.mjs +1 -1
  5. package/dist/flow-BHVkk_6W.cjs +1 -0
  6. package/dist/{flow-_OmguvZm.mjs → flow-DlhHOlMk.mjs} +2 -2
  7. package/dist/flow-DlhHOlMk.mjs.map +1 -0
  8. package/dist/index-9gyMMEIB.d.cts.map +1 -1
  9. package/dist/{index-Dim9X1-G.d.cts → index-BtDyiX5-.d.cts} +1604 -1604
  10. package/dist/index-BtDyiX5-.d.cts.map +1 -0
  11. package/dist/{index-Bhlv8wF9.d.mts → index-XXHmCYAu.d.mts} +1604 -1604
  12. package/dist/index-XXHmCYAu.d.mts.map +1 -0
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.d.cts +2 -2
  15. package/dist/index.d.mts +2 -2
  16. package/dist/index.mjs +1 -1
  17. package/dist/testing/index.cjs +2 -2
  18. package/dist/testing/index.d.cts +9 -9
  19. package/dist/testing/index.d.cts.map +1 -1
  20. package/dist/testing/index.d.mts +9 -9
  21. package/dist/testing/index.d.mts.map +1 -1
  22. package/dist/testing/index.mjs +2 -2
  23. package/dist/testing/index.mjs.map +1 -1
  24. package/dist/types/index.d.cts +1 -1
  25. package/dist/types/index.d.mts +1 -1
  26. package/dist/upload/index.cjs +1 -1
  27. package/dist/upload/index.d.cts +2 -2
  28. package/dist/upload/index.d.mts +2 -2
  29. package/dist/upload/index.mjs +1 -1
  30. package/dist/{upload-tLC7uR9U.mjs → upload-C-C7hn1-.mjs} +2 -2
  31. package/dist/{upload-tLC7uR9U.mjs.map → upload-C-C7hn1-.mjs.map} +1 -1
  32. package/dist/{upload-BHDuuJ80.cjs → upload-DWBlRXHh.cjs} +1 -1
  33. package/package.json +7 -7
  34. package/src/flow/{flow-server.ts → flow-engine.ts} +106 -106
  35. package/src/flow/index.ts +10 -10
  36. package/src/flow/nodes/input-node.ts +5 -5
  37. package/src/flow/nodes/transform-node.ts +11 -14
  38. package/src/flow/typed-flow.ts +22 -20
  39. package/src/testing/index.ts +1 -1
  40. package/src/testing/{mock-upload-server.ts → mock-upload-engine.ts} +10 -10
  41. package/src/upload/index.ts +1 -1
  42. package/src/upload/{upload-server.ts → upload-engine.ts} +44 -40
  43. package/dist/flow-Cv8vCBQ2.cjs +0 -1
  44. package/dist/flow-_OmguvZm.mjs.map +0 -1
  45. package/dist/index-Bhlv8wF9.d.mts.map +0 -1
  46. package/dist/index-Dim9X1-G.d.cts.map +0 -1
@@ -1,4 +1,4 @@
1
- import"../uploadista-error-CkSxSyNo.mjs";import"../errors-CtPUOWNd.mjs";import{A as e,M as t,a as n,i as r,j as i,k as a,r as o}from"../flow-_OmguvZm.mjs";import{b as s}from"../types-DKGQJIEr.mjs";import{n as c}from"../upload-tLC7uR9U.mjs";import"../checksum-COoD-F1l.mjs";import"../stream-limiter-B9nsn2gb.mjs";import{Effect as l,Layer as u,Stream as d}from"effect";const f=u.succeed(t,t.of({performOCR:(e,t,n)=>l.sync(()=>({extractedText:t.taskType===`convertToMarkdown`?`# Document Title
1
+ import"../uploadista-error-CkSxSyNo.mjs";import"../errors-CtPUOWNd.mjs";import{A as e,M as t,a as n,i as r,j as i,k as a,r as o}from"../flow-DlhHOlMk.mjs";import{b as s}from"../types-DKGQJIEr.mjs";import{n as c}from"../upload-C-C7hn1-.mjs";import"../checksum-COoD-F1l.mjs";import"../stream-limiter-B9nsn2gb.mjs";import{Effect as l,Layer as u,Stream as d}from"effect";const f=u.succeed(t,t.of({performOCR:(e,t,n)=>l.sync(()=>({extractedText:t.taskType===`convertToMarkdown`?`# Document Title
2
2
 
3
3
  This is a paragraph with **bold** text.
4
4
 
@@ -6,5 +6,5 @@ This is a paragraph with **bold** text.
6
6
 
7
7
  - List item 1
8
8
  - List item 2`:`Plain text extracted from document without formatting.`,format:t.taskType===`convertToMarkdown`?`markdown`:`plain`,confidence:.95}))})),p=u.succeed(i,i.of({extractText:e=>l.sync(()=>`This is extracted text from a PDF document.
9
- Page 1 content.`),splitPdf:(e,t)=>l.sync(()=>t.mode===`range`?{mode:`range`,pdf:new Uint8Array(500).fill(80)}:{mode:`individual`,pdfs:[new Uint8Array(200).fill(81),new Uint8Array(200).fill(82),new Uint8Array(200).fill(83)]}),mergePdfs:e=>l.sync(()=>{let t=e.pdfs.reduce((e,t)=>e+t.byteLength,0);return new Uint8Array(t).fill(90)}),getMetadata:e=>l.sync(()=>({pageCount:5,format:`pdf`,author:`Test Author`,title:`Test Document`,subject:`Test Subject`,creator:`Test Creator`,creationDate:`2024-01-01T00:00:00Z`,modifiedDate:`2024-01-02T00:00:00Z`,fileSize:e.byteLength}))})),m=u.succeed(e,e.of({removeBackground:(e,t)=>l.sync(()=>({outputUrl:e.replace(`.jpg`,`-no-bg.png`)})),describeImage:(e,t)=>l.sync(()=>({description:`A test image from ${e}`}))})),h=u.succeed(a,a.of({optimize:(e,t)=>l.sync(()=>{let n=t.quality/100,r=Math.floor(e.byteLength*n);return new Uint8Array(r).fill(128)}),resize:(e,t)=>l.sync(()=>{let e=t.width||800,n=t.height||600,r=Math.floor(e*n/10);return new Uint8Array(r).fill(100)}),transform:(e,t)=>l.sync(()=>t.type===`rotate`&&t.angle===90?new Uint8Array(e.byteLength+10).fill(150):t.type===`blur`?new Uint8Array(e.byteLength).fill(180):t.type===`grayscale`?new Uint8Array(e.byteLength).fill(128):new Uint8Array(e.byteLength).fill(200))})),g=u.succeed(c,c.of({read:(e,t)=>l.sync(()=>{let t=`Content of file ${e}`;return new TextEncoder().encode(t)}),readStream:(e,t,n)=>l.sync(()=>{let t={...s,...n},r=`Content of file ${e}`,i=new TextEncoder().encode(r),a=t.chunkSize,o=[];for(let e=0;e<i.length;e+=a)o.push(i.slice(e,e+a));return d.fromIterable(o)}),uploadStream:(e,t,n)=>l.gen(function*(){let t=[];yield*d.runForEach(n,e=>l.sync(()=>{t.push(e)}));let r=t.reduce((e,t)=>e+t.length,0),i=typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata||{},a=e.fileName?e.fileName.split(`.`).pop():i.extension,o=`stream-uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`;return{id:o,offset:r,size:r,storage:{id:e.storageId,type:`memory`},metadata:{...i,mimeType:e.type,type:e.type,"content-type":e.type,fileName:e.fileName,originalName:e.fileName,name:e.fileName,extension:a},url:`http://test-storage/${o}`,creationDate:new Date().toISOString()}}),upload:(e,t,n)=>l.gen(function*(){let t=n.getReader(),r=0,i=[];for(;;){let{done:e,value:n}=yield*l.promise(()=>t.read());if(e)break;n&&(i.push(n),r+=n.byteLength)}let a=typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata||{},o=e.fileName?e.fileName.split(`.`).pop():a.extension;return{id:`uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:r,size:r,storage:{id:e.storageId,type:`memory`},metadata:{...a,mimeType:e.type,type:e.type,"content-type":e.type,fileName:e.fileName,originalName:e.fileName,name:e.fileName,extension:o},creationDate:new Date().toISOString()}}),delete:(e,t)=>l.void,createUpload:(e,t)=>l.succeed({id:`uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:0,size:0,storage:{id:e.storageId,type:`memory`},metadata:typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata}),uploadChunk:(e,t,n)=>l.gen(function*(){let t=n.getReader(),r=0,i=[];for(;;){let{done:e,value:n}=yield*l.promise(()=>t.read());if(e)break;n&&(i.push(n),r+=n.byteLength)}return{id:e,offset:r,size:r,storage:{id:`test-storage`,type:`memory`},metadata:{mimeType:`application/octet-stream`,extension:`bin`},creationDate:new Date().toISOString()}}),getCapabilities:(e,t)=>l.succeed({supportsParallelUploads:!0,supportsConcatenation:!0,supportsDeferredLength:!0,supportsResumableUploads:!0,supportsTransactionalUploads:!1,supportsStreamingRead:!0,supportsStreamingWrite:!0,maxConcurrentUploads:10,minChunkSize:5*1024*1024,maxChunkSize:100*1024*1024,maxParts:1e4,optimalChunkSize:10*1024*1024,requiresOrderedChunks:!1,requiresMimeTypeValidation:!1}),uploadFromUrl:(e,t,n)=>l.succeed({id:`uploaded-from-url-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:0,size:0,storage:{id:e.storageId,type:`memory`},metadata:typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata,url:n,creationDate:new Date().toISOString()}),getUpload:e=>l.succeed({id:e,offset:0,size:1024,storage:{id:`test-storage`,type:`memory`},metadata:{mimeType:`text/plain`,originalName:`file-${e}.txt`,extension:`txt`},creationDate:new Date().toISOString()}),subscribeToUploadEvents:(e,t)=>l.void,unsubscribeFromUploadEvents:e=>l.void})),_=u.succeed(n,n.of({describe:e=>l.sync(()=>({duration:120,width:1920,height:1080,codec:`h264`,format:`mp4`,bitrate:5e6,frameRate:30,aspectRatio:`16:9`,hasAudio:!0,audioCodec:`aac`,audioBitrate:128e3,size:e.byteLength})),transcode:(e,t)=>l.sync(()=>{let n=1;t.codec===`vp9`?n=.8:t.codec===`h265`&&(n=.7);let r=Math.floor(e.byteLength*n);return new Uint8Array(r).fill(42)}),resize:(e,t)=>l.sync(()=>{let e=t.width||1280,n=t.height||720,r=Math.floor(e*n/50);return new Uint8Array(r).fill(84)}),trim:(e,t)=>l.sync(()=>{let n;n=t.duration===void 0?t.endTime===void 0?120-t.startTime:t.endTime-t.startTime:t.duration;let r=n/120,i=Math.floor(e.byteLength*r);return new Uint8Array(i).fill(63)}),extractFrame:(e,t)=>l.sync(()=>{let e=(t.format||`jpeg`)===`png`?5e4:3e4;return new Uint8Array(e).fill(255)})})),v=u.succeed(r,r.of({scan:e=>l.sync(()=>new TextDecoder().decode(e).includes(`X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*`)?{isClean:!1,detectedViruses:[`EICAR-Test-File`]}:{isClean:!0,detectedViruses:[]}),getVersion:()=>l.sync(()=>`TestVirusScanPlugin 1.0.0`)})),y=u.succeed(o,o.of({zip:(e,t)=>l.gen(function*(){let n=e.map(e=>({id:e.id,size:e.data.byteLength})),r=JSON.stringify({zipName:t.zipName,includeMetadata:t.includeMetadata,files:n});return new TextEncoder().encode(r)})}));export{f as TestDocumentAiPlugin,p as TestDocumentPlugin,m as TestImageAiPlugin,h as TestImagePlugin,g as TestUploadServer,_ as TestVideoPlugin,v as TestVirusScanPlugin,y as TestZipPlugin};
9
+ Page 1 content.`),splitPdf:(e,t)=>l.sync(()=>t.mode===`range`?{mode:`range`,pdf:new Uint8Array(500).fill(80)}:{mode:`individual`,pdfs:[new Uint8Array(200).fill(81),new Uint8Array(200).fill(82),new Uint8Array(200).fill(83)]}),mergePdfs:e=>l.sync(()=>{let t=e.pdfs.reduce((e,t)=>e+t.byteLength,0);return new Uint8Array(t).fill(90)}),getMetadata:e=>l.sync(()=>({pageCount:5,format:`pdf`,author:`Test Author`,title:`Test Document`,subject:`Test Subject`,creator:`Test Creator`,creationDate:`2024-01-01T00:00:00Z`,modifiedDate:`2024-01-02T00:00:00Z`,fileSize:e.byteLength}))})),m=u.succeed(e,e.of({removeBackground:(e,t)=>l.sync(()=>({outputUrl:e.replace(`.jpg`,`-no-bg.png`)})),describeImage:(e,t)=>l.sync(()=>({description:`A test image from ${e}`}))})),h=u.succeed(a,a.of({optimize:(e,t)=>l.sync(()=>{let n=t.quality/100,r=Math.floor(e.byteLength*n);return new Uint8Array(r).fill(128)}),resize:(e,t)=>l.sync(()=>{let e=t.width||800,n=t.height||600,r=Math.floor(e*n/10);return new Uint8Array(r).fill(100)}),transform:(e,t)=>l.sync(()=>t.type===`rotate`&&t.angle===90?new Uint8Array(e.byteLength+10).fill(150):t.type===`blur`?new Uint8Array(e.byteLength).fill(180):t.type===`grayscale`?new Uint8Array(e.byteLength).fill(128):new Uint8Array(e.byteLength).fill(200))})),g=u.succeed(c,c.of({read:(e,t)=>l.sync(()=>{let t=`Content of file ${e}`;return new TextEncoder().encode(t)}),readStream:(e,t,n)=>l.sync(()=>{let t={...s,...n},r=`Content of file ${e}`,i=new TextEncoder().encode(r),a=t.chunkSize,o=[];for(let e=0;e<i.length;e+=a)o.push(i.slice(e,e+a));return d.fromIterable(o)}),uploadStream:(e,t,n)=>l.gen(function*(){let t=[];yield*d.runForEach(n,e=>l.sync(()=>{t.push(e)}));let r=t.reduce((e,t)=>e+t.length,0),i=typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata||{},a=e.fileName?e.fileName.split(`.`).pop():i.extension,o=`stream-uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`;return{id:o,offset:r,size:r,storage:{id:e.storageId,type:`memory`},metadata:{...i,mimeType:e.type,type:e.type,"content-type":e.type,fileName:e.fileName,originalName:e.fileName,name:e.fileName,extension:a},url:`http://test-storage/${o}`,creationDate:new Date().toISOString()}}),upload:(e,t,n)=>l.gen(function*(){let t=n.getReader(),r=0,i=[];for(;;){let{done:e,value:n}=yield*l.promise(()=>t.read());if(e)break;n&&(i.push(n),r+=n.byteLength)}let a=typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata||{},o=e.fileName?e.fileName.split(`.`).pop():a.extension;return{id:`uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:r,size:r,storage:{id:e.storageId,type:`memory`},metadata:{...a,mimeType:e.type,type:e.type,"content-type":e.type,fileName:e.fileName,originalName:e.fileName,name:e.fileName,extension:o},creationDate:new Date().toISOString()}}),delete:(e,t)=>l.void,createUpload:(e,t)=>l.succeed({id:`uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:0,size:0,storage:{id:e.storageId,type:`memory`},metadata:typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata}),uploadChunk:(e,t,n)=>l.gen(function*(){let t=n.getReader(),r=0,i=[];for(;;){let{done:e,value:n}=yield*l.promise(()=>t.read());if(e)break;n&&(i.push(n),r+=n.byteLength)}return{id:e,offset:r,size:r,storage:{id:`test-storage`,type:`memory`},metadata:{mimeType:`application/octet-stream`,extension:`bin`},creationDate:new Date().toISOString()}}),getCapabilities:(e,t)=>l.succeed({supportsParallelUploads:!0,supportsConcatenation:!0,supportsDeferredLength:!0,supportsResumableUploads:!0,supportsTransactionalUploads:!1,supportsStreamingRead:!0,supportsStreamingWrite:!0,maxConcurrentUploads:10,minChunkSize:5*1024*1024,maxChunkSize:100*1024*1024,maxParts:1e4,optimalChunkSize:10*1024*1024,requiresOrderedChunks:!1,requiresMimeTypeValidation:!1}),uploadFromUrl:(e,t,n)=>l.succeed({id:`uploaded-from-url-${Date.now()}-${Math.random().toString(36).substring(7)}`,offset:0,size:0,storage:{id:e.storageId,type:`memory`},metadata:typeof e.metadata==`string`?JSON.parse(e.metadata):e.metadata,url:n,creationDate:new Date().toISOString()}),getUpload:e=>l.succeed({id:e,offset:0,size:1024,storage:{id:`test-storage`,type:`memory`},metadata:{mimeType:`text/plain`,originalName:`file-${e}.txt`,extension:`txt`},creationDate:new Date().toISOString()}),subscribeToUploadEvents:(e,t)=>l.void,unsubscribeFromUploadEvents:e=>l.void})),_=u.succeed(n,n.of({describe:e=>l.sync(()=>({duration:120,width:1920,height:1080,codec:`h264`,format:`mp4`,bitrate:5e6,frameRate:30,aspectRatio:`16:9`,hasAudio:!0,audioCodec:`aac`,audioBitrate:128e3,size:e.byteLength})),transcode:(e,t)=>l.sync(()=>{let n=1;t.codec===`vp9`?n=.8:t.codec===`h265`&&(n=.7);let r=Math.floor(e.byteLength*n);return new Uint8Array(r).fill(42)}),resize:(e,t)=>l.sync(()=>{let e=t.width||1280,n=t.height||720,r=Math.floor(e*n/50);return new Uint8Array(r).fill(84)}),trim:(e,t)=>l.sync(()=>{let n;n=t.duration===void 0?t.endTime===void 0?120-t.startTime:t.endTime-t.startTime:t.duration;let r=n/120,i=Math.floor(e.byteLength*r);return new Uint8Array(i).fill(63)}),extractFrame:(e,t)=>l.sync(()=>{let e=(t.format||`jpeg`)===`png`?5e4:3e4;return new Uint8Array(e).fill(255)})})),v=u.succeed(r,r.of({scan:e=>l.sync(()=>new TextDecoder().decode(e).includes(`X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*`)?{isClean:!1,detectedViruses:[`EICAR-Test-File`]}:{isClean:!0,detectedViruses:[]}),getVersion:()=>l.sync(()=>`TestVirusScanPlugin 1.0.0`)})),y=u.succeed(o,o.of({zip:(e,t)=>l.gen(function*(){let n=e.map(e=>({id:e.id,size:e.data.byteLength})),r=JSON.stringify({zipName:t.zipName,includeMetadata:t.includeMetadata,files:n});return new TextEncoder().encode(r)})}));export{f as TestDocumentAiPlugin,p as TestDocumentPlugin,m as TestImageAiPlugin,h as TestImagePlugin,g as TestUploadEngine,_ as TestVideoPlugin,v as TestVirusScanPlugin,y as TestZipPlugin};
10
10
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["chunks: Uint8Array[]","duration: number"],"sources":["../../src/testing/mock-document-ai-plugin.ts","../../src/testing/mock-document-plugin.ts","../../src/testing/mock-image-ai-plugin.ts","../../src/testing/mock-image-plugin.ts","../../src/testing/mock-upload-server.ts","../../src/testing/mock-video-plugin.ts","../../src/testing/mock-virus-scan-plugin.ts","../../src/testing/mock-zip-plugin.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport type { OcrResult } from \"../flow\";\nimport { DocumentAiPlugin } from \"../flow\";\n\n/**\n * Mock DocumentAiPlugin implementation for testing.\n *\n * Provides simple mock implementations of AI document operations.\n *\n * @example\n * ```typescript\n * import { TestDocumentAiPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* DocumentAiPlugin;\n * const result = yield* plugin.performOCR(\n * \"https://example.com/doc.pdf\",\n * { taskType: \"convertToMarkdown\", resolution: \"gundam\" },\n * { clientId: \"test-client\" }\n * );\n * return result;\n * }).pipe(Effect.provide(TestDocumentAiPlugin));\n * ```\n */\nexport const TestDocumentAiPlugin = Layer.succeed(\n DocumentAiPlugin,\n DocumentAiPlugin.of({\n performOCR: (inputUrl: string, params, context) =>\n Effect.sync(() => {\n const result: OcrResult = {\n extractedText:\n params.taskType === \"convertToMarkdown\"\n ? \"# Document Title\\n\\nThis is a paragraph with **bold** text.\\n\\n## Section 2\\n\\n- List item 1\\n- List item 2\"\n : \"Plain text extracted from document without formatting.\",\n format:\n params.taskType === \"convertToMarkdown\" ? \"markdown\" : \"plain\",\n confidence: 0.95,\n };\n return result;\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport type { DocumentMetadata, SplitPdfResult } from \"../flow\";\nimport { DocumentPlugin } from \"../flow\";\n\n/**\n * Mock DocumentPlugin implementation for testing.\n *\n * Provides simple mock implementations of PDF operations that return mock data.\n *\n * @example\n * ```typescript\n * import { TestDocumentPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* DocumentPlugin;\n * const text = yield* plugin.extractText(pdfBytes);\n * return text;\n * }).pipe(Effect.provide(TestDocumentPlugin));\n * ```\n */\nexport const TestDocumentPlugin = Layer.succeed(\n DocumentPlugin,\n DocumentPlugin.of({\n extractText: (input: Uint8Array) =>\n Effect.sync(() => {\n // Mock text extraction\n return \"This is extracted text from a PDF document.\\nPage 1 content.\";\n }),\n splitPdf: (input: Uint8Array, options) =>\n Effect.sync(() => {\n if (options.mode === \"range\") {\n // Mock range split\n const mockPdf = new Uint8Array(500).fill(80);\n return {\n mode: \"range\" as const,\n pdf: mockPdf,\n } satisfies SplitPdfResult;\n }\n // Mock individual split\n const mockPdfs = [\n new Uint8Array(200).fill(81),\n new Uint8Array(200).fill(82),\n new Uint8Array(200).fill(83),\n ];\n return {\n mode: \"individual\" as const,\n pdfs: mockPdfs,\n } satisfies SplitPdfResult;\n }),\n mergePdfs: (options) =>\n Effect.sync(() => {\n // Mock merge: combine sizes\n const totalSize = options.pdfs.reduce(\n (sum, pdf) => sum + pdf.byteLength,\n 0,\n );\n return new Uint8Array(totalSize).fill(90);\n }),\n getMetadata: (input: Uint8Array) =>\n Effect.sync(() => {\n const metadata: DocumentMetadata = {\n pageCount: 5,\n format: \"pdf\",\n author: \"Test Author\",\n title: \"Test Document\",\n subject: \"Test Subject\",\n creator: \"Test Creator\",\n creationDate: \"2024-01-01T00:00:00Z\",\n modifiedDate: \"2024-01-02T00:00:00Z\",\n fileSize: input.byteLength,\n };\n return metadata;\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ImageAiPlugin } from \"../flow\";\n\n/**\n * Mock ImageAiPlugin implementation for testing.\n *\n * Provides simple mock implementations of AI-powered image operations\n * like background removal and image description.\n *\n * @example\n * ```typescript\n * import { TestImageAiPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* ImageAiPlugin;\n * const result = yield* plugin.removeBackground(imageUrl, context);\n * return result;\n * }).pipe(Effect.provide(TestImageAiPlugin));\n * ```\n */\nexport const TestImageAiPlugin = Layer.succeed(\n ImageAiPlugin,\n ImageAiPlugin.of({\n removeBackground: (inputUrl: string, _context) =>\n Effect.sync(() => ({\n outputUrl: inputUrl.replace(\".jpg\", \"-no-bg.png\"),\n })),\n describeImage: (inputUrl: string, _context) =>\n Effect.sync(() => ({\n description: `A test image from ${inputUrl}`,\n })),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ImagePlugin } from \"../flow\";\n\n/**\n * Mock ImagePlugin implementation for testing.\n *\n * Provides simple mock implementations of image optimization, resizing,\n * and transformation operations that return mock Uint8Array data.\n *\n * @example\n * ```typescript\n * import { TestImagePlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* ImagePlugin;\n * const optimized = yield* plugin.optimize(imageBytes, { quality: 80, format: \"webp\" });\n * return optimized;\n * }).pipe(Effect.provide(TestImagePlugin));\n * ```\n */\nexport const TestImagePlugin = Layer.succeed(\n ImagePlugin,\n ImagePlugin.of({\n optimize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock optimize: return smaller array for lower quality\n const sizeMultiplier = options.quality / 100;\n const newSize = Math.floor(input.byteLength * sizeMultiplier);\n return new Uint8Array(newSize).fill(128);\n }),\n resize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock resize: return array with size based on dimensions\n const width = options.width || 800;\n const height = options.height || 600;\n const mockSize = Math.floor((width * height) / 10);\n return new Uint8Array(mockSize).fill(100);\n }),\n transform: (input: Uint8Array, transformation) =>\n Effect.sync(() => {\n // Mock transform: modify array based on transformation type\n if (transformation.type === \"rotate\" && transformation.angle === 90) {\n // For 90° rotation, swap dimensions (mock behavior)\n return new Uint8Array(input.byteLength + 10).fill(150);\n }\n if (transformation.type === \"blur\") {\n return new Uint8Array(input.byteLength).fill(180);\n }\n if (transformation.type === \"grayscale\") {\n return new Uint8Array(input.byteLength).fill(128);\n }\n // Default: return modified copy\n return new Uint8Array(input.byteLength).fill(200);\n }),\n }),\n);\n","import { Effect, Layer, Stream } from \"effect\";\nimport type { UploadistaError } from \"../errors\";\nimport type { InputFile, UploadFile, WebSocketConnection } from \"../types\";\nimport {\n DEFAULT_STREAMING_CONFIG,\n type DataStoreCapabilities,\n type StreamingConfig,\n} from \"../types/data-store\";\nimport { UploadServer } from \"../upload\";\n\n/**\n * Mock UploadServer implementation for testing.\n *\n * Provides a complete in-memory implementation of all UploadServer methods\n * suitable for unit and integration tests.\n *\n * @example\n * ```typescript\n * import { TestUploadServer } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const server = yield* UploadServer;\n * const upload = yield* server.createUpload(inputFile, \"client-123\");\n * return upload;\n * }).pipe(Effect.provide(TestUploadServer));\n * ```\n */\nexport const TestUploadServer = Layer.succeed(\n UploadServer,\n UploadServer.of({\n read: (fileId: string, _clientId: string | null) =>\n Effect.sync(() => {\n // Generate mock file data based on fileId\n const text = `Content of file ${fileId}`;\n return new TextEncoder().encode(text);\n }),\n readStream: (\n fileId: string,\n _clientId: string | null,\n config?: StreamingConfig,\n ) =>\n Effect.sync(() => {\n const effectiveConfig = { ...DEFAULT_STREAMING_CONFIG, ...config };\n // Generate mock file data based on fileId\n const text = `Content of file ${fileId}`;\n const fullData = new TextEncoder().encode(text);\n\n // Split data into chunks based on chunkSize\n const chunkSize = effectiveConfig.chunkSize;\n const chunks: Uint8Array[] = [];\n for (let i = 0; i < fullData.length; i += chunkSize) {\n chunks.push(fullData.slice(i, i + chunkSize));\n }\n\n // Return as a stream of chunks\n return Stream.fromIterable(chunks);\n }),\n uploadStream: (\n file: Omit<InputFile, \"size\"> & { size?: number; sizeHint?: number },\n _clientId: string | null,\n stream: Stream.Stream<Uint8Array, UploadistaError>,\n ) =>\n Effect.gen(function* () {\n // Collect stream to calculate total size\n const chunks: Uint8Array[] = [];\n yield* Stream.runForEach(stream, (chunk) =>\n Effect.sync(() => {\n chunks.push(chunk);\n }),\n );\n\n const totalSize = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n\n // Parse existing metadata\n const existingMetadata =\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata || {};\n\n // Extract extension from fileName\n const extension = file.fileName\n ? file.fileName.split(\".\").pop()\n : existingMetadata.extension;\n\n // Create new UploadFile with final size\n const uploadId = `stream-uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n return {\n id: uploadId,\n offset: totalSize,\n size: totalSize,\n storage: {\n id: file.storageId,\n type: \"memory\",\n },\n metadata: {\n ...existingMetadata,\n mimeType: file.type,\n type: file.type,\n \"content-type\": file.type,\n fileName: file.fileName,\n originalName: file.fileName,\n name: file.fileName,\n extension,\n },\n url: `http://test-storage/${uploadId}`,\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n upload: (file, _clientId, stream) =>\n Effect.gen(function* () {\n // Read stream to completion\n const reader = stream.getReader();\n let totalSize = 0;\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = yield* Effect.promise(() => reader.read());\n if (done) break;\n if (value) {\n chunks.push(value);\n totalSize += value.byteLength;\n }\n }\n\n // Parse existing metadata\n const existingMetadata =\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata || {};\n\n // Extract extension from fileName\n const extension = file.fileName\n ? file.fileName.split(\".\").pop()\n : existingMetadata.extension;\n\n // Create new UploadFile with merged metadata\n return {\n id: `uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: totalSize,\n size: totalSize,\n storage: {\n id: file.storageId,\n type: \"memory\",\n },\n metadata: {\n ...existingMetadata,\n // Update with InputFile type and fileName\n mimeType: file.type,\n type: file.type,\n \"content-type\": file.type,\n fileName: file.fileName,\n originalName: file.fileName,\n name: file.fileName,\n extension,\n },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n delete: (_fileId: string, _clientId: string | null) => Effect.void,\n createUpload: (file: InputFile, _clientId: string | null) =>\n Effect.succeed({\n id: `uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: 0,\n size: 0,\n storage: { id: file.storageId, type: \"memory\" },\n metadata:\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata,\n } satisfies UploadFile),\n uploadChunk: (\n uploadId: string,\n _clientId: string | null,\n chunk: ReadableStream,\n ) =>\n Effect.gen(function* () {\n // Read stream to completion\n const reader = chunk.getReader();\n let totalSize = 0;\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = yield* Effect.promise(() => reader.read());\n if (done) break;\n if (value) {\n chunks.push(value);\n totalSize += value.byteLength;\n }\n }\n return {\n id: uploadId,\n offset: totalSize,\n size: totalSize,\n storage: { id: \"test-storage\", type: \"memory\" },\n metadata: { mimeType: \"application/octet-stream\", extension: \"bin\" },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n getCapabilities: (_storageId: string, _clientId: string | null) =>\n Effect.succeed({\n supportsParallelUploads: true,\n supportsConcatenation: true,\n supportsDeferredLength: true,\n supportsResumableUploads: true,\n supportsTransactionalUploads: false,\n supportsStreamingRead: true,\n supportsStreamingWrite: true,\n maxConcurrentUploads: 10,\n minChunkSize: 5 * 1024 * 1024, // 5MB\n maxChunkSize: 100 * 1024 * 1024, // 100MB\n maxParts: 10000,\n optimalChunkSize: 10 * 1024 * 1024, // 10MB\n requiresOrderedChunks: false,\n requiresMimeTypeValidation: false,\n } satisfies DataStoreCapabilities),\n uploadFromUrl: (\n inputFile: InputFile,\n _clientId: string | null,\n url: string,\n ) =>\n Effect.succeed({\n id: `uploaded-from-url-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: 0,\n size: 0,\n storage: { id: inputFile.storageId, type: \"memory\" },\n metadata:\n typeof inputFile.metadata === \"string\"\n ? JSON.parse(inputFile.metadata)\n : inputFile.metadata,\n url,\n creationDate: new Date().toISOString(),\n } satisfies UploadFile),\n getUpload: (uploadId: string) =>\n Effect.succeed({\n id: uploadId,\n offset: 0,\n size: 1024,\n storage: {\n id: \"test-storage\",\n type: \"memory\",\n },\n metadata: {\n mimeType: \"text/plain\",\n originalName: `file-${uploadId}.txt`,\n extension: \"txt\",\n },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile),\n subscribeToUploadEvents: (\n _uploadId: string,\n _connection: WebSocketConnection,\n ) => Effect.void,\n unsubscribeFromUploadEvents: (_uploadId: string) => Effect.void,\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { VideoPlugin } from \"../flow\";\nimport type { DescribeVideoMetadata } from \"../flow/plugins/types/describe-video-node\";\n\n/**\n * Mock VideoPlugin implementation for testing.\n *\n * Provides simple mock implementations of video processing operations\n * that return mock Uint8Array data without requiring FFmpeg or node-av.\n *\n * @example\n * ```typescript\n * import { TestVideoPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* VideoPlugin;\n * const transcoded = yield* plugin.transcode(videoBytes, { format: \"webm\", codec: \"vp9\" });\n * return transcoded;\n * }).pipe(Effect.provide(TestVideoPlugin));\n * ```\n */\nexport const TestVideoPlugin = Layer.succeed(\n VideoPlugin,\n VideoPlugin.of({\n describe: (input: Uint8Array) =>\n Effect.sync(() => {\n // Mock describe: return fake metadata based on input size\n const metadata: DescribeVideoMetadata = {\n duration: 120, // 2 minutes\n width: 1920,\n height: 1080,\n codec: \"h264\",\n format: \"mp4\",\n bitrate: 5000000, // 5 Mbps\n frameRate: 30,\n aspectRatio: \"16:9\",\n hasAudio: true,\n audioCodec: \"aac\",\n audioBitrate: 128000, // 128 kbps\n size: input.byteLength,\n };\n return metadata;\n }),\n transcode: (_input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock transcode: return modified array\n // Simulate different file sizes for different codecs\n let sizeMultiplier = 1.0;\n if (options.codec === \"vp9\") {\n sizeMultiplier = 0.8; // VP9 is more efficient\n } else if (options.codec === \"h265\") {\n sizeMultiplier = 0.7; // H265 is even more efficient\n }\n\n const newSize = Math.floor(_input.byteLength * sizeMultiplier);\n return new Uint8Array(newSize).fill(42);\n }),\n resize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock resize: return array with size based on dimensions\n const width = options.width || 1280;\n const height = options.height || 720;\n // Simulate file size roughly proportional to resolution\n const mockSize = Math.floor((width * height) / 50);\n return new Uint8Array(mockSize).fill(84);\n }),\n trim: (_input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock trim: return smaller array based on duration\n let duration: number;\n if (options.duration !== undefined) {\n duration = options.duration;\n } else if (options.endTime !== undefined) {\n duration = options.endTime - options.startTime;\n } else {\n // Assume 120s total duration\n duration = 120 - options.startTime;\n }\n\n // Simulate proportional file size based on duration\n const ratio = duration / 120; // Assuming 120s original\n const newSize = Math.floor(_input.byteLength * ratio);\n return new Uint8Array(newSize).fill(63);\n }),\n extractFrame: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock extractFrame: return image bytes (smaller than video)\n const format = options.format || \"jpeg\";\n // JPEG typically smaller than PNG\n const mockSize = format === \"png\" ? 50000 : 30000;\n return new Uint8Array(mockSize).fill(255);\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { VirusScanPlugin } from \"../flow\";\n\n/**\n * EICAR test file signature (standard antivirus test file)\n * This is a safe, non-malicious string used to test antivirus software\n */\nconst EICAR_SIGNATURE =\n \"X5O!P%@AP[4\\\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\";\n\n/**\n * Mock VirusScanPlugin implementation for testing.\n *\n * Provides a simple mock implementation that:\n * - Detects the EICAR test signature as infected\n * - Treats all other files as clean\n * - Returns mock version information\n *\n * @example\n * ```typescript\n * import { TestVirusScanPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* VirusScanPlugin;\n * const result = yield* plugin.scan(fileBytes);\n * console.log(result.isClean ? \"Clean\" : \"Infected\");\n * }).pipe(Effect.provide(TestVirusScanPlugin));\n * ```\n */\nexport const TestVirusScanPlugin = Layer.succeed(\n VirusScanPlugin,\n VirusScanPlugin.of({\n scan: (input: Uint8Array) =>\n Effect.sync(() => {\n // Convert bytes to string to check for EICAR signature\n const textDecoder = new TextDecoder();\n const content = textDecoder.decode(input);\n\n // Check if file contains EICAR test signature\n if (content.includes(EICAR_SIGNATURE)) {\n return {\n isClean: false,\n detectedViruses: [\"EICAR-Test-File\"],\n };\n }\n\n // All other files are considered clean\n return {\n isClean: true,\n detectedViruses: [],\n };\n }),\n getVersion: () =>\n Effect.sync(() => {\n return \"TestVirusScanPlugin 1.0.0\";\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ZipPlugin } from \"../flow\";\n\n/**\n * Mock ZipPlugin implementation for testing.\n *\n * Provides a simple in-memory implementation that creates mock zip data\n * by serializing file metadata as JSON.\n *\n * @example\n * ```typescript\n * import { TestZipPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const zipPlugin = yield* ZipPlugin;\n * const zipData = yield* zipPlugin.zip(inputs, options);\n * return zipData;\n * }).pipe(Effect.provide(TestZipPlugin));\n * ```\n */\nexport const TestZipPlugin = Layer.succeed(\n ZipPlugin,\n ZipPlugin.of({\n zip: (inputs, options) =>\n Effect.gen(function* () {\n // Create mock zip data\n const files = inputs.map((input) => ({\n id: input.id,\n size: input.data.byteLength,\n }));\n\n const zipContent = JSON.stringify({\n zipName: options.zipName,\n includeMetadata: options.includeMetadata,\n files,\n });\n\n return new TextEncoder().encode(zipContent);\n }),\n }),\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["chunks: Uint8Array[]","duration: number"],"sources":["../../src/testing/mock-document-ai-plugin.ts","../../src/testing/mock-document-plugin.ts","../../src/testing/mock-image-ai-plugin.ts","../../src/testing/mock-image-plugin.ts","../../src/testing/mock-upload-engine.ts","../../src/testing/mock-video-plugin.ts","../../src/testing/mock-virus-scan-plugin.ts","../../src/testing/mock-zip-plugin.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport type { OcrResult } from \"../flow\";\nimport { DocumentAiPlugin } from \"../flow\";\n\n/**\n * Mock DocumentAiPlugin implementation for testing.\n *\n * Provides simple mock implementations of AI document operations.\n *\n * @example\n * ```typescript\n * import { TestDocumentAiPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* DocumentAiPlugin;\n * const result = yield* plugin.performOCR(\n * \"https://example.com/doc.pdf\",\n * { taskType: \"convertToMarkdown\", resolution: \"gundam\" },\n * { clientId: \"test-client\" }\n * );\n * return result;\n * }).pipe(Effect.provide(TestDocumentAiPlugin));\n * ```\n */\nexport const TestDocumentAiPlugin = Layer.succeed(\n DocumentAiPlugin,\n DocumentAiPlugin.of({\n performOCR: (inputUrl: string, params, context) =>\n Effect.sync(() => {\n const result: OcrResult = {\n extractedText:\n params.taskType === \"convertToMarkdown\"\n ? \"# Document Title\\n\\nThis is a paragraph with **bold** text.\\n\\n## Section 2\\n\\n- List item 1\\n- List item 2\"\n : \"Plain text extracted from document without formatting.\",\n format:\n params.taskType === \"convertToMarkdown\" ? \"markdown\" : \"plain\",\n confidence: 0.95,\n };\n return result;\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport type { DocumentMetadata, SplitPdfResult } from \"../flow\";\nimport { DocumentPlugin } from \"../flow\";\n\n/**\n * Mock DocumentPlugin implementation for testing.\n *\n * Provides simple mock implementations of PDF operations that return mock data.\n *\n * @example\n * ```typescript\n * import { TestDocumentPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* DocumentPlugin;\n * const text = yield* plugin.extractText(pdfBytes);\n * return text;\n * }).pipe(Effect.provide(TestDocumentPlugin));\n * ```\n */\nexport const TestDocumentPlugin = Layer.succeed(\n DocumentPlugin,\n DocumentPlugin.of({\n extractText: (input: Uint8Array) =>\n Effect.sync(() => {\n // Mock text extraction\n return \"This is extracted text from a PDF document.\\nPage 1 content.\";\n }),\n splitPdf: (input: Uint8Array, options) =>\n Effect.sync(() => {\n if (options.mode === \"range\") {\n // Mock range split\n const mockPdf = new Uint8Array(500).fill(80);\n return {\n mode: \"range\" as const,\n pdf: mockPdf,\n } satisfies SplitPdfResult;\n }\n // Mock individual split\n const mockPdfs = [\n new Uint8Array(200).fill(81),\n new Uint8Array(200).fill(82),\n new Uint8Array(200).fill(83),\n ];\n return {\n mode: \"individual\" as const,\n pdfs: mockPdfs,\n } satisfies SplitPdfResult;\n }),\n mergePdfs: (options) =>\n Effect.sync(() => {\n // Mock merge: combine sizes\n const totalSize = options.pdfs.reduce(\n (sum, pdf) => sum + pdf.byteLength,\n 0,\n );\n return new Uint8Array(totalSize).fill(90);\n }),\n getMetadata: (input: Uint8Array) =>\n Effect.sync(() => {\n const metadata: DocumentMetadata = {\n pageCount: 5,\n format: \"pdf\",\n author: \"Test Author\",\n title: \"Test Document\",\n subject: \"Test Subject\",\n creator: \"Test Creator\",\n creationDate: \"2024-01-01T00:00:00Z\",\n modifiedDate: \"2024-01-02T00:00:00Z\",\n fileSize: input.byteLength,\n };\n return metadata;\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ImageAiPlugin } from \"../flow\";\n\n/**\n * Mock ImageAiPlugin implementation for testing.\n *\n * Provides simple mock implementations of AI-powered image operations\n * like background removal and image description.\n *\n * @example\n * ```typescript\n * import { TestImageAiPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* ImageAiPlugin;\n * const result = yield* plugin.removeBackground(imageUrl, context);\n * return result;\n * }).pipe(Effect.provide(TestImageAiPlugin));\n * ```\n */\nexport const TestImageAiPlugin = Layer.succeed(\n ImageAiPlugin,\n ImageAiPlugin.of({\n removeBackground: (inputUrl: string, _context) =>\n Effect.sync(() => ({\n outputUrl: inputUrl.replace(\".jpg\", \"-no-bg.png\"),\n })),\n describeImage: (inputUrl: string, _context) =>\n Effect.sync(() => ({\n description: `A test image from ${inputUrl}`,\n })),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ImagePlugin } from \"../flow\";\n\n/**\n * Mock ImagePlugin implementation for testing.\n *\n * Provides simple mock implementations of image optimization, resizing,\n * and transformation operations that return mock Uint8Array data.\n *\n * @example\n * ```typescript\n * import { TestImagePlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* ImagePlugin;\n * const optimized = yield* plugin.optimize(imageBytes, { quality: 80, format: \"webp\" });\n * return optimized;\n * }).pipe(Effect.provide(TestImagePlugin));\n * ```\n */\nexport const TestImagePlugin = Layer.succeed(\n ImagePlugin,\n ImagePlugin.of({\n optimize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock optimize: return smaller array for lower quality\n const sizeMultiplier = options.quality / 100;\n const newSize = Math.floor(input.byteLength * sizeMultiplier);\n return new Uint8Array(newSize).fill(128);\n }),\n resize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock resize: return array with size based on dimensions\n const width = options.width || 800;\n const height = options.height || 600;\n const mockSize = Math.floor((width * height) / 10);\n return new Uint8Array(mockSize).fill(100);\n }),\n transform: (input: Uint8Array, transformation) =>\n Effect.sync(() => {\n // Mock transform: modify array based on transformation type\n if (transformation.type === \"rotate\" && transformation.angle === 90) {\n // For 90° rotation, swap dimensions (mock behavior)\n return new Uint8Array(input.byteLength + 10).fill(150);\n }\n if (transformation.type === \"blur\") {\n return new Uint8Array(input.byteLength).fill(180);\n }\n if (transformation.type === \"grayscale\") {\n return new Uint8Array(input.byteLength).fill(128);\n }\n // Default: return modified copy\n return new Uint8Array(input.byteLength).fill(200);\n }),\n }),\n);\n","import { Effect, Layer, Stream } from \"effect\";\nimport type { UploadistaError } from \"../errors\";\nimport type { InputFile, UploadFile, WebSocketConnection } from \"../types\";\nimport {\n type DataStoreCapabilities,\n DEFAULT_STREAMING_CONFIG,\n type StreamingConfig,\n} from \"../types/data-store\";\nimport { UploadEngine } from \"../upload\";\n\n/**\n * Mock UploadEngine implementation for testing.\n *\n * Provides a complete in-memory implementation of all UploadEngine methods\n * suitable for unit and integration tests.\n *\n * @example\n * ```typescript\n * import { TestUploadEngine } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const server = yield* UploadEngine;\n * const upload = yield* server.createUpload(inputFile, \"client-123\");\n * return upload;\n * }).pipe(Effect.provide(TestUploadEngine));\n * ```\n */\nexport const TestUploadEngine = Layer.succeed(\n UploadEngine,\n UploadEngine.of({\n read: (fileId: string, _clientId: string | null) =>\n Effect.sync(() => {\n // Generate mock file data based on fileId\n const text = `Content of file ${fileId}`;\n return new TextEncoder().encode(text);\n }),\n readStream: (\n fileId: string,\n _clientId: string | null,\n config?: StreamingConfig,\n ) =>\n Effect.sync(() => {\n const effectiveConfig = { ...DEFAULT_STREAMING_CONFIG, ...config };\n // Generate mock file data based on fileId\n const text = `Content of file ${fileId}`;\n const fullData = new TextEncoder().encode(text);\n\n // Split data into chunks based on chunkSize\n const chunkSize = effectiveConfig.chunkSize;\n const chunks: Uint8Array[] = [];\n for (let i = 0; i < fullData.length; i += chunkSize) {\n chunks.push(fullData.slice(i, i + chunkSize));\n }\n\n // Return as a stream of chunks\n return Stream.fromIterable(chunks);\n }),\n uploadStream: (\n file: Omit<InputFile, \"size\"> & { size?: number; sizeHint?: number },\n _clientId: string | null,\n stream: Stream.Stream<Uint8Array, UploadistaError>,\n ) =>\n Effect.gen(function* () {\n // Collect stream to calculate total size\n const chunks: Uint8Array[] = [];\n yield* Stream.runForEach(stream, (chunk) =>\n Effect.sync(() => {\n chunks.push(chunk);\n }),\n );\n\n const totalSize = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n\n // Parse existing metadata\n const existingMetadata =\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata || {};\n\n // Extract extension from fileName\n const extension = file.fileName\n ? file.fileName.split(\".\").pop()\n : existingMetadata.extension;\n\n // Create new UploadFile with final size\n const uploadId = `stream-uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n return {\n id: uploadId,\n offset: totalSize,\n size: totalSize,\n storage: {\n id: file.storageId,\n type: \"memory\",\n },\n metadata: {\n ...existingMetadata,\n mimeType: file.type,\n type: file.type,\n \"content-type\": file.type,\n fileName: file.fileName,\n originalName: file.fileName,\n name: file.fileName,\n extension,\n },\n url: `http://test-storage/${uploadId}`,\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n upload: (file, _clientId, stream) =>\n Effect.gen(function* () {\n // Read stream to completion\n const reader = stream.getReader();\n let totalSize = 0;\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = yield* Effect.promise(() => reader.read());\n if (done) break;\n if (value) {\n chunks.push(value);\n totalSize += value.byteLength;\n }\n }\n\n // Parse existing metadata\n const existingMetadata =\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata || {};\n\n // Extract extension from fileName\n const extension = file.fileName\n ? file.fileName.split(\".\").pop()\n : existingMetadata.extension;\n\n // Create new UploadFile with merged metadata\n return {\n id: `uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: totalSize,\n size: totalSize,\n storage: {\n id: file.storageId,\n type: \"memory\",\n },\n metadata: {\n ...existingMetadata,\n // Update with InputFile type and fileName\n mimeType: file.type,\n type: file.type,\n \"content-type\": file.type,\n fileName: file.fileName,\n originalName: file.fileName,\n name: file.fileName,\n extension,\n },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n delete: (_fileId: string, _clientId: string | null) => Effect.void,\n createUpload: (file: InputFile, _clientId: string | null) =>\n Effect.succeed({\n id: `uploaded-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: 0,\n size: 0,\n storage: { id: file.storageId, type: \"memory\" },\n metadata:\n typeof file.metadata === \"string\"\n ? JSON.parse(file.metadata)\n : file.metadata,\n } satisfies UploadFile),\n uploadChunk: (\n uploadId: string,\n _clientId: string | null,\n chunk: ReadableStream,\n ) =>\n Effect.gen(function* () {\n // Read stream to completion\n const reader = chunk.getReader();\n let totalSize = 0;\n const chunks: Uint8Array[] = [];\n\n while (true) {\n const { done, value } = yield* Effect.promise(() => reader.read());\n if (done) break;\n if (value) {\n chunks.push(value);\n totalSize += value.byteLength;\n }\n }\n return {\n id: uploadId,\n offset: totalSize,\n size: totalSize,\n storage: { id: \"test-storage\", type: \"memory\" },\n metadata: { mimeType: \"application/octet-stream\", extension: \"bin\" },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile;\n }),\n getCapabilities: (_storageId: string, _clientId: string | null) =>\n Effect.succeed({\n supportsParallelUploads: true,\n supportsConcatenation: true,\n supportsDeferredLength: true,\n supportsResumableUploads: true,\n supportsTransactionalUploads: false,\n supportsStreamingRead: true,\n supportsStreamingWrite: true,\n maxConcurrentUploads: 10,\n minChunkSize: 5 * 1024 * 1024, // 5MB\n maxChunkSize: 100 * 1024 * 1024, // 100MB\n maxParts: 10000,\n optimalChunkSize: 10 * 1024 * 1024, // 10MB\n requiresOrderedChunks: false,\n requiresMimeTypeValidation: false,\n } satisfies DataStoreCapabilities),\n uploadFromUrl: (\n inputFile: InputFile,\n _clientId: string | null,\n url: string,\n ) =>\n Effect.succeed({\n id: `uploaded-from-url-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n offset: 0,\n size: 0,\n storage: { id: inputFile.storageId, type: \"memory\" },\n metadata:\n typeof inputFile.metadata === \"string\"\n ? JSON.parse(inputFile.metadata)\n : inputFile.metadata,\n url,\n creationDate: new Date().toISOString(),\n } satisfies UploadFile),\n getUpload: (uploadId: string) =>\n Effect.succeed({\n id: uploadId,\n offset: 0,\n size: 1024,\n storage: {\n id: \"test-storage\",\n type: \"memory\",\n },\n metadata: {\n mimeType: \"text/plain\",\n originalName: `file-${uploadId}.txt`,\n extension: \"txt\",\n },\n creationDate: new Date().toISOString(),\n } satisfies UploadFile),\n subscribeToUploadEvents: (\n _uploadId: string,\n _connection: WebSocketConnection,\n ) => Effect.void,\n unsubscribeFromUploadEvents: (_uploadId: string) => Effect.void,\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { VideoPlugin } from \"../flow\";\nimport type { DescribeVideoMetadata } from \"../flow/plugins/types/describe-video-node\";\n\n/**\n * Mock VideoPlugin implementation for testing.\n *\n * Provides simple mock implementations of video processing operations\n * that return mock Uint8Array data without requiring FFmpeg or node-av.\n *\n * @example\n * ```typescript\n * import { TestVideoPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* VideoPlugin;\n * const transcoded = yield* plugin.transcode(videoBytes, { format: \"webm\", codec: \"vp9\" });\n * return transcoded;\n * }).pipe(Effect.provide(TestVideoPlugin));\n * ```\n */\nexport const TestVideoPlugin = Layer.succeed(\n VideoPlugin,\n VideoPlugin.of({\n describe: (input: Uint8Array) =>\n Effect.sync(() => {\n // Mock describe: return fake metadata based on input size\n const metadata: DescribeVideoMetadata = {\n duration: 120, // 2 minutes\n width: 1920,\n height: 1080,\n codec: \"h264\",\n format: \"mp4\",\n bitrate: 5000000, // 5 Mbps\n frameRate: 30,\n aspectRatio: \"16:9\",\n hasAudio: true,\n audioCodec: \"aac\",\n audioBitrate: 128000, // 128 kbps\n size: input.byteLength,\n };\n return metadata;\n }),\n transcode: (_input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock transcode: return modified array\n // Simulate different file sizes for different codecs\n let sizeMultiplier = 1.0;\n if (options.codec === \"vp9\") {\n sizeMultiplier = 0.8; // VP9 is more efficient\n } else if (options.codec === \"h265\") {\n sizeMultiplier = 0.7; // H265 is even more efficient\n }\n\n const newSize = Math.floor(_input.byteLength * sizeMultiplier);\n return new Uint8Array(newSize).fill(42);\n }),\n resize: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock resize: return array with size based on dimensions\n const width = options.width || 1280;\n const height = options.height || 720;\n // Simulate file size roughly proportional to resolution\n const mockSize = Math.floor((width * height) / 50);\n return new Uint8Array(mockSize).fill(84);\n }),\n trim: (_input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock trim: return smaller array based on duration\n let duration: number;\n if (options.duration !== undefined) {\n duration = options.duration;\n } else if (options.endTime !== undefined) {\n duration = options.endTime - options.startTime;\n } else {\n // Assume 120s total duration\n duration = 120 - options.startTime;\n }\n\n // Simulate proportional file size based on duration\n const ratio = duration / 120; // Assuming 120s original\n const newSize = Math.floor(_input.byteLength * ratio);\n return new Uint8Array(newSize).fill(63);\n }),\n extractFrame: (input: Uint8Array, options) =>\n Effect.sync(() => {\n // Mock extractFrame: return image bytes (smaller than video)\n const format = options.format || \"jpeg\";\n // JPEG typically smaller than PNG\n const mockSize = format === \"png\" ? 50000 : 30000;\n return new Uint8Array(mockSize).fill(255);\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { VirusScanPlugin } from \"../flow\";\n\n/**\n * EICAR test file signature (standard antivirus test file)\n * This is a safe, non-malicious string used to test antivirus software\n */\nconst EICAR_SIGNATURE =\n \"X5O!P%@AP[4\\\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\";\n\n/**\n * Mock VirusScanPlugin implementation for testing.\n *\n * Provides a simple mock implementation that:\n * - Detects the EICAR test signature as infected\n * - Treats all other files as clean\n * - Returns mock version information\n *\n * @example\n * ```typescript\n * import { TestVirusScanPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const plugin = yield* VirusScanPlugin;\n * const result = yield* plugin.scan(fileBytes);\n * console.log(result.isClean ? \"Clean\" : \"Infected\");\n * }).pipe(Effect.provide(TestVirusScanPlugin));\n * ```\n */\nexport const TestVirusScanPlugin = Layer.succeed(\n VirusScanPlugin,\n VirusScanPlugin.of({\n scan: (input: Uint8Array) =>\n Effect.sync(() => {\n // Convert bytes to string to check for EICAR signature\n const textDecoder = new TextDecoder();\n const content = textDecoder.decode(input);\n\n // Check if file contains EICAR test signature\n if (content.includes(EICAR_SIGNATURE)) {\n return {\n isClean: false,\n detectedViruses: [\"EICAR-Test-File\"],\n };\n }\n\n // All other files are considered clean\n return {\n isClean: true,\n detectedViruses: [],\n };\n }),\n getVersion: () =>\n Effect.sync(() => {\n return \"TestVirusScanPlugin 1.0.0\";\n }),\n }),\n);\n","import { Effect, Layer } from \"effect\";\nimport { ZipPlugin } from \"../flow\";\n\n/**\n * Mock ZipPlugin implementation for testing.\n *\n * Provides a simple in-memory implementation that creates mock zip data\n * by serializing file metadata as JSON.\n *\n * @example\n * ```typescript\n * import { TestZipPlugin } from \"@uploadista/core/testing\";\n *\n * const program = Effect.gen(function* () {\n * const zipPlugin = yield* ZipPlugin;\n * const zipData = yield* zipPlugin.zip(inputs, options);\n * return zipData;\n * }).pipe(Effect.provide(TestZipPlugin));\n * ```\n */\nexport const TestZipPlugin = Layer.succeed(\n ZipPlugin,\n ZipPlugin.of({\n zip: (inputs, options) =>\n Effect.gen(function* () {\n // Create mock zip data\n const files = inputs.map((input) => ({\n id: input.id,\n size: input.data.byteLength,\n }));\n\n const zipContent = JSON.stringify({\n zipName: options.zipName,\n includeMetadata: options.includeMetadata,\n files,\n });\n\n return new TextEncoder().encode(zipContent);\n }),\n }),\n);\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { $r as UploadEvent, Ai as DataStore, Ar as CircuitBreakerHealthSummary, Bi as UploadStrategy, Br as getHealthResponseFormat, Cr as Middleware, Di as BufferedUploadFileDataStore, Dr as MiddlewareServiceLive, Er as MiddlewareService, Fi as StreamWriteResult, Fr as HealthComponents, Gr as TypedEventEmitter, Hi as isDataStore, Hr as BaseEventEmitterService, Ii as StreamingConfig, Ir as HealthResponse, Jr as flowEventEmitter, Kr as UploadEventEmitter, Li as UploadFileDataStore, Lr as HealthResponseFormat, Mi as DataStoreConfig, Mr as DEFAULT_HEALTH_CHECK_CONFIG, Ni as DataStoreWriteOptions, Nr as DlqHealthSummary, Oi as DEFAULT_MULTIPART_PART_SIZE, Or as InputFile, Pi as StreamWriteOptions, Pr as HealthCheckConfig, Qr as webSocketMessageSchema, Ri as UploadFileDataStores, Rr as HealthStatus, Tr as MiddlewareNext, Ur as EventEmitter, Vi as createDataStoreLayer, Vr as BaseEventEmitter, Wr as FlowEventEmitter, Xr as WebSocketConnection, Yr as uploadEventEmitter, Zr as WebSocketMessage, _o as UploadFile, ao as createInitialCircuitBreakerState, bo as uploadFileSchema, co as DeadLetterQueueKVStore, do as TypedKvStore, ei as UploadEventType, eo as CircuitBreakerStateData, fo as UploadFileKVStore, go as uploadFileKvStore, ho as jsonSerializer, io as CircuitBreakerStoreService, ji as DataStoreCapabilities, jr as ComponentHealth, ki as DEFAULT_STREAMING_CONFIG, kr as inputFileSchema, lo as FlowJobKVStore, mo as flowJobKvStore, ni as EventBroadcaster, no as CircuitBreakerStats, oo as BaseKvStore, po as deadLetterQueueKvStore, qr as eventToMessageSerializer, ri as EventBroadcasterService, ro as CircuitBreakerStore, so as BaseKvStoreService, ti as uploadEventSchema, to as CircuitBreakerStateValue, uo as KvStore, vo as UploadFileTraceContext, wr as MiddlewareContext, yo as traceContextSchema, zi as UploadFileDataStoresShape, zr as formatHealthAsText } from "../index-Dim9X1-G.cjs";
1
+ import { Ai as DataStore, Ar as uploadEventEmitter, Bi as UploadStrategy, Cr as BaseEventEmitterService, Di as BufferedUploadFileDataStore, Dr as UploadEventEmitter, Er as TypedEventEmitter, Fi as StreamWriteResult, Fr as UploadEventType, Hi as isDataStore, Ii as StreamingConfig, Ir as uploadEventSchema, Li as UploadFileDataStore, Lr as EventBroadcaster, Mi as DataStoreConfig, Mr as WebSocketMessage, Ni as DataStoreWriteOptions, Nr as webSocketMessageSchema, Oi as DEFAULT_MULTIPART_PART_SIZE, Or as eventToMessageSerializer, Pi as StreamWriteOptions, Pr as UploadEvent, Ri as UploadFileDataStores, Rr as EventBroadcasterService, Sr as BaseEventEmitter, Tr as FlowEventEmitter, Vi as createDataStoreLayer, _o as UploadFile, _r as HealthResponse, ao as createInitialCircuitBreakerState, ar as MiddlewareContext, bo as uploadFileSchema, br as formatHealthAsText, co as DeadLetterQueueKVStore, cr as MiddlewareServiceLive, do as TypedKvStore, dr as CircuitBreakerHealthSummary, eo as CircuitBreakerStateData, fo as UploadFileKVStore, fr as ComponentHealth, go as uploadFileKvStore, gr as HealthComponents, ho as jsonSerializer, hr as HealthCheckConfig, io as CircuitBreakerStoreService, ir as Middleware, ji as DataStoreCapabilities, jr as WebSocketConnection, ki as DEFAULT_STREAMING_CONFIG, kr as flowEventEmitter, lo as FlowJobKVStore, lr as InputFile, mo as flowJobKvStore, mr as DlqHealthSummary, no as CircuitBreakerStats, oo as BaseKvStore, or as MiddlewareNext, po as deadLetterQueueKvStore, pr as DEFAULT_HEALTH_CHECK_CONFIG, ro as CircuitBreakerStore, so as BaseKvStoreService, sr as MiddlewareService, to as CircuitBreakerStateValue, uo as KvStore, ur as inputFileSchema, vo as UploadFileTraceContext, vr as HealthResponseFormat, wr as EventEmitter, xr as getHealthResponseFormat, yo as traceContextSchema, yr as HealthStatus, zi as UploadFileDataStoresShape } from "../index-BtDyiX5-.cjs";
2
2
  export { BaseEventEmitter, BaseEventEmitterService, BaseKvStore, BaseKvStoreService, BufferedUploadFileDataStore, CircuitBreakerHealthSummary, CircuitBreakerStateData, CircuitBreakerStateValue, CircuitBreakerStats, CircuitBreakerStore, CircuitBreakerStoreService, ComponentHealth, DEFAULT_HEALTH_CHECK_CONFIG, DEFAULT_MULTIPART_PART_SIZE, DEFAULT_STREAMING_CONFIG, DataStore, DataStoreCapabilities, DataStoreConfig, DataStoreWriteOptions, DeadLetterQueueKVStore, DlqHealthSummary, EventBroadcaster, EventBroadcasterService, EventEmitter, FlowEventEmitter, FlowJobKVStore, HealthCheckConfig, HealthComponents, HealthResponse, HealthResponseFormat, HealthStatus, InputFile, KvStore, Middleware, MiddlewareContext, MiddlewareNext, MiddlewareService, MiddlewareServiceLive, StreamWriteOptions, StreamWriteResult, StreamingConfig, TypedEventEmitter, TypedKvStore, UploadEvent, UploadEventEmitter, UploadEventType, UploadFile, UploadFileDataStore, UploadFileDataStores, UploadFileDataStoresShape, UploadFileKVStore, UploadFileTraceContext, UploadStrategy, WebSocketConnection, WebSocketMessage, createDataStoreLayer, createInitialCircuitBreakerState, deadLetterQueueKvStore, eventToMessageSerializer, flowEventEmitter, flowJobKvStore, formatHealthAsText, getHealthResponseFormat, inputFileSchema, isDataStore, jsonSerializer, traceContextSchema, uploadEventEmitter, uploadEventSchema, uploadFileKvStore, uploadFileSchema, webSocketMessageSchema };
@@ -1,6 +1,6 @@
1
1
  import "../uploadista-error-DR0XimpE.mjs";
2
2
  import "../index-C-svZlpj.mjs";
3
- import { $r as UploadEvent, Ai as DataStore, Ar as CircuitBreakerHealthSummary, Bi as UploadStrategy, Br as getHealthResponseFormat, Cr as Middleware, Di as BufferedUploadFileDataStore, Dr as MiddlewareServiceLive, Er as MiddlewareService, Fi as StreamWriteResult, Fr as HealthComponents, Gr as TypedEventEmitter, Hi as isDataStore, Hr as BaseEventEmitterService, Ii as StreamingConfig, Ir as HealthResponse, Jr as flowEventEmitter, Kr as UploadEventEmitter, Li as UploadFileDataStore, Lr as HealthResponseFormat, Mi as DataStoreConfig, Mr as DEFAULT_HEALTH_CHECK_CONFIG, Ni as DataStoreWriteOptions, Nr as DlqHealthSummary, Oi as DEFAULT_MULTIPART_PART_SIZE, Or as InputFile, Pi as StreamWriteOptions, Pr as HealthCheckConfig, Qr as webSocketMessageSchema, Ri as UploadFileDataStores, Rr as HealthStatus, Tr as MiddlewareNext, Ur as EventEmitter, Vi as createDataStoreLayer, Vr as BaseEventEmitter, Wr as FlowEventEmitter, Xr as WebSocketConnection, Yr as uploadEventEmitter, Zr as WebSocketMessage, _o as UploadFile, ao as createInitialCircuitBreakerState, bo as uploadFileSchema, co as DeadLetterQueueKVStore, do as TypedKvStore, ei as UploadEventType, eo as CircuitBreakerStateData, fo as UploadFileKVStore, go as uploadFileKvStore, ho as jsonSerializer, io as CircuitBreakerStoreService, ji as DataStoreCapabilities, jr as ComponentHealth, ki as DEFAULT_STREAMING_CONFIG, kr as inputFileSchema, lo as FlowJobKVStore, mo as flowJobKvStore, ni as EventBroadcaster, no as CircuitBreakerStats, oo as BaseKvStore, po as deadLetterQueueKvStore, qr as eventToMessageSerializer, ri as EventBroadcasterService, ro as CircuitBreakerStore, so as BaseKvStoreService, ti as uploadEventSchema, to as CircuitBreakerStateValue, uo as KvStore, vo as UploadFileTraceContext, wr as MiddlewareContext, yo as traceContextSchema, zi as UploadFileDataStoresShape, zr as formatHealthAsText } from "../index-Bhlv8wF9.mjs";
3
+ import { Ai as DataStore, Ar as uploadEventEmitter, Bi as UploadStrategy, Cr as BaseEventEmitterService, Di as BufferedUploadFileDataStore, Dr as UploadEventEmitter, Er as TypedEventEmitter, Fi as StreamWriteResult, Fr as UploadEventType, Hi as isDataStore, Ii as StreamingConfig, Ir as uploadEventSchema, Li as UploadFileDataStore, Lr as EventBroadcaster, Mi as DataStoreConfig, Mr as WebSocketMessage, Ni as DataStoreWriteOptions, Nr as webSocketMessageSchema, Oi as DEFAULT_MULTIPART_PART_SIZE, Or as eventToMessageSerializer, Pi as StreamWriteOptions, Pr as UploadEvent, Ri as UploadFileDataStores, Rr as EventBroadcasterService, Sr as BaseEventEmitter, Tr as FlowEventEmitter, Vi as createDataStoreLayer, _o as UploadFile, _r as HealthResponse, ao as createInitialCircuitBreakerState, ar as MiddlewareContext, bo as uploadFileSchema, br as formatHealthAsText, co as DeadLetterQueueKVStore, cr as MiddlewareServiceLive, do as TypedKvStore, dr as CircuitBreakerHealthSummary, eo as CircuitBreakerStateData, fo as UploadFileKVStore, fr as ComponentHealth, go as uploadFileKvStore, gr as HealthComponents, ho as jsonSerializer, hr as HealthCheckConfig, io as CircuitBreakerStoreService, ir as Middleware, ji as DataStoreCapabilities, jr as WebSocketConnection, ki as DEFAULT_STREAMING_CONFIG, kr as flowEventEmitter, lo as FlowJobKVStore, lr as InputFile, mo as flowJobKvStore, mr as DlqHealthSummary, no as CircuitBreakerStats, oo as BaseKvStore, or as MiddlewareNext, po as deadLetterQueueKvStore, pr as DEFAULT_HEALTH_CHECK_CONFIG, ro as CircuitBreakerStore, so as BaseKvStoreService, sr as MiddlewareService, to as CircuitBreakerStateValue, uo as KvStore, ur as inputFileSchema, vo as UploadFileTraceContext, vr as HealthResponseFormat, wr as EventEmitter, xr as getHealthResponseFormat, yo as traceContextSchema, yr as HealthStatus, zi as UploadFileDataStoresShape } from "../index-XXHmCYAu.mjs";
4
4
  import "../index-B9V5SSxl.mjs";
5
5
  import "../index-BFSHumky.mjs";
6
6
  export { BaseEventEmitter, BaseEventEmitterService, BaseKvStore, BaseKvStoreService, BufferedUploadFileDataStore, CircuitBreakerHealthSummary, CircuitBreakerStateData, CircuitBreakerStateValue, CircuitBreakerStats, CircuitBreakerStore, CircuitBreakerStoreService, ComponentHealth, DEFAULT_HEALTH_CHECK_CONFIG, DEFAULT_MULTIPART_PART_SIZE, DEFAULT_STREAMING_CONFIG, DataStore, DataStoreCapabilities, DataStoreConfig, DataStoreWriteOptions, DeadLetterQueueKVStore, DlqHealthSummary, EventBroadcaster, EventBroadcasterService, EventEmitter, FlowEventEmitter, FlowJobKVStore, HealthCheckConfig, HealthComponents, HealthResponse, HealthResponseFormat, HealthStatus, InputFile, KvStore, Middleware, MiddlewareContext, MiddlewareNext, MiddlewareService, MiddlewareServiceLive, StreamWriteOptions, StreamWriteResult, StreamingConfig, TypedEventEmitter, TypedKvStore, UploadEvent, UploadEventEmitter, UploadEventType, UploadFile, UploadFileDataStore, UploadFileDataStores, UploadFileDataStoresShape, UploadFileKVStore, UploadFileTraceContext, UploadStrategy, WebSocketConnection, WebSocketMessage, createDataStoreLayer, createInitialCircuitBreakerState, deadLetterQueueKvStore, eventToMessageSerializer, flowEventEmitter, flowJobKvStore, formatHealthAsText, getHealthResponseFormat, inputFileSchema, isDataStore, jsonSerializer, traceContextSchema, uploadEventEmitter, uploadEventSchema, uploadFileKvStore, uploadFileSchema, webSocketMessageSchema };
@@ -1 +1 @@
1
- require(`../types-Cws60JHC.cjs`),require(`../uploadista-error-BgQU45we.cjs`),require(`../errors-CRm1FHHT.cjs`);const e=require(`../upload-BHDuuJ80.cjs`);require(`../checksum-DVPe3Db4.cjs`),require(`../stream-limiter-BvkaZXcz.cjs`),exports.UploadServer=e.n,exports.UploadStrategyNegotiator=e.t,exports.compareMimeTypes=e.s,exports.createUploadServer=e.r,exports.detectMimeType=e.c,exports.uploadServer=e.i;
1
+ require(`../types-Cws60JHC.cjs`),require(`../uploadista-error-BgQU45we.cjs`),require(`../errors-CRm1FHHT.cjs`);const e=require(`../upload-DWBlRXHh.cjs`);require(`../checksum-DVPe3Db4.cjs`),require(`../stream-limiter-BvkaZXcz.cjs`),exports.UploadEngine=e.n,exports.UploadStrategyNegotiator=e.t,exports.compareMimeTypes=e.s,exports.createUploadEngine=e.r,exports.detectMimeType=e.c,exports.uploadEngine=e.i;
@@ -1,2 +1,2 @@
1
- import { Sr as detectMimeType, _r as UploadServerOptions, br as uploadServer, gr as UploadServer, hr as UploadStrategyOptions, mr as UploadStrategyNegotiator, pr as NegotiatedStrategy, vr as UploadServerShape, xr as compareMimeTypes, yr as createUploadServer } from "../index-Dim9X1-G.cjs";
2
- export { NegotiatedStrategy, UploadServer, UploadServerOptions, UploadServerShape, UploadStrategyNegotiator, UploadStrategyOptions, compareMimeTypes, createUploadServer, detectMimeType, uploadServer };
1
+ import { $n as UploadEngineShape, Jn as NegotiatedStrategy, Qn as UploadEngineOptions, Xn as UploadStrategyOptions, Yn as UploadStrategyNegotiator, Zn as UploadEngine, er as createUploadEngine, nr as compareMimeTypes, rr as detectMimeType, tr as uploadEngine } from "../index-BtDyiX5-.cjs";
2
+ export { NegotiatedStrategy, UploadEngine, UploadEngineOptions, UploadEngineShape, UploadStrategyNegotiator, UploadStrategyOptions, compareMimeTypes, createUploadEngine, detectMimeType, uploadEngine };
@@ -1,6 +1,6 @@
1
1
  import "../uploadista-error-DR0XimpE.mjs";
2
2
  import "../index-C-svZlpj.mjs";
3
- import { Sr as detectMimeType, _r as UploadServerOptions, br as uploadServer, gr as UploadServer, hr as UploadStrategyOptions, mr as UploadStrategyNegotiator, pr as NegotiatedStrategy, vr as UploadServerShape, xr as compareMimeTypes, yr as createUploadServer } from "../index-Bhlv8wF9.mjs";
3
+ import { $n as UploadEngineShape, Jn as NegotiatedStrategy, Qn as UploadEngineOptions, Xn as UploadStrategyOptions, Yn as UploadStrategyNegotiator, Zn as UploadEngine, er as createUploadEngine, nr as compareMimeTypes, rr as detectMimeType, tr as uploadEngine } from "../index-XXHmCYAu.mjs";
4
4
  import "../index-B9V5SSxl.mjs";
5
5
  import "../index-BFSHumky.mjs";
6
- export { NegotiatedStrategy, UploadServer, UploadServerOptions, UploadServerShape, UploadStrategyNegotiator, UploadStrategyOptions, compareMimeTypes, createUploadServer, detectMimeType, uploadServer };
6
+ export { NegotiatedStrategy, UploadEngine, UploadEngineOptions, UploadEngineShape, UploadStrategyNegotiator, UploadStrategyOptions, compareMimeTypes, createUploadEngine, detectMimeType, uploadEngine };
@@ -1 +1 @@
1
- import"../uploadista-error-CkSxSyNo.mjs";import"../errors-CtPUOWNd.mjs";import"../types-DKGQJIEr.mjs";import{c as e,i as t,n,r,s as i,t as a}from"../upload-tLC7uR9U.mjs";import"../checksum-COoD-F1l.mjs";import"../stream-limiter-B9nsn2gb.mjs";export{n as UploadServer,a as UploadStrategyNegotiator,i as compareMimeTypes,r as createUploadServer,e as detectMimeType,t as uploadServer};
1
+ import"../uploadista-error-CkSxSyNo.mjs";import"../errors-CtPUOWNd.mjs";import"../types-DKGQJIEr.mjs";import{c as e,i as t,n,r,s as i,t as a}from"../upload-C-C7hn1-.mjs";import"../checksum-COoD-F1l.mjs";import"../stream-limiter-B9nsn2gb.mjs";export{n as UploadEngine,a as UploadStrategyNegotiator,i as compareMimeTypes,r as createUploadEngine,e as detectMimeType,t as uploadEngine};
@@ -1,2 +1,2 @@
1
- import{n as e}from"./uploadista-error-CkSxSyNo.mjs";import{N as t,S as n,n as r,p as i}from"./types-DKGQJIEr.mjs";import{r as a,t as o}from"./checksum-COoD-F1l.mjs";import{t as s}from"./stream-limiter-B9nsn2gb.mjs";import{Context as c,Effect as l,Layer as u,Metric as d,MetricBoundaries as f,Option as p,Ref as m,Stream as h,Tracer as g}from"effect";function _(e,t,n=0){return e.length<n+t.length?!1:t.every((t,r)=>e[n+r]===t)}function v(e,t,n=0){if(e.length<n+t.length)return!1;for(let r=0;r<t.length;r++)if(e[n+r]!==t.charCodeAt(r))return!1;return!0}const y=(e,t)=>{if(e.length===0)return`application/octet-stream`;if(_(e,[137,80,78,71,13,10,26,10]))return`image/png`;if(_(e,[255,216,255]))return`image/jpeg`;if(v(e,`GIF87a`)||v(e,`GIF89a`))return`image/gif`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`WEBP`,8))return`image/webp`;if(e.length>=12&&_(e,[0,0,0],0)&&v(e,`ftyp`,4)&&(v(e,`avif`,8)||v(e,`avis`,8)))return`image/avif`;if(e.length>=12&&v(e,`ftyp`,4)&&(v(e,`heic`,8)||v(e,`heif`,8)||v(e,`mif1`,8)))return`image/heic`;if(_(e,[66,77]))return`image/bmp`;if(_(e,[73,73,42,0])||_(e,[77,77,0,42]))return`image/tiff`;if(_(e,[0,0,1,0]))return`image/x-icon`;if(e.length>=5){let t=new TextDecoder(`utf-8`,{fatal:!1}).decode(e.slice(0,Math.min(1024,e.length)));if(t.includes(`<svg`)||t.includes(`<?xml`)&&t.includes(`<svg`))return`image/svg+xml`}if(e.length>=12&&v(e,`ftyp`,4)){let t=new TextDecoder().decode(e.slice(8,12));if(t.startsWith(`mp4`)||t.startsWith(`M4`)||t.startsWith(`isom`))return`video/mp4`}if(_(e,[26,69,223,163]))return`video/webm`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`AVI `,8))return`video/x-msvideo`;if(e.length>=8&&(v(e,`moov`,4)||v(e,`mdat`,4)||v(e,`free`,4)))return`video/quicktime`;if(_(e,[26,69,223,163])&&e.length>=100&&new TextDecoder(`utf-8`,{fatal:!1}).decode(e.slice(0,100)).includes(`matroska`))return`video/x-matroska`;if(_(e,[255,251])||_(e,[255,243])||_(e,[255,242])||v(e,`ID3`))return`audio/mpeg`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`WAVE`,8))return`audio/wav`;if(v(e,`fLaC`))return`audio/flac`;if(v(e,`OggS`))return`audio/ogg`;if(e.length>=12&&v(e,`ftyp`,4)&&v(e,`M4A`,8))return`audio/mp4`;if(v(e,`%PDF`))return`application/pdf`;if(_(e,[80,75,3,4])||_(e,[80,75,5,6])||_(e,[80,75,7,8])){if(e.length>=1024){let t=new TextDecoder(`utf-8`,{fatal:!1}).decode(e);if(t.includes(`word/`))return`application/vnd.openxmlformats-officedocument.wordprocessingml.document`;if(t.includes(`xl/`))return`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`;if(t.includes(`ppt/`))return`application/vnd.openxmlformats-officedocument.presentationml.presentation`}return`application/zip`}if(_(e,[82,97,114,33,26,7]))return`application/x-rar-compressed`;if(_(e,[55,122,188,175,39,28]))return`application/x-7z-compressed`;if(_(e,[31,139]))return`application/gzip`;if(e.length>=262&&v(e,`ustar`,257))return`application/x-tar`;if(v(e,`wOFF`))return`font/woff`;if(v(e,`wOF2`))return`font/woff2`;if(_(e,[0,1,0,0,0]))return`font/ttf`;if(v(e,`OTTO`))return`font/otf`;if(e.length>=1){let t=e[0];if(t===123||t===91)try{let t=new TextDecoder(`utf-8`).decode(e.slice(0,Math.min(1024,e.length)));return JSON.parse(t.trim()),`application/json`}catch{}}if(t)switch(t.split(`.`).pop()?.toLowerCase()){case`jpg`:case`jpeg`:return`image/jpeg`;case`png`:return`image/png`;case`gif`:return`image/gif`;case`webp`:return`image/webp`;case`avif`:return`image/avif`;case`heic`:case`heif`:return`image/heic`;case`bmp`:return`image/bmp`;case`tiff`:case`tif`:return`image/tiff`;case`ico`:return`image/x-icon`;case`svg`:return`image/svg+xml`;case`mp4`:case`m4v`:return`video/mp4`;case`webm`:return`video/webm`;case`avi`:return`video/x-msvideo`;case`mov`:return`video/quicktime`;case`mkv`:return`video/x-matroska`;case`mp3`:return`audio/mpeg`;case`wav`:return`audio/wav`;case`flac`:return`audio/flac`;case`ogg`:return`audio/ogg`;case`m4a`:return`audio/mp4`;case`pdf`:return`application/pdf`;case`docx`:return`application/vnd.openxmlformats-officedocument.wordprocessingml.document`;case`xlsx`:return`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`;case`pptx`:return`application/vnd.openxmlformats-officedocument.presentationml.presentation`;case`zip`:return`application/zip`;case`rar`:return`application/x-rar-compressed`;case`7z`:return`application/x-7z-compressed`;case`gz`:case`gzip`:return`application/gzip`;case`tar`:return`application/x-tar`;case`woff`:return`font/woff`;case`woff2`:return`font/woff2`;case`ttf`:return`font/ttf`;case`otf`:return`font/otf`;case`txt`:return`text/plain`;case`json`:return`application/json`;case`xml`:return`application/xml`;case`html`:case`htm`:return`text/html`;case`css`:return`text/css`;case`js`:return`application/javascript`;case`csv`:return`text/csv`;default:return`application/octet-stream`}return`application/octet-stream`};function b(e,t){return e===t?!0:e.split(`/`)[0]===t.split(`/`)[0]}const x=l.gen(function*(){let e=yield*l.currentSpan.pipe(l.option);return p.match(e,{onNone:()=>void 0,onSome:e=>({traceId:e.traceId,spanId:e.spanId,traceFlags:e.sampled?1:0})})}),S=(e,t,{dataStoreService:n,kvStore:i,eventEmitter:a,generateId:o})=>l.gen(function*(){let s=yield*x,c=new Date().toISOString();return yield*l.gen(function*(){let l=yield*n.getDataStore(e.storageId,t),u=yield*o.generateId(),{size:d,type:f,fileName:p,lastModified:m,metadata:h,flow:g}=e,_={};if(h)try{_=JSON.parse(h)}catch{_={}}let v={..._,type:f,fileName:p??``};m&&(v.lastModified=m.toString());let y={id:u,size:d,metadata:v,offset:0,creationDate:c,storage:{id:e.storageId,type:f,path:``,bucket:l.bucket},flow:g,traceContext:s},b=yield*l.create(y);return yield*i.set(u,b),yield*a.emit(u,{type:r.UPLOAD_STARTED,data:b,flow:b.flow}),b}).pipe(l.withSpan(`upload-create`,{attributes:{"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId,"upload.mime_type":e.type,"upload.has_flow":e.flow?`true`:`false`}}))}).pipe(l.withSpan(`upload`,{attributes:{"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId,"upload.mime_type":e.type,"upload.has_flow":e.flow?`true`:`false`}}),l.tap(e=>l.gen(function*(){if(yield*d.increment(d.counter(`upload_created_total`,{description:`Total number of uploads created`})),e.size){let t=d.histogram(`upload_file_size_bytes`,f.exponential({start:1024,factor:2,count:25}));yield*d.update(t,e.size)}let t=d.gauge(`active_uploads`);yield*d.increment(t)})),l.tap(t=>l.logInfo(`Upload created`).pipe(l.annotateLogs({"upload.id":t.id,"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId}))),l.tapError(t=>l.gen(function*(){yield*l.logError(`Upload creation failed`).pipe(l.annotateLogs({"upload.file_name":e.fileName??`unknown`,"upload.storage_id":e.storageId,error:String(t)})),yield*d.increment(d.counter(`upload_failed_total`,{description:`Total number of uploads that failed`}))})));function C(t){return h.fromReadableStream(()=>t,t=>new e({code:`UNKNOWN_ERROR`,status:500,body:String(t)}))}function w({data:t,upload:n,dataStore:i,maxFileSize:a,controller:o,eventEmitter:c,uploadProgressInterval:u=200}){return l.gen(function*(){let d=C(t);if(o.signal.aborted)return yield*l.fail(e.fromCode(`ABORTED`));let f=new AbortController,{signal:p}=f,h=()=>{f.abort()};return o.signal.addEventListener(`abort`,h,{once:!0}),yield*l.acquireUseRelease(l.sync(()=>({signal:p,onAbort:h})),({signal:t})=>l.gen(function*(){let e=yield*m.make(0),t=s.limit({maxSize:a})(d);return yield*i.write({stream:t,file_id:n.id,offset:n.offset},{onProgress:t=>{let i=Date.now();m.get(e).pipe(l.flatMap(a=>i-a>=u?l.gen(function*(){yield*m.set(e,i),yield*c.emit(n.id,{type:r.UPLOAD_PROGRESS,data:{id:n.id,progress:t,total:n.size??0},flow:n.flow})}):l.void),l.runPromise).catch(()=>{})}})}).pipe(l.catchAll(t=>t instanceof Error&&t.name===`AbortError`?l.fail(e.fromCode(`ABORTED`)):t instanceof e?l.fail(t):l.fail(e.fromCode(`FILE_WRITE_ERROR`,{cause:t})))),({onAbort:e})=>l.sync(()=>{o.signal.removeEventListener(`abort`,e)}))}).pipe(l.withSpan(`upload-write-to-store`,{attributes:{"upload.id":n.id,"upload.offset":n.offset.toString(),"upload.max_file_size":a.toString(),"upload.file_size":n.size?.toString()??`0`}}),l.tap(e=>l.logDebug(`Data written to store`).pipe(l.annotateLogs({"upload.id":n.id,"write.offset":e.toString(),"write.bytes_written":(e-n.offset).toString()}))),l.tapError(t=>l.logError(`Failed to write to store`).pipe(l.annotateLogs({"upload.id":n.id,"upload.offset":n.offset.toString(),error:t instanceof e?t.code:String(t)}))))}function T(e){return g.externalSpan({traceId:e.traceId,spanId:e.spanId,sampled:e.traceFlags===1})}const E=(e,t)=>{let n=new Date(e.creationDate).getTime(),r=Date.now()-n;return l.void.pipe(l.withSpan(`upload-complete`,{attributes:{"upload.id":e.id,"upload.size":e.size??0,"upload.total_duration_ms":r,"upload.storage_id":e.storage.id,"upload.file_name":e.metadata?.fileName??`unknown`,"upload.creation_date":e.creationDate,"upload.completion_date":new Date().toISOString()},parent:t}))},D=(e,t,n,{dataStoreService:i,kvStore:a,eventEmitter:o})=>l.gen(function*(){let s=yield*a.get(e),c=s.traceContext?T(s.traceContext):void 0;return yield*l.gen(function*(){let c=yield*i.getDataStore(s.storage.id,t);return s.offset=yield*w({dataStore:c,data:n,upload:s,maxFileSize:1e8,controller:new AbortController,uploadProgressInterval:200,eventEmitter:o}),yield*a.set(e,s),yield*o.emit(s.id,{type:r.UPLOAD_PROGRESS,data:{id:s.id,progress:s.offset,total:s.size??0},flow:s.flow}),s.size&&s.offset===s.size&&(yield*O({file:s,dataStore:c,eventEmitter:o}),s.traceContext&&(yield*E(s,T(s.traceContext)))),s}).pipe(l.withSpan(`upload-chunk`,{attributes:{"upload.id":e,"chunk.upload_id":e,"upload.has_trace_context":s.traceContext?`true`:`false`},parent:c}))}).pipe(l.tap(e=>l.gen(function*(){yield*d.increment(d.counter(`chunk_uploaded_total`,{description:`Total number of chunks uploaded`}));let t=e.offset,n=d.histogram(`chunk_size_bytes`,f.linear({start:262144,width:262144,count:20}));if(yield*d.update(n,t),e.size&&e.size>0){let e=t,n=d.gauge(`upload_throughput_bytes_per_second`);yield*d.set(n,e)}})),l.tap(e=>l.logDebug(`Chunk uploaded`).pipe(l.annotateLogs({"upload.id":e.id,"chunk.size":e.offset.toString(),"chunk.progress":e.size&&e.size>0?(e.offset/e.size*100).toFixed(2):`0`,"upload.total_size":e.size?.toString()??`0`}))),l.tapError(t=>l.logError(`Chunk upload failed`).pipe(l.annotateLogs({"upload.id":e,error:String(t)})))),O=({file:t,dataStore:n,eventEmitter:i})=>l.gen(function*(){let a=n.getCapabilities();if(a.maxValidationSize&&t.size&&t.size>a.maxValidationSize){yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_WARNING,data:{id:t.id,message:`File size (${t.size} bytes) exceeds max validation size (${a.maxValidationSize} bytes). Validation skipped.`},flow:t.flow});return}let s=yield*n.read(t.id);if(t.checksum&&t.checksumAlgorithm){let a=yield*o(s,t.checksumAlgorithm);if(a!==t.checksum)return yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_FAILED,data:{id:t.id,reason:`checksum_mismatch`,expected:t.checksum,actual:a},flow:t.flow}),yield*n.remove(t.id),yield*e.fromCode(`CHECKSUM_MISMATCH`,{body:`Checksum validation failed. Expected: ${t.checksum}, Got: ${a}`,details:{uploadId:t.id,expected:t.checksum,actual:a,algorithm:t.checksumAlgorithm}}).toEffect();yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_SUCCESS,data:{id:t.id,validationType:`checksum`,algorithm:t.checksumAlgorithm},flow:t.flow})}if(a.requiresMimeTypeValidation){let a=y(s),o=t.metadata?.type;if(o&&!b(o,a))return yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_FAILED,data:{id:t.id,reason:`mimetype_mismatch`,expected:o,actual:a},flow:t.flow}),yield*n.remove(t.id),yield*e.fromCode(`MIMETYPE_MISMATCH`,{body:`MIME type validation failed. Expected: ${o}, Detected: ${a}`,details:{uploadId:t.id,expected:o,actual:a}}).toEffect();yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_SUCCESS,data:{id:t.id,validationType:`mimetype`},flow:t.flow})}}).pipe(l.withSpan(`validate-upload`,{attributes:{"upload.id":t.id,"validation.checksum_provided":t.checksum?`true`:`false`,"validation.mime_required":n.getCapabilities().requiresMimeTypeValidation?`true`:`false`}})),k=t=>l.tryPromise({try:async()=>await fetch(t),catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}).pipe(l.withSpan(`upload-fetch-url`,{attributes:{"upload.url":t,"upload.operation":`fetch`}}),l.tap(e=>l.gen(function*(){yield*d.increment(d.counter(`upload_from_url_total`,{description:`Total number of URL-based uploads`})),e.ok&&(yield*d.increment(d.counter(`upload_from_url_success_total`,{description:`Total number of successful URL-based uploads`})))})),l.tap(e=>l.logInfo(`URL fetch completed`).pipe(l.annotateLogs({"upload.url":t,"response.status":e.status.toString(),"response.ok":e.ok.toString(),"response.content_length":e.headers.get(`content-length`)??`unknown`}))),l.tapError(e=>l.gen(function*(){yield*d.increment(d.counter(`upload_from_url_failed_total`,{description:`Total number of failed URL-based uploads`})),yield*l.logError(`URL fetch failed`).pipe(l.annotateLogs({"upload.url":t,error:String(e)}))}))),A=t=>l.tryPromise({try:async()=>await t.arrayBuffer(),catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}).pipe(l.withSpan(`upload-convert-to-buffer`,{attributes:{"upload.operation":`arrayBuffer`}}),l.tap(e=>l.logDebug(`Response converted to array buffer`).pipe(l.annotateLogs({"buffer.size":e.byteLength.toString()}))),l.tapError(e=>l.logError(`Failed to convert response to array buffer`).pipe(l.annotateLogs({error:String(e)}))));var j=class extends c.Tag(`UploadServer`)(){};function M(){return l.gen(function*(){let e=yield*t,o=yield*i,s=yield*a,c=yield*n;return{upload:(t,n,r)=>l.gen(function*(){return yield*D((yield*S(t,n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})).id,n,r,{dataStoreService:c,kvStore:e,eventEmitter:o})}),uploadFromUrl:(t,n,r)=>l.gen(function*(){let i=yield*A(yield*k(r)),a=new ReadableStream({start(e){e.enqueue(new Uint8Array(i)),e.close()}});return yield*D((yield*S({...t,size:i.byteLength},n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})).id,n,a,{dataStoreService:c,kvStore:e,eventEmitter:o})}),createUpload:(t,n)=>l.gen(function*(){return yield*S(t,n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})}),uploadChunk:(t,n,r)=>l.gen(function*(){return yield*D(t,n,r,{dataStoreService:c,kvStore:e,eventEmitter:o})}),getUpload:t=>l.gen(function*(){return yield*e.get(t)}),read:(t,n)=>l.gen(function*(){let r=yield*e.get(t);return yield*(yield*c.getDataStore(r.storage.id,n)).read(t)}),readStream:(t,n,r)=>l.gen(function*(){let i=yield*e.get(t),a=yield*c.getDataStore(i.storage.id,n);if(a.getCapabilities().supportsStreamingRead&&a.readStream)return yield*l.logDebug(`Using streaming read for file ${t}`),yield*a.readStream(t,r);yield*l.logDebug(`Falling back to buffered read for file ${t} (streaming not supported)`);let o=yield*a.read(t);return h.succeed(o)}),uploadStream:(t,n,i)=>l.gen(function*(){let a=yield*c.getDataStore(t.storageId,n),u=a.getCapabilities(),d=yield*s.generateId();if(u.supportsStreamingWrite&&a.writeStream){yield*l.logDebug(`Using streaming write for file ${d}`);let n=typeof t.metadata==`string`?JSON.parse(t.metadata):t.metadata||{},s=Object.fromEntries(Object.entries(n).map(([e,t])=>[e,String(t)])),c={id:d,offset:0,size:t.size??0,storage:{id:t.storageId,type:a.getCapabilities().supportsStreamingWrite?`streaming`:`default`},metadata:n,creationDate:new Date().toISOString()};yield*e.set(d,c),yield*o.emit(d,{type:r.UPLOAD_STARTED,data:c});let u=yield*a.writeStream(d,{stream:i,contentType:t.type,sizeHint:t.sizeHint,metadata:s}),f={...c,size:u.size,offset:u.size,storage:{...c.storage,path:u.path},...u.url&&{url:u.url}};return yield*e.set(d,f),yield*o.emit(d,{type:r.UPLOAD_COMPLETE,data:f}),f}yield*l.logWarning(`Falling back to buffered upload for file ${d} (streaming write not supported)`);let f=[];yield*h.runForEach(i,e=>l.sync(()=>{f.push(e)}));let p=f.reduce((e,t)=>e+t.length,0),m=new Uint8Array(p),g=0;for(let e of f)m.set(e,g),g+=e.length;let _=new ReadableStream({start(e){e.enqueue(m),e.close()}});return yield*S({...t,size:p},n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:{generateId:()=>l.succeed(d)}}),yield*D(d,n,_,{dataStoreService:c,kvStore:e,eventEmitter:o})}),delete:(t,n)=>l.gen(function*(){let r=yield*e.get(t);yield*(yield*c.getDataStore(r.storage.id,n)).remove(t),yield*e.delete(t)}),getCapabilities:(e,t)=>l.gen(function*(){return(yield*c.getDataStore(e,t)).getCapabilities()}),subscribeToUploadEvents:(e,t)=>l.gen(function*(){yield*o.subscribe(e,t)}),unsubscribeFromUploadEvents:e=>l.gen(function*(){yield*o.unsubscribe(e)})}})}const N=u.effect(j,M());var P=class{constructor(e,t){this.capabilities=e,this.validateUploadStrategy=t}negotiateStrategy(e){let t=[],n=[],r=`single`,i=e.preferredChunkSize??this.capabilities.optimalChunkSize??1024*1024,a=e.parallelUploads??1;if(e.preferredStrategy&&(this.validateUploadStrategy(e.preferredStrategy)?(r=e.preferredStrategy,t.push(`Using preferred strategy: ${r}`)):n.push(`Preferred strategy '${e.preferredStrategy}' not supported by data store, falling back`)),(!e.preferredStrategy||!this.validateUploadStrategy(e.preferredStrategy))&&(this.capabilities.supportsParallelUploads&&e.fileSize>(e.minChunkSizeForParallel??10*1024*1024)?(r=`parallel`,t.push(`Selected parallel upload for large file (${e.fileSize} bytes)`)):(r=`single`,t.push(this.capabilities.supportsParallelUploads?`Selected single upload for small file (${e.fileSize} bytes)`:`Selected single upload (parallel not supported by data store)`))),this.capabilities.minChunkSize&&i<this.capabilities.minChunkSize&&(n.push(`Chunk size ${i} below minimum ${this.capabilities.minChunkSize}, adjusting`),i=this.capabilities.minChunkSize),this.capabilities.maxChunkSize&&i>this.capabilities.maxChunkSize&&(n.push(`Chunk size ${i} above maximum ${this.capabilities.maxChunkSize}, adjusting`),i=this.capabilities.maxChunkSize),r===`parallel`&&(this.capabilities.maxConcurrentUploads&&a>this.capabilities.maxConcurrentUploads&&(n.push(`Parallel uploads ${a} exceeds maximum ${this.capabilities.maxConcurrentUploads}, adjusting`),a=this.capabilities.maxConcurrentUploads),this.capabilities.maxParts)){let t=Math.ceil(e.fileSize/i);if(t>this.capabilities.maxParts){let r=Math.ceil(e.fileSize/this.capabilities.maxParts);n.push(`Estimated parts ${t} exceeds maximum ${this.capabilities.maxParts}, increasing chunk size`),i=Math.max(i,r)}}return this.validateUploadStrategy(r)||(n.push(`Final strategy validation failed, falling back to single upload`),r=`single`,a=1),t.push(`Data store capabilities: parallel=${this.capabilities.supportsParallelUploads}, concatenation=${this.capabilities.supportsConcatenation}, resumable=${this.capabilities.supportsResumableUploads}`),{strategy:r,chunkSize:i,parallelUploads:r===`parallel`?a:1,reasoning:t,warnings:n}}getDataStoreCapabilities(){return this.capabilities}validateConfiguration(e){let t=[];return e.preferredStrategy&&!this.validateUploadStrategy(e.preferredStrategy)&&t.push(`Preferred strategy '${e.preferredStrategy}' not supported by data store`),e.preferredChunkSize&&(this.capabilities.minChunkSize&&e.preferredChunkSize<this.capabilities.minChunkSize&&t.push(`Chunk size ${e.preferredChunkSize} below data store minimum ${this.capabilities.minChunkSize}`),this.capabilities.maxChunkSize&&e.preferredChunkSize>this.capabilities.maxChunkSize&&t.push(`Chunk size ${e.preferredChunkSize} above data store maximum ${this.capabilities.maxChunkSize}`)),e.parallelUploads&&this.capabilities.maxConcurrentUploads&&e.parallelUploads>this.capabilities.maxConcurrentUploads&&t.push(`Parallel uploads ${e.parallelUploads} exceeds data store maximum ${this.capabilities.maxConcurrentUploads}`),{valid:t.length===0,errors:t}}};export{A as a,y as c,N as i,j as n,k as o,M as r,b as s,P as t};
2
- //# sourceMappingURL=upload-tLC7uR9U.mjs.map
1
+ import{n as e}from"./uploadista-error-CkSxSyNo.mjs";import{N as t,S as n,n as r,p as i}from"./types-DKGQJIEr.mjs";import{r as a,t as o}from"./checksum-COoD-F1l.mjs";import{t as s}from"./stream-limiter-B9nsn2gb.mjs";import{Context as c,Effect as l,Layer as u,Metric as d,MetricBoundaries as f,Option as p,Ref as m,Stream as h,Tracer as g}from"effect";function _(e,t,n=0){return e.length<n+t.length?!1:t.every((t,r)=>e[n+r]===t)}function v(e,t,n=0){if(e.length<n+t.length)return!1;for(let r=0;r<t.length;r++)if(e[n+r]!==t.charCodeAt(r))return!1;return!0}const y=(e,t)=>{if(e.length===0)return`application/octet-stream`;if(_(e,[137,80,78,71,13,10,26,10]))return`image/png`;if(_(e,[255,216,255]))return`image/jpeg`;if(v(e,`GIF87a`)||v(e,`GIF89a`))return`image/gif`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`WEBP`,8))return`image/webp`;if(e.length>=12&&_(e,[0,0,0],0)&&v(e,`ftyp`,4)&&(v(e,`avif`,8)||v(e,`avis`,8)))return`image/avif`;if(e.length>=12&&v(e,`ftyp`,4)&&(v(e,`heic`,8)||v(e,`heif`,8)||v(e,`mif1`,8)))return`image/heic`;if(_(e,[66,77]))return`image/bmp`;if(_(e,[73,73,42,0])||_(e,[77,77,0,42]))return`image/tiff`;if(_(e,[0,0,1,0]))return`image/x-icon`;if(e.length>=5){let t=new TextDecoder(`utf-8`,{fatal:!1}).decode(e.slice(0,Math.min(1024,e.length)));if(t.includes(`<svg`)||t.includes(`<?xml`)&&t.includes(`<svg`))return`image/svg+xml`}if(e.length>=12&&v(e,`ftyp`,4)){let t=new TextDecoder().decode(e.slice(8,12));if(t.startsWith(`mp4`)||t.startsWith(`M4`)||t.startsWith(`isom`))return`video/mp4`}if(_(e,[26,69,223,163]))return`video/webm`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`AVI `,8))return`video/x-msvideo`;if(e.length>=8&&(v(e,`moov`,4)||v(e,`mdat`,4)||v(e,`free`,4)))return`video/quicktime`;if(_(e,[26,69,223,163])&&e.length>=100&&new TextDecoder(`utf-8`,{fatal:!1}).decode(e.slice(0,100)).includes(`matroska`))return`video/x-matroska`;if(_(e,[255,251])||_(e,[255,243])||_(e,[255,242])||v(e,`ID3`))return`audio/mpeg`;if(_(e,[82,73,70,70])&&e.length>=12&&v(e,`WAVE`,8))return`audio/wav`;if(v(e,`fLaC`))return`audio/flac`;if(v(e,`OggS`))return`audio/ogg`;if(e.length>=12&&v(e,`ftyp`,4)&&v(e,`M4A`,8))return`audio/mp4`;if(v(e,`%PDF`))return`application/pdf`;if(_(e,[80,75,3,4])||_(e,[80,75,5,6])||_(e,[80,75,7,8])){if(e.length>=1024){let t=new TextDecoder(`utf-8`,{fatal:!1}).decode(e);if(t.includes(`word/`))return`application/vnd.openxmlformats-officedocument.wordprocessingml.document`;if(t.includes(`xl/`))return`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`;if(t.includes(`ppt/`))return`application/vnd.openxmlformats-officedocument.presentationml.presentation`}return`application/zip`}if(_(e,[82,97,114,33,26,7]))return`application/x-rar-compressed`;if(_(e,[55,122,188,175,39,28]))return`application/x-7z-compressed`;if(_(e,[31,139]))return`application/gzip`;if(e.length>=262&&v(e,`ustar`,257))return`application/x-tar`;if(v(e,`wOFF`))return`font/woff`;if(v(e,`wOF2`))return`font/woff2`;if(_(e,[0,1,0,0,0]))return`font/ttf`;if(v(e,`OTTO`))return`font/otf`;if(e.length>=1){let t=e[0];if(t===123||t===91)try{let t=new TextDecoder(`utf-8`).decode(e.slice(0,Math.min(1024,e.length)));return JSON.parse(t.trim()),`application/json`}catch{}}if(t)switch(t.split(`.`).pop()?.toLowerCase()){case`jpg`:case`jpeg`:return`image/jpeg`;case`png`:return`image/png`;case`gif`:return`image/gif`;case`webp`:return`image/webp`;case`avif`:return`image/avif`;case`heic`:case`heif`:return`image/heic`;case`bmp`:return`image/bmp`;case`tiff`:case`tif`:return`image/tiff`;case`ico`:return`image/x-icon`;case`svg`:return`image/svg+xml`;case`mp4`:case`m4v`:return`video/mp4`;case`webm`:return`video/webm`;case`avi`:return`video/x-msvideo`;case`mov`:return`video/quicktime`;case`mkv`:return`video/x-matroska`;case`mp3`:return`audio/mpeg`;case`wav`:return`audio/wav`;case`flac`:return`audio/flac`;case`ogg`:return`audio/ogg`;case`m4a`:return`audio/mp4`;case`pdf`:return`application/pdf`;case`docx`:return`application/vnd.openxmlformats-officedocument.wordprocessingml.document`;case`xlsx`:return`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`;case`pptx`:return`application/vnd.openxmlformats-officedocument.presentationml.presentation`;case`zip`:return`application/zip`;case`rar`:return`application/x-rar-compressed`;case`7z`:return`application/x-7z-compressed`;case`gz`:case`gzip`:return`application/gzip`;case`tar`:return`application/x-tar`;case`woff`:return`font/woff`;case`woff2`:return`font/woff2`;case`ttf`:return`font/ttf`;case`otf`:return`font/otf`;case`txt`:return`text/plain`;case`json`:return`application/json`;case`xml`:return`application/xml`;case`html`:case`htm`:return`text/html`;case`css`:return`text/css`;case`js`:return`application/javascript`;case`csv`:return`text/csv`;default:return`application/octet-stream`}return`application/octet-stream`};function b(e,t){return e===t?!0:e.split(`/`)[0]===t.split(`/`)[0]}const x=l.gen(function*(){let e=yield*l.currentSpan.pipe(l.option);return p.match(e,{onNone:()=>void 0,onSome:e=>({traceId:e.traceId,spanId:e.spanId,traceFlags:e.sampled?1:0})})}),S=(e,t,{dataStoreService:n,kvStore:i,eventEmitter:a,generateId:o})=>l.gen(function*(){let s=yield*x,c=new Date().toISOString();return yield*l.gen(function*(){let l=yield*n.getDataStore(e.storageId,t),u=yield*o.generateId(),{size:d,type:f,fileName:p,lastModified:m,metadata:h,flow:g}=e,_={};if(h)try{_=JSON.parse(h)}catch{_={}}let v={..._,type:f,fileName:p??``};m&&(v.lastModified=m.toString());let y={id:u,size:d,metadata:v,offset:0,creationDate:c,storage:{id:e.storageId,type:f,path:``,bucket:l.bucket},flow:g,traceContext:s},b=yield*l.create(y);return yield*i.set(u,b),yield*a.emit(u,{type:r.UPLOAD_STARTED,data:b,flow:b.flow}),b}).pipe(l.withSpan(`upload-create`,{attributes:{"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId,"upload.mime_type":e.type,"upload.has_flow":e.flow?`true`:`false`}}))}).pipe(l.withSpan(`upload`,{attributes:{"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId,"upload.mime_type":e.type,"upload.has_flow":e.flow?`true`:`false`}}),l.tap(e=>l.gen(function*(){if(yield*d.increment(d.counter(`upload_created_total`,{description:`Total number of uploads created`})),e.size){let t=d.histogram(`upload_file_size_bytes`,f.exponential({start:1024,factor:2,count:25}));yield*d.update(t,e.size)}let t=d.gauge(`active_uploads`);yield*d.increment(t)})),l.tap(t=>l.logInfo(`Upload created`).pipe(l.annotateLogs({"upload.id":t.id,"upload.file_name":e.fileName??`unknown`,"upload.file_size":e.size?.toString()??`0`,"upload.storage_id":e.storageId}))),l.tapError(t=>l.gen(function*(){yield*l.logError(`Upload creation failed`).pipe(l.annotateLogs({"upload.file_name":e.fileName??`unknown`,"upload.storage_id":e.storageId,error:String(t)})),yield*d.increment(d.counter(`upload_failed_total`,{description:`Total number of uploads that failed`}))})));function C(t){return h.fromReadableStream(()=>t,t=>new e({code:`UNKNOWN_ERROR`,status:500,body:String(t)}))}function w({data:t,upload:n,dataStore:i,maxFileSize:a,controller:o,eventEmitter:c,uploadProgressInterval:u=200}){return l.gen(function*(){let d=C(t);if(o.signal.aborted)return yield*l.fail(e.fromCode(`ABORTED`));let f=new AbortController,{signal:p}=f,h=()=>{f.abort()};return o.signal.addEventListener(`abort`,h,{once:!0}),yield*l.acquireUseRelease(l.sync(()=>({signal:p,onAbort:h})),({signal:t})=>l.gen(function*(){let e=yield*m.make(0),t=s.limit({maxSize:a})(d);return yield*i.write({stream:t,file_id:n.id,offset:n.offset},{onProgress:t=>{let i=Date.now();m.get(e).pipe(l.flatMap(a=>i-a>=u?l.gen(function*(){yield*m.set(e,i),yield*c.emit(n.id,{type:r.UPLOAD_PROGRESS,data:{id:n.id,progress:t,total:n.size??0},flow:n.flow})}):l.void),l.runPromise).catch(()=>{})}})}).pipe(l.catchAll(t=>t instanceof Error&&t.name===`AbortError`?l.fail(e.fromCode(`ABORTED`)):t instanceof e?l.fail(t):l.fail(e.fromCode(`FILE_WRITE_ERROR`,{cause:t})))),({onAbort:e})=>l.sync(()=>{o.signal.removeEventListener(`abort`,e)}))}).pipe(l.withSpan(`upload-write-to-store`,{attributes:{"upload.id":n.id,"upload.offset":n.offset.toString(),"upload.max_file_size":a.toString(),"upload.file_size":n.size?.toString()??`0`}}),l.tap(e=>l.logDebug(`Data written to store`).pipe(l.annotateLogs({"upload.id":n.id,"write.offset":e.toString(),"write.bytes_written":(e-n.offset).toString()}))),l.tapError(t=>l.logError(`Failed to write to store`).pipe(l.annotateLogs({"upload.id":n.id,"upload.offset":n.offset.toString(),error:t instanceof e?t.code:String(t)}))))}function T(e){return g.externalSpan({traceId:e.traceId,spanId:e.spanId,sampled:e.traceFlags===1})}const E=(e,t)=>{let n=new Date(e.creationDate).getTime(),r=Date.now()-n;return l.void.pipe(l.withSpan(`upload-complete`,{attributes:{"upload.id":e.id,"upload.size":e.size??0,"upload.total_duration_ms":r,"upload.storage_id":e.storage.id,"upload.file_name":e.metadata?.fileName??`unknown`,"upload.creation_date":e.creationDate,"upload.completion_date":new Date().toISOString()},parent:t}))},D=(e,t,n,{dataStoreService:i,kvStore:a,eventEmitter:o})=>l.gen(function*(){let s=yield*a.get(e),c=s.traceContext?T(s.traceContext):void 0;return yield*l.gen(function*(){let c=yield*i.getDataStore(s.storage.id,t);return s.offset=yield*w({dataStore:c,data:n,upload:s,maxFileSize:1e8,controller:new AbortController,uploadProgressInterval:200,eventEmitter:o}),yield*a.set(e,s),yield*o.emit(s.id,{type:r.UPLOAD_PROGRESS,data:{id:s.id,progress:s.offset,total:s.size??0},flow:s.flow}),s.size&&s.offset===s.size&&(yield*O({file:s,dataStore:c,eventEmitter:o}),s.traceContext&&(yield*E(s,T(s.traceContext)))),s}).pipe(l.withSpan(`upload-chunk`,{attributes:{"upload.id":e,"chunk.upload_id":e,"upload.has_trace_context":s.traceContext?`true`:`false`},parent:c}))}).pipe(l.tap(e=>l.gen(function*(){yield*d.increment(d.counter(`chunk_uploaded_total`,{description:`Total number of chunks uploaded`}));let t=e.offset,n=d.histogram(`chunk_size_bytes`,f.linear({start:262144,width:262144,count:20}));if(yield*d.update(n,t),e.size&&e.size>0){let e=t,n=d.gauge(`upload_throughput_bytes_per_second`);yield*d.set(n,e)}})),l.tap(e=>l.logDebug(`Chunk uploaded`).pipe(l.annotateLogs({"upload.id":e.id,"chunk.size":e.offset.toString(),"chunk.progress":e.size&&e.size>0?(e.offset/e.size*100).toFixed(2):`0`,"upload.total_size":e.size?.toString()??`0`}))),l.tapError(t=>l.logError(`Chunk upload failed`).pipe(l.annotateLogs({"upload.id":e,error:String(t)})))),O=({file:t,dataStore:n,eventEmitter:i})=>l.gen(function*(){let a=n.getCapabilities();if(a.maxValidationSize&&t.size&&t.size>a.maxValidationSize){yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_WARNING,data:{id:t.id,message:`File size (${t.size} bytes) exceeds max validation size (${a.maxValidationSize} bytes). Validation skipped.`},flow:t.flow});return}let s=yield*n.read(t.id);if(t.checksum&&t.checksumAlgorithm){let a=yield*o(s,t.checksumAlgorithm);if(a!==t.checksum)return yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_FAILED,data:{id:t.id,reason:`checksum_mismatch`,expected:t.checksum,actual:a},flow:t.flow}),yield*n.remove(t.id),yield*e.fromCode(`CHECKSUM_MISMATCH`,{body:`Checksum validation failed. Expected: ${t.checksum}, Got: ${a}`,details:{uploadId:t.id,expected:t.checksum,actual:a,algorithm:t.checksumAlgorithm}}).toEffect();yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_SUCCESS,data:{id:t.id,validationType:`checksum`,algorithm:t.checksumAlgorithm},flow:t.flow})}if(a.requiresMimeTypeValidation){let a=y(s),o=t.metadata?.type;if(o&&!b(o,a))return yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_FAILED,data:{id:t.id,reason:`mimetype_mismatch`,expected:o,actual:a},flow:t.flow}),yield*n.remove(t.id),yield*e.fromCode(`MIMETYPE_MISMATCH`,{body:`MIME type validation failed. Expected: ${o}, Detected: ${a}`,details:{uploadId:t.id,expected:o,actual:a}}).toEffect();yield*i.emit(t.id,{type:r.UPLOAD_VALIDATION_SUCCESS,data:{id:t.id,validationType:`mimetype`},flow:t.flow})}}).pipe(l.withSpan(`validate-upload`,{attributes:{"upload.id":t.id,"validation.checksum_provided":t.checksum?`true`:`false`,"validation.mime_required":n.getCapabilities().requiresMimeTypeValidation?`true`:`false`}})),k=t=>l.tryPromise({try:async()=>await fetch(t),catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}).pipe(l.withSpan(`upload-fetch-url`,{attributes:{"upload.url":t,"upload.operation":`fetch`}}),l.tap(e=>l.gen(function*(){yield*d.increment(d.counter(`upload_from_url_total`,{description:`Total number of URL-based uploads`})),e.ok&&(yield*d.increment(d.counter(`upload_from_url_success_total`,{description:`Total number of successful URL-based uploads`})))})),l.tap(e=>l.logInfo(`URL fetch completed`).pipe(l.annotateLogs({"upload.url":t,"response.status":e.status.toString(),"response.ok":e.ok.toString(),"response.content_length":e.headers.get(`content-length`)??`unknown`}))),l.tapError(e=>l.gen(function*(){yield*d.increment(d.counter(`upload_from_url_failed_total`,{description:`Total number of failed URL-based uploads`})),yield*l.logError(`URL fetch failed`).pipe(l.annotateLogs({"upload.url":t,error:String(e)}))}))),A=t=>l.tryPromise({try:async()=>await t.arrayBuffer(),catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}).pipe(l.withSpan(`upload-convert-to-buffer`,{attributes:{"upload.operation":`arrayBuffer`}}),l.tap(e=>l.logDebug(`Response converted to array buffer`).pipe(l.annotateLogs({"buffer.size":e.byteLength.toString()}))),l.tapError(e=>l.logError(`Failed to convert response to array buffer`).pipe(l.annotateLogs({error:String(e)}))));var j=class extends c.Tag(`UploadEngine`)(){};function M(){return l.gen(function*(){let e=yield*t,o=yield*i,s=yield*a,c=yield*n;return{upload:(t,n,r)=>l.gen(function*(){return yield*D((yield*S(t,n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})).id,n,r,{dataStoreService:c,kvStore:e,eventEmitter:o})}),uploadFromUrl:(t,n,r)=>l.gen(function*(){let i=yield*A(yield*k(r)),a=new ReadableStream({start(e){e.enqueue(new Uint8Array(i)),e.close()}});return yield*D((yield*S({...t,size:i.byteLength},n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})).id,n,a,{dataStoreService:c,kvStore:e,eventEmitter:o})}),createUpload:(t,n)=>l.gen(function*(){return yield*S(t,n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:s})}),uploadChunk:(t,n,r)=>l.gen(function*(){return yield*D(t,n,r,{dataStoreService:c,kvStore:e,eventEmitter:o})}),getUpload:t=>l.gen(function*(){return yield*e.get(t)}),read:(t,n)=>l.gen(function*(){let r=yield*e.get(t);return yield*(yield*c.getDataStore(r.storage.id,n)).read(t)}),readStream:(t,n,r)=>l.gen(function*(){let i=yield*e.get(t),a=yield*c.getDataStore(i.storage.id,n);if(a.getCapabilities().supportsStreamingRead&&a.readStream)return yield*l.logDebug(`Using streaming read for file ${t}`),yield*a.readStream(t,r);yield*l.logDebug(`Falling back to buffered read for file ${t} (streaming not supported)`);let o=yield*a.read(t);return h.succeed(o)}),uploadStream:(t,n,i)=>l.gen(function*(){let a=yield*c.getDataStore(t.storageId,n),u=a.getCapabilities(),d=yield*s.generateId();if(u.supportsStreamingWrite&&a.writeStream){yield*l.logDebug(`Using streaming write for file ${d}`);let n=typeof t.metadata==`string`?JSON.parse(t.metadata):t.metadata||{},s=Object.fromEntries(Object.entries(n).map(([e,t])=>[e,String(t)])),c={id:d,offset:0,size:t.size??0,storage:{id:t.storageId,type:a.getCapabilities().supportsStreamingWrite?`streaming`:`default`},metadata:n,creationDate:new Date().toISOString()};yield*e.set(d,c),yield*o.emit(d,{type:r.UPLOAD_STARTED,data:c});let u=yield*a.writeStream(d,{stream:i,contentType:t.type,sizeHint:t.sizeHint,metadata:s}),f={...c,size:u.size,offset:u.size,storage:{...c.storage,path:u.path},...u.url&&{url:u.url}};return yield*e.set(d,f),yield*o.emit(d,{type:r.UPLOAD_COMPLETE,data:f}),f}yield*l.logWarning(`Falling back to buffered upload for file ${d} (streaming write not supported)`);let f=[];yield*h.runForEach(i,e=>l.sync(()=>{f.push(e)}));let p=f.reduce((e,t)=>e+t.length,0),m=new Uint8Array(p),g=0;for(let e of f)m.set(e,g),g+=e.length;let _=new ReadableStream({start(e){e.enqueue(m),e.close()}});return yield*S({...t,size:p},n,{dataStoreService:c,kvStore:e,eventEmitter:o,generateId:{generateId:()=>l.succeed(d)}}),yield*D(d,n,_,{dataStoreService:c,kvStore:e,eventEmitter:o})}),delete:(t,n)=>l.gen(function*(){let r=yield*e.get(t);yield*(yield*c.getDataStore(r.storage.id,n)).remove(t),yield*e.delete(t)}),getCapabilities:(e,t)=>l.gen(function*(){return(yield*c.getDataStore(e,t)).getCapabilities()}),subscribeToUploadEvents:(e,t)=>l.gen(function*(){yield*o.subscribe(e,t)}),unsubscribeFromUploadEvents:e=>l.gen(function*(){yield*o.unsubscribe(e)})}})}const N=u.effect(j,M());var P=class{constructor(e,t){this.capabilities=e,this.validateUploadStrategy=t}negotiateStrategy(e){let t=[],n=[],r=`single`,i=e.preferredChunkSize??this.capabilities.optimalChunkSize??1024*1024,a=e.parallelUploads??1;if(e.preferredStrategy&&(this.validateUploadStrategy(e.preferredStrategy)?(r=e.preferredStrategy,t.push(`Using preferred strategy: ${r}`)):n.push(`Preferred strategy '${e.preferredStrategy}' not supported by data store, falling back`)),(!e.preferredStrategy||!this.validateUploadStrategy(e.preferredStrategy))&&(this.capabilities.supportsParallelUploads&&e.fileSize>(e.minChunkSizeForParallel??10*1024*1024)?(r=`parallel`,t.push(`Selected parallel upload for large file (${e.fileSize} bytes)`)):(r=`single`,t.push(this.capabilities.supportsParallelUploads?`Selected single upload for small file (${e.fileSize} bytes)`:`Selected single upload (parallel not supported by data store)`))),this.capabilities.minChunkSize&&i<this.capabilities.minChunkSize&&(n.push(`Chunk size ${i} below minimum ${this.capabilities.minChunkSize}, adjusting`),i=this.capabilities.minChunkSize),this.capabilities.maxChunkSize&&i>this.capabilities.maxChunkSize&&(n.push(`Chunk size ${i} above maximum ${this.capabilities.maxChunkSize}, adjusting`),i=this.capabilities.maxChunkSize),r===`parallel`&&(this.capabilities.maxConcurrentUploads&&a>this.capabilities.maxConcurrentUploads&&(n.push(`Parallel uploads ${a} exceeds maximum ${this.capabilities.maxConcurrentUploads}, adjusting`),a=this.capabilities.maxConcurrentUploads),this.capabilities.maxParts)){let t=Math.ceil(e.fileSize/i);if(t>this.capabilities.maxParts){let r=Math.ceil(e.fileSize/this.capabilities.maxParts);n.push(`Estimated parts ${t} exceeds maximum ${this.capabilities.maxParts}, increasing chunk size`),i=Math.max(i,r)}}return this.validateUploadStrategy(r)||(n.push(`Final strategy validation failed, falling back to single upload`),r=`single`,a=1),t.push(`Data store capabilities: parallel=${this.capabilities.supportsParallelUploads}, concatenation=${this.capabilities.supportsConcatenation}, resumable=${this.capabilities.supportsResumableUploads}`),{strategy:r,chunkSize:i,parallelUploads:r===`parallel`?a:1,reasoning:t,warnings:n}}getDataStoreCapabilities(){return this.capabilities}validateConfiguration(e){let t=[];return e.preferredStrategy&&!this.validateUploadStrategy(e.preferredStrategy)&&t.push(`Preferred strategy '${e.preferredStrategy}' not supported by data store`),e.preferredChunkSize&&(this.capabilities.minChunkSize&&e.preferredChunkSize<this.capabilities.minChunkSize&&t.push(`Chunk size ${e.preferredChunkSize} below data store minimum ${this.capabilities.minChunkSize}`),this.capabilities.maxChunkSize&&e.preferredChunkSize>this.capabilities.maxChunkSize&&t.push(`Chunk size ${e.preferredChunkSize} above data store maximum ${this.capabilities.maxChunkSize}`)),e.parallelUploads&&this.capabilities.maxConcurrentUploads&&e.parallelUploads>this.capabilities.maxConcurrentUploads&&t.push(`Parallel uploads ${e.parallelUploads} exceeds data store maximum ${this.capabilities.maxConcurrentUploads}`),{valid:t.length===0,errors:t}}};export{A as a,y as c,N as i,j as n,k as o,M as r,b as s,P as t};
2
+ //# sourceMappingURL=upload-C-C7hn1-.mjs.map