@uploadista/core 0.0.15 → 0.0.16-beta.2

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 (97) hide show
  1. package/dist/{checksum-BaO9w1gC.mjs → checksum-Cwf-Mqw5.mjs} +2 -2
  2. package/dist/{checksum-BaO9w1gC.mjs.map → checksum-Cwf-Mqw5.mjs.map} +1 -1
  3. package/dist/{checksum-DXCv7Avr.cjs → checksum-DIrJRrlk.cjs} +1 -1
  4. package/dist/errors/index.cjs +1 -1
  5. package/dist/errors/index.d.cts +1 -1
  6. package/dist/errors/index.d.mts +1 -1
  7. package/dist/errors/index.mjs +1 -1
  8. package/dist/flow/index.cjs +1 -1
  9. package/dist/flow/index.d.cts +5 -5
  10. package/dist/flow/index.d.mts +5 -5
  11. package/dist/flow/index.mjs +1 -1
  12. package/dist/flow-BtI159Fi.mjs +2 -0
  13. package/dist/flow-BtI159Fi.mjs.map +1 -0
  14. package/dist/flow-DK3kacMQ.cjs +1 -0
  15. package/dist/{index-CdP4c5LF.d.mts → index-8m7lfPuJ.d.mts} +612 -245
  16. package/dist/index-8m7lfPuJ.d.mts.map +1 -0
  17. package/dist/{index-Bu5i-gcV.d.mts → index-BGi1r_fi.d.mts} +2 -2
  18. package/dist/{index-Bu5i-gcV.d.mts.map → index-BGi1r_fi.d.mts.map} +1 -1
  19. package/dist/{index-T6MZvUlM.d.cts → index-B_SvQ0MU.d.cts} +2 -2
  20. package/dist/{index-T6MZvUlM.d.cts.map → index-B_SvQ0MU.d.cts.map} +1 -1
  21. package/dist/{index-3jSHmGwH.d.mts → index-DIWuZlxd.d.mts} +2 -2
  22. package/dist/{index-3jSHmGwH.d.mts.map → index-DIWuZlxd.d.mts.map} +1 -1
  23. package/dist/{index-BmL4G8Qk.d.cts → index-DiKp9dFO.d.cts} +612 -245
  24. package/dist/index-DiKp9dFO.d.cts.map +1 -0
  25. package/dist/{index-CHGBYDtr.d.cts → index-qIN6ULCb.d.cts} +2 -2
  26. package/dist/{index-CHGBYDtr.d.cts.map → index-qIN6ULCb.d.cts.map} +1 -1
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.cts +5 -5
  29. package/dist/index.d.mts +5 -5
  30. package/dist/index.mjs +1 -1
  31. package/dist/{stream-limiter-BcTJAjs-.cjs → stream-limiter-B6dfCtCy.cjs} +1 -1
  32. package/dist/{stream-limiter-D1-sVS5i.mjs → stream-limiter-Dfyh6hbh.mjs} +2 -2
  33. package/dist/{stream-limiter-D1-sVS5i.mjs.map → stream-limiter-Dfyh6hbh.mjs.map} +1 -1
  34. package/dist/streams/index.cjs +1 -1
  35. package/dist/streams/index.d.cts +2 -2
  36. package/dist/streams/index.d.mts +2 -2
  37. package/dist/streams/index.mjs +1 -1
  38. package/dist/testing/index.cjs +1 -1
  39. package/dist/testing/index.d.cts +67 -45
  40. package/dist/testing/index.d.cts.map +1 -1
  41. package/dist/testing/index.d.mts +67 -45
  42. package/dist/testing/index.d.mts.map +1 -1
  43. package/dist/testing/index.mjs +1 -1
  44. package/dist/testing/index.mjs.map +1 -1
  45. package/dist/types/index.cjs +1 -1
  46. package/dist/types/index.d.cts +4 -4
  47. package/dist/types/index.d.mts +4 -4
  48. package/dist/types/index.mjs +1 -1
  49. package/dist/{types-B-EckCWW.cjs → types-B140y5RX.cjs} +1 -1
  50. package/dist/{types-CO-R4pFG.mjs → types-D54Q_YmF.mjs} +2 -2
  51. package/dist/{types-CO-R4pFG.mjs.map → types-D54Q_YmF.mjs.map} +1 -1
  52. package/dist/upload/index.cjs +1 -1
  53. package/dist/upload/index.d.cts +4 -4
  54. package/dist/upload/index.d.mts +4 -4
  55. package/dist/upload/index.mjs +1 -1
  56. package/dist/{upload-C_Ew1NMF.mjs → upload-DDke4PGB.mjs} +2 -2
  57. package/dist/{upload-C_Ew1NMF.mjs.map → upload-DDke4PGB.mjs.map} +1 -1
  58. package/dist/{upload-BwXGQQ26.cjs → upload-DsehAabn.cjs} +1 -1
  59. package/dist/{uploadista-error-Blmj3lpk.cjs → uploadista-error-B9lL5xFQ.cjs} +12 -1
  60. package/dist/{uploadista-error-DgdQnozn.d.cts → uploadista-error-Bb-qIIKM.d.cts} +2 -2
  61. package/dist/uploadista-error-Bb-qIIKM.d.cts.map +1 -0
  62. package/dist/{uploadista-error-Cpn3uBLO.d.mts → uploadista-error-D7Gubrr1.d.mts} +2 -2
  63. package/dist/uploadista-error-D7Gubrr1.d.mts.map +1 -0
  64. package/dist/{uploadista-error-DhNBioWq.mjs → uploadista-error-DR65duXB.mjs} +12 -1
  65. package/dist/uploadista-error-DR65duXB.mjs.map +1 -0
  66. package/dist/utils/index.cjs +1 -1
  67. package/dist/utils/index.d.cts +2 -2
  68. package/dist/utils/index.d.mts +2 -2
  69. package/dist/utils/index.mjs +1 -1
  70. package/dist/{utils-7gziergl.mjs → utils-B6ATFEx5.mjs} +2 -2
  71. package/dist/{utils-7gziergl.mjs.map → utils-B6ATFEx5.mjs.map} +1 -1
  72. package/dist/{utils-C_STf6Wl.cjs → utils-XGw-9f3d.cjs} +1 -1
  73. package/package.json +5 -5
  74. package/src/errors/uploadista-error.ts +56 -1
  75. package/src/flow/flow-server.ts +1 -1
  76. package/src/flow/flow.ts +1 -3
  77. package/src/flow/index.ts +7 -3
  78. package/src/flow/node-types/index.ts +2 -1
  79. package/src/flow/node.ts +95 -78
  80. package/src/flow/nodes/transform-node.ts +2 -1
  81. package/src/flow/plugins/document-ai-plugin.ts +124 -0
  82. package/src/flow/plugins/document-plugin.ts +161 -0
  83. package/src/flow/plugins/plugins.ts +15 -0
  84. package/src/flow/plugins/virus-scan-plugin.ts +129 -0
  85. package/src/flow/type-guards.ts +2 -4
  86. package/src/flow/types/flow-types.ts +3 -1
  87. package/src/testing/index.ts +4 -3
  88. package/src/testing/mock-upload-server.ts +1 -1
  89. package/src/testing/mock-virus-scan-plugin.ts +58 -0
  90. package/dist/flow-DhuIQwjv.mjs +0 -2
  91. package/dist/flow-DhuIQwjv.mjs.map +0 -1
  92. package/dist/flow-s_AlC4r5.cjs +0 -1
  93. package/dist/index-BmL4G8Qk.d.cts.map +0 -1
  94. package/dist/index-CdP4c5LF.d.mts.map +0 -1
  95. package/dist/uploadista-error-Cpn3uBLO.d.mts.map +0 -1
  96. package/dist/uploadista-error-DgdQnozn.d.cts.map +0 -1
  97. package/dist/uploadista-error-DhNBioWq.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { n as UploadistaError } from "./uploadista-error-Cpn3uBLO.mjs";
2
- import { l as GenerateId, p as GenerateIdShape } from "./index-Bu5i-gcV.mjs";
1
+ import { n as UploadistaError } from "./uploadista-error-D7Gubrr1.mjs";
2
+ import { l as GenerateId, p as GenerateIdShape } from "./index-BGi1r_fi.mjs";
3
3
  import { Context, Effect, Layer, Option, Stream } from "effect";
4
4
  import * as zod0 from "zod";
5
5
  import z$1, { z } from "zod";
@@ -2919,201 +2919,6 @@ declare const MiddlewareService_base: Context.TagClass<MiddlewareService, "Middl
2919
2919
  declare class MiddlewareService extends MiddlewareService_base {}
2920
2920
  declare const MiddlewareServiceLive: Layer.Layer<MiddlewareService, never, never>;
2921
2921
  //#endregion
2922
- //#region src/flow/type-guards.d.ts
2923
- /**
2924
- * Factory function to create type guards for specific node types.
2925
- *
2926
- * Creates a TypeScript type guard that validates both the type tag and
2927
- * the data structure against the registered schema. This enables type-safe
2928
- * narrowing of TypedOutput objects in TypeScript.
2929
- *
2930
- * @template T - The expected TypeScript type after narrowing
2931
- * @param typeId - The registered type ID to check against (e.g., "storage-output-v1")
2932
- * @returns A type guard function that narrows TypedOutput to TypedOutput<T>
2933
- *
2934
- * @example
2935
- * ```typescript
2936
- * import { createTypeGuard } from "@uploadista/core/flow";
2937
- * import { z } from "zod";
2938
- *
2939
- * const descriptionSchema = z.object({
2940
- * description: z.string(),
2941
- * confidence: z.number(),
2942
- * });
2943
- *
2944
- * type DescriptionOutput = z.infer<typeof descriptionSchema>;
2945
- *
2946
- * const isDescriptionOutput = createTypeGuard<DescriptionOutput>(
2947
- * "description-output-v1"
2948
- * );
2949
- *
2950
- * // Use in code
2951
- * if (isDescriptionOutput(output)) {
2952
- * // output.data is typed as DescriptionOutput
2953
- * console.log(output.data.description);
2954
- * }
2955
- * ```
2956
- */
2957
- declare function createTypeGuard<T>(typeId: string): (output: TypedOutput) => output is TypedOutput<T>;
2958
- /**
2959
- * Type guard for storage output nodes.
2960
- *
2961
- * Validates that an output is from a storage node and contains valid UploadFile data.
2962
- *
2963
- * @param output - The output to check
2964
- * @returns True if the output is a storage output with valid UploadFile data
2965
- *
2966
- * @example
2967
- * ```typescript
2968
- * import { isStorageOutput } from "@uploadista/core/flow";
2969
- *
2970
- * if (isStorageOutput(output)) {
2971
- * // output.data is typed as UploadFile
2972
- * console.log("File URL:", output.data.url);
2973
- * console.log("File size:", output.data.size);
2974
- * }
2975
- * ```
2976
- */
2977
- declare const isStorageOutput: (output: TypedOutput) => output is TypedOutput<UploadFile>;
2978
- /**
2979
- * Filter an array of outputs to only those matching a specific type.
2980
- *
2981
- * This helper function filters outputs using a type guard and returns a
2982
- * properly typed array of results. It's useful for extracting specific
2983
- * output types from multi-output flows.
2984
- *
2985
- * @template T - The expected output data type
2986
- * @param outputs - Array of typed outputs to filter
2987
- * @param typeGuard - Type guard function to use for filtering
2988
- * @returns Array of outputs that match the type guard, properly typed
2989
- *
2990
- * @example
2991
- * ```typescript
2992
- * import { filterOutputsByType, isStorageOutput } from "@uploadista/core/flow";
2993
- *
2994
- * // Get all storage outputs from a multi-output flow
2995
- * const storageOutputs = filterOutputsByType(
2996
- * flowResult.outputs,
2997
- * isStorageOutput
2998
- * );
2999
- *
3000
- * for (const output of storageOutputs) {
3001
- * // Each output.data is typed as UploadFile
3002
- * console.log("Saved file:", output.data.url);
3003
- * }
3004
- * ```
3005
- */
3006
- declare function filterOutputsByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): TypedOutput<T>[];
3007
- /**
3008
- * Get a single output of a specific type from an array of outputs.
3009
- *
3010
- * This helper function finds exactly one output matching the type guard.
3011
- * It throws an error if no outputs match or if multiple outputs match,
3012
- * ensuring the caller receives exactly the expected result.
3013
- *
3014
- * @template T - The expected output data type
3015
- * @param outputs - Array of typed outputs to search
3016
- * @param typeGuard - Type guard function to use for matching
3017
- * @returns The single matching output, properly typed
3018
- * @throws {UploadistaError} If no outputs match (OUTPUT_NOT_FOUND)
3019
- * @throws {UploadistaError} If multiple outputs match (MULTIPLE_OUTPUTS_FOUND)
3020
- *
3021
- * @example
3022
- * ```typescript
3023
- * import { getSingleOutputByType, isStorageOutput } from "@uploadista/core/flow";
3024
- *
3025
- * try {
3026
- * const storageOutput = getSingleOutputByType(
3027
- * flowResult.outputs,
3028
- * isStorageOutput
3029
- * );
3030
- * // storageOutput.data is typed as UploadFile
3031
- * console.log("File saved at:", storageOutput.data.url);
3032
- * } catch (error) {
3033
- * if (error.code === "OUTPUT_NOT_FOUND") {
3034
- * console.error("No storage output found");
3035
- * } else if (error.code === "MULTIPLE_OUTPUTS_FOUND") {
3036
- * console.error("Multiple storage outputs found, expected one");
3037
- * }
3038
- * }
3039
- * ```
3040
- */
3041
- declare function getSingleOutputByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): Effect.Effect<TypedOutput<T>, UploadistaError>;
3042
- /**
3043
- * Get the first output of a specific type, if any exists.
3044
- *
3045
- * Unlike getSingleOutputByType, this function returns undefined if no outputs
3046
- * match, and returns the first match if multiple outputs exist. This is useful
3047
- * when you want a more lenient matching strategy.
3048
- *
3049
- * @template T - The expected output data type
3050
- * @param outputs - Array of typed outputs to search
3051
- * @param typeGuard - Type guard function to use for matching
3052
- * @returns The first matching output, or undefined if none match
3053
- *
3054
- * @example
3055
- * ```typescript
3056
- * import { getFirstOutputByType, isStorageOutput } from "@uploadista/core/flow";
3057
- *
3058
- * const storageOutput = getFirstOutputByType(
3059
- * flowResult.outputs,
3060
- * isStorageOutput
3061
- * );
3062
- *
3063
- * if (storageOutput) {
3064
- * console.log("First storage output:", storageOutput.data.url);
3065
- * } else {
3066
- * console.log("No storage outputs found");
3067
- * }
3068
- * ```
3069
- */
3070
- declare function getFirstOutputByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): TypedOutput<T> | undefined;
3071
- /**
3072
- * Get an output by its node ID.
3073
- *
3074
- * This helper finds an output produced by a specific node instance,
3075
- * regardless of its type. Useful when you know the specific node ID
3076
- * you're looking for.
3077
- *
3078
- * @param outputs - Array of typed outputs to search
3079
- * @param nodeId - The node ID to match
3080
- * @returns The output from the specified node, or undefined if not found
3081
- *
3082
- * @example
3083
- * ```typescript
3084
- * import { getOutputByNodeId } from "@uploadista/core/flow";
3085
- *
3086
- * const cdnOutput = getOutputByNodeId(flowResult.outputs, "cdn-storage");
3087
- * if (cdnOutput) {
3088
- * console.log("CDN output:", cdnOutput.data);
3089
- * }
3090
- * ```
3091
- */
3092
- declare function getOutputByNodeId(outputs: TypedOutput[], nodeId: string): TypedOutput | undefined;
3093
- /**
3094
- * Check if any outputs match a specific type.
3095
- *
3096
- * Simple predicate function to check if at least one output of a given
3097
- * type exists in the results.
3098
- *
3099
- * @template T - The expected output data type
3100
- * @param outputs - Array of typed outputs to check
3101
- * @param typeGuard - Type guard function to use for checking
3102
- * @returns True if at least one output matches the type guard
3103
- *
3104
- * @example
3105
- * ```typescript
3106
- * import { hasOutputOfType, isStorageOutput } from "@uploadista/core/flow";
3107
- *
3108
- * if (hasOutputOfType(flowResult.outputs, isStorageOutput)) {
3109
- * console.log("Flow produced at least one storage output");
3110
- * } else {
3111
- * console.log("No storage outputs in this flow");
3112
- * }
3113
- * ```
3114
- */
3115
- declare function hasOutputOfType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): boolean;
3116
- //#endregion
3117
2922
  //#region src/upload/mime.d.ts
3118
2923
  /**
3119
2924
  * Detect MIME type from buffer using magic bytes (file signatures).
@@ -3321,7 +3126,7 @@ declare function createUploadServer(): Effect.Effect<{
3321
3126
  getCapabilities: (storageId: string, clientId: string | null) => Effect.Effect<DataStoreCapabilities, UploadistaError, never>;
3322
3127
  subscribeToUploadEvents: (uploadId: string, connection: WebSocketConnection) => Effect.Effect<void, UploadistaError, never>;
3323
3128
  unsubscribeFromUploadEvents: (uploadId: string) => Effect.Effect<void, UploadistaError, never>;
3324
- }, never, GenerateId | UploadEventEmitter | UploadFileDataStores | UploadFileKVStore>;
3129
+ }, never, GenerateId | UploadFileDataStores | UploadFileKVStore | UploadEventEmitter>;
3325
3130
  /**
3326
3131
  * Pre-built UploadServer Effect Layer.
3327
3132
  *
@@ -3352,7 +3157,7 @@ declare function createUploadServer(): Effect.Effect<{
3352
3157
  * }).pipe(Effect.provide(fullUploadSystem));
3353
3158
  * ```
3354
3159
  */
3355
- declare const uploadServer: Layer.Layer<UploadServer, never, GenerateId | UploadEventEmitter | UploadFileDataStores | UploadFileKVStore>;
3160
+ declare const uploadServer: Layer.Layer<UploadServer, never, GenerateId | UploadFileDataStores | UploadFileKVStore | UploadEventEmitter>;
3356
3161
  //#endregion
3357
3162
  //#region src/upload/upload-strategy-negotiator.d.ts
3358
3163
  /**
@@ -3907,8 +3712,8 @@ declare function createFlowServer(): Effect.Effect<{
3907
3712
  cancelFlow: (jobId: string, clientId: string | null) => Effect.Effect<FlowJob, UploadistaError, never>;
3908
3713
  subscribeToFlowEvents: (jobId: string, connection: WebSocketConnection) => Effect.Effect<void, UploadistaError, never>;
3909
3714
  unsubscribeFromFlowEvents: (jobId: string) => Effect.Effect<void, UploadistaError, never>;
3910
- }, never, UploadServer | FlowProvider | FlowJobKVStore | FlowEventEmitter>;
3911
- declare const flowServer: Layer.Layer<FlowServer, never, UploadServer | FlowProvider | FlowJobKVStore | FlowEventEmitter>;
3715
+ }, never, UploadServer | FlowEventEmitter | FlowJobKVStore | FlowProvider>;
3716
+ declare const flowServer: Layer.Layer<FlowServer, never, UploadServer | FlowEventEmitter | FlowJobKVStore | FlowProvider>;
3912
3717
  type FlowServerLayer = typeof flowServer;
3913
3718
  //#endregion
3914
3719
  //#region src/flow/nodes/input-node.d.ts
@@ -4464,75 +4269,327 @@ declare const CredentialProvider_base: Context.TagClass<CredentialProvider, "Cre
4464
4269
  declare class CredentialProvider extends CredentialProvider_base {}
4465
4270
  type CredentialProviderLayer = Layer.Layer<CredentialProvider, never, never>;
4466
4271
  //#endregion
4467
- //#region src/flow/plugins/image-ai-plugin.d.ts
4272
+ //#region src/flow/plugins/document-ai-plugin.d.ts
4468
4273
  /**
4469
- * Context information for AI image processing operations.
4470
- * Contains client identification for tracking and billing purposes.
4274
+ * Context information for AI document processing operations.
4275
+ * Contains client identification and credentials for tracking and billing purposes.
4471
4276
  */
4472
- type ImageAiContext = {
4277
+ type DocumentAiContext = {
4473
4278
  /** Unique identifier for the client making the request, or null if not available */
4474
4279
  clientId: string | null;
4280
+ /** Credential ID for accessing the AI service (e.g., Replicate API key) */
4281
+ credentialId?: string;
4475
4282
  };
4476
4283
  /**
4477
- * Shape definition for the Image AI Plugin interface.
4478
- * Defines the contract that all image AI implementations must follow.
4284
+ * Task types supported by OCR operations.
4479
4285
  */
4480
- type ImageAiPluginShape = {
4286
+ type OcrTaskType = "convertToMarkdown" | "freeOcr" | "parseFigure" | "locateObject";
4287
+ /**
4288
+ * Resolution options for OCR processing.
4289
+ * Higher resolutions provide better accuracy but slower processing.
4290
+ */
4291
+ type OcrResolution = "tiny" | "small" | "base" | "gundam" | "large";
4292
+ /**
4293
+ * Parameters for OCR operations.
4294
+ */
4295
+ type OcrParams = {
4481
4296
  /**
4482
- * Removes the background from an image using AI processing.
4483
- *
4484
- * @param inputUrl - The URL of the input image to process
4485
- * @param context - Context information including client ID for tracking
4486
- * @returns An Effect that resolves to an object containing the output image URL
4487
- * @throws {UploadistaError} When the background removal fails
4297
+ * Type of OCR task to perform.
4298
+ * - "convertToMarkdown": Convert document to structured Markdown
4299
+ * - "freeOcr": Extract all visible text without structure
4300
+ * - "parseFigure": Analyze charts and diagrams
4301
+ * - "locateObject": Find specific content using reference text
4488
4302
  */
4489
- removeBackground: (inputUrl: string, context: ImageAiContext) => Effect.Effect<{
4490
- outputUrl: string;
4491
- }, UploadistaError>;
4303
+ taskType: OcrTaskType;
4492
4304
  /**
4493
- * Generates a textual description of an image using AI analysis.
4305
+ * Resolution size for processing.
4306
+ * Affects speed/accuracy tradeoff.
4307
+ * Default: "gundam" (recommended)
4308
+ */
4309
+ resolution?: OcrResolution;
4310
+ /**
4311
+ * Reference text for object location tasks.
4312
+ * Only used when taskType is "locateObject".
4313
+ */
4314
+ referenceText?: string;
4315
+ };
4316
+ /**
4317
+ * Result of an OCR operation.
4318
+ */
4319
+ type OcrResult = {
4320
+ /**
4321
+ * The extracted text content.
4322
+ */
4323
+ extractedText: string;
4324
+ /**
4325
+ * Format of the extracted text.
4326
+ * - "markdown": Structured markdown format
4327
+ * - "plain": Unstructured plain text
4328
+ * - "structured": Structured analysis (for figures)
4329
+ */
4330
+ format: "markdown" | "plain" | "structured";
4331
+ /**
4332
+ * Confidence score (0-1) if provided by the service.
4333
+ */
4334
+ confidence?: number;
4335
+ };
4336
+ /**
4337
+ * Shape definition for the Document AI Plugin interface.
4338
+ * Defines the contract that all document AI implementations must follow.
4339
+ */
4340
+ type DocumentAiPluginShape = {
4341
+ /**
4342
+ * Performs OCR on a document image or scanned PDF using AI.
4494
4343
  *
4495
- * @param inputUrl - The URL of the input image to analyze
4344
+ * @param inputUrl - The URL of the input document/image to process
4345
+ * @param params - OCR parameters including task type and resolution
4496
4346
  * @param context - Context information including client ID for tracking
4497
- * @returns An Effect that resolves to an object containing the image description
4498
- * @throws {UploadistaError} When the image analysis fails
4347
+ * @returns An Effect that resolves to OcrResult with extracted text
4348
+ * @throws {UploadistaError} When OCR operation fails
4499
4349
  */
4500
- describeImage: (inputUrl: string, context: ImageAiContext) => Effect.Effect<{
4501
- description: string;
4502
- }, UploadistaError>;
4350
+ performOCR: (inputUrl: string, params: OcrParams, context: DocumentAiContext) => Effect.Effect<OcrResult, UploadistaError>;
4503
4351
  };
4504
- declare const ImageAiPlugin_base: Context.TagClass<ImageAiPlugin, "ImageAiPlugin", ImageAiPluginShape>;
4352
+ declare const DocumentAiPlugin_base: Context.TagClass<DocumentAiPlugin, "DocumentAiPlugin", DocumentAiPluginShape>;
4505
4353
  /**
4506
- * Context tag for the Image AI Plugin.
4354
+ * Context tag for the Document AI Plugin.
4507
4355
  *
4508
- * This tag provides a type-safe way to access image AI functionality
4356
+ * This tag provides a type-safe way to access document AI functionality
4509
4357
  * throughout the application using Effect's dependency injection system.
4510
4358
  *
4511
4359
  * @example
4512
4360
  * ```typescript
4513
- * import { ImageAiPlugin } from "@uploadista/core/flow/plugins";
4361
+ * import { DocumentAiPlugin } from "@uploadista/core/flow/plugins";
4514
4362
  *
4515
4363
  * // In your flow node
4516
4364
  * const program = Effect.gen(function* () {
4517
- * const imageAi = yield* ImageAiPlugin;
4518
- * const result = yield* imageAi.removeBackground(imageUrl, { clientId: "user123" });
4519
- * return result.outputUrl;
4365
+ * const documentAi = yield* DocumentAiPlugin;
4366
+ * const result = yield* documentAi.performOCR(
4367
+ * documentUrl,
4368
+ * { taskType: "convertToMarkdown", resolution: "gundam" },
4369
+ * { clientId: "user123" }
4370
+ * );
4371
+ * return result.extractedText;
4520
4372
  * });
4521
4373
  * ```
4522
4374
  */
4523
- declare class ImageAiPlugin extends ImageAiPlugin_base {}
4524
- type ImageAiPluginLayer = Layer.Layer<ImageAiPlugin, never, never>;
4375
+ declare class DocumentAiPlugin extends DocumentAiPlugin_base {}
4376
+ type DocumentAiPluginLayer = Layer.Layer<DocumentAiPlugin, never, never>;
4525
4377
  //#endregion
4526
- //#region src/flow/plugins/types/optimize-node.d.ts
4378
+ //#region src/flow/plugins/document-plugin.d.ts
4527
4379
  /**
4528
- * Zod schema for validating image optimization parameters.
4529
- * Defines the structure and validation rules for image optimization requests.
4380
+ * Parameters for splitting a PDF document.
4530
4381
  */
4531
- declare const optimizeParamsSchema: z.ZodObject<{
4532
- quality: z.ZodNumber;
4533
- format: z.ZodEnum<{
4534
- jpeg: "jpeg";
4535
- webp: "webp";
4382
+ type SplitPdfParams = {
4383
+ /**
4384
+ * Mode of split operation.
4385
+ * - "range": Extract a contiguous range of pages
4386
+ * - "individual": Split into individual single-page PDFs
4387
+ */
4388
+ mode: "range" | "individual";
4389
+ /**
4390
+ * Starting page number (1-indexed).
4391
+ * Only used in "range" mode.
4392
+ */
4393
+ startPage?: number;
4394
+ /**
4395
+ * Ending page number (1-indexed, inclusive).
4396
+ * Only used in "range" mode.
4397
+ */
4398
+ endPage?: number;
4399
+ };
4400
+ /**
4401
+ * Result of a split PDF operation.
4402
+ * In "range" mode, returns a single PDF.
4403
+ * In "individual" mode, returns an array of single-page PDFs.
4404
+ */
4405
+ type SplitPdfResult = {
4406
+ mode: "range";
4407
+ pdf: Uint8Array;
4408
+ } | {
4409
+ mode: "individual";
4410
+ pdfs: Uint8Array[];
4411
+ };
4412
+ /**
4413
+ * Parameters for merging multiple PDF documents.
4414
+ */
4415
+ type MergePdfParams = {
4416
+ /**
4417
+ * Array of PDF documents to merge (in order).
4418
+ */
4419
+ pdfs: Uint8Array[];
4420
+ };
4421
+ /**
4422
+ * Metadata extracted from a PDF document.
4423
+ */
4424
+ type DocumentMetadata = {
4425
+ /**
4426
+ * Total number of pages in the document.
4427
+ */
4428
+ pageCount: number;
4429
+ /**
4430
+ * Document format (e.g., "pdf").
4431
+ */
4432
+ format: string;
4433
+ /**
4434
+ * Author of the document (if available).
4435
+ */
4436
+ author: string | null;
4437
+ /**
4438
+ * Title of the document (if available).
4439
+ */
4440
+ title: string | null;
4441
+ /**
4442
+ * Subject of the document (if available).
4443
+ */
4444
+ subject: string | null;
4445
+ /**
4446
+ * Creator application (if available).
4447
+ */
4448
+ creator: string | null;
4449
+ /**
4450
+ * Creation date in ISO 8601 format (if available).
4451
+ */
4452
+ creationDate: string | null;
4453
+ /**
4454
+ * Last modification date in ISO 8601 format (if available).
4455
+ */
4456
+ modifiedDate: string | null;
4457
+ /**
4458
+ * File size in bytes.
4459
+ */
4460
+ fileSize: number;
4461
+ };
4462
+ /**
4463
+ * Shape definition for the Document Plugin interface.
4464
+ * Defines the contract that all document processing implementations must follow.
4465
+ */
4466
+ type DocumentPluginShape = {
4467
+ /**
4468
+ * Extracts plain text from a searchable PDF document.
4469
+ *
4470
+ * @param input - The input PDF as a Uint8Array
4471
+ * @returns An Effect that resolves to the extracted text as a string
4472
+ * @throws {UploadistaError} When text extraction fails (e.g., PDF_ENCRYPTED, PDF_CORRUPTED)
4473
+ */
4474
+ extractText: (input: Uint8Array) => Effect.Effect<string, UploadistaError>;
4475
+ /**
4476
+ * Splits a PDF document by page range or into individual pages.
4477
+ *
4478
+ * @param input - The input PDF as a Uint8Array
4479
+ * @param options - Split parameters including mode and page range
4480
+ * @returns An Effect that resolves to either a single PDF or array of PDFs
4481
+ * @throws {UploadistaError} When splitting fails (e.g., PAGE_RANGE_INVALID)
4482
+ */
4483
+ splitPdf: (input: Uint8Array, options: SplitPdfParams) => Effect.Effect<SplitPdfResult, UploadistaError>;
4484
+ /**
4485
+ * Merges multiple PDF documents into a single document.
4486
+ *
4487
+ * @param options - Merge parameters including array of PDFs to merge
4488
+ * @returns An Effect that resolves to the merged PDF as a Uint8Array
4489
+ * @throws {UploadistaError} When merging fails
4490
+ */
4491
+ mergePdfs: (options: MergePdfParams) => Effect.Effect<Uint8Array, UploadistaError>;
4492
+ /**
4493
+ * Extracts metadata from a PDF document.
4494
+ *
4495
+ * @param input - The input PDF as a Uint8Array
4496
+ * @returns An Effect that resolves to DocumentMetadata with comprehensive document information
4497
+ * @throws {UploadistaError} When metadata extraction fails
4498
+ */
4499
+ getMetadata: (input: Uint8Array) => Effect.Effect<DocumentMetadata, UploadistaError>;
4500
+ };
4501
+ declare const DocumentPlugin_base: Context.TagClass<DocumentPlugin, "DocumentPlugin", DocumentPluginShape>;
4502
+ /**
4503
+ * Context tag for the Document Plugin.
4504
+ *
4505
+ * This tag provides a type-safe way to access document processing functionality
4506
+ * throughout the application using Effect's dependency injection system.
4507
+ *
4508
+ * @example
4509
+ * ```typescript
4510
+ * import { DocumentPlugin } from "@uploadista/core/flow/plugins";
4511
+ *
4512
+ * // In your flow node
4513
+ * const program = Effect.gen(function* () {
4514
+ * const documentPlugin = yield* DocumentPlugin;
4515
+ * const text = yield* documentPlugin.extractText(pdfData);
4516
+ * const metadata = yield* documentPlugin.getMetadata(pdfData);
4517
+ * return { text, metadata };
4518
+ * });
4519
+ * ```
4520
+ */
4521
+ declare class DocumentPlugin extends DocumentPlugin_base {}
4522
+ type DocumentPluginLayer = Layer.Layer<DocumentPlugin, never, never>;
4523
+ //#endregion
4524
+ //#region src/flow/plugins/image-ai-plugin.d.ts
4525
+ /**
4526
+ * Context information for AI image processing operations.
4527
+ * Contains client identification for tracking and billing purposes.
4528
+ */
4529
+ type ImageAiContext = {
4530
+ /** Unique identifier for the client making the request, or null if not available */
4531
+ clientId: string | null;
4532
+ };
4533
+ /**
4534
+ * Shape definition for the Image AI Plugin interface.
4535
+ * Defines the contract that all image AI implementations must follow.
4536
+ */
4537
+ type ImageAiPluginShape = {
4538
+ /**
4539
+ * Removes the background from an image using AI processing.
4540
+ *
4541
+ * @param inputUrl - The URL of the input image to process
4542
+ * @param context - Context information including client ID for tracking
4543
+ * @returns An Effect that resolves to an object containing the output image URL
4544
+ * @throws {UploadistaError} When the background removal fails
4545
+ */
4546
+ removeBackground: (inputUrl: string, context: ImageAiContext) => Effect.Effect<{
4547
+ outputUrl: string;
4548
+ }, UploadistaError>;
4549
+ /**
4550
+ * Generates a textual description of an image using AI analysis.
4551
+ *
4552
+ * @param inputUrl - The URL of the input image to analyze
4553
+ * @param context - Context information including client ID for tracking
4554
+ * @returns An Effect that resolves to an object containing the image description
4555
+ * @throws {UploadistaError} When the image analysis fails
4556
+ */
4557
+ describeImage: (inputUrl: string, context: ImageAiContext) => Effect.Effect<{
4558
+ description: string;
4559
+ }, UploadistaError>;
4560
+ };
4561
+ declare const ImageAiPlugin_base: Context.TagClass<ImageAiPlugin, "ImageAiPlugin", ImageAiPluginShape>;
4562
+ /**
4563
+ * Context tag for the Image AI Plugin.
4564
+ *
4565
+ * This tag provides a type-safe way to access image AI functionality
4566
+ * throughout the application using Effect's dependency injection system.
4567
+ *
4568
+ * @example
4569
+ * ```typescript
4570
+ * import { ImageAiPlugin } from "@uploadista/core/flow/plugins";
4571
+ *
4572
+ * // In your flow node
4573
+ * const program = Effect.gen(function* () {
4574
+ * const imageAi = yield* ImageAiPlugin;
4575
+ * const result = yield* imageAi.removeBackground(imageUrl, { clientId: "user123" });
4576
+ * return result.outputUrl;
4577
+ * });
4578
+ * ```
4579
+ */
4580
+ declare class ImageAiPlugin extends ImageAiPlugin_base {}
4581
+ type ImageAiPluginLayer = Layer.Layer<ImageAiPlugin, never, never>;
4582
+ //#endregion
4583
+ //#region src/flow/plugins/types/optimize-node.d.ts
4584
+ /**
4585
+ * Zod schema for validating image optimization parameters.
4586
+ * Defines the structure and validation rules for image optimization requests.
4587
+ */
4588
+ declare const optimizeParamsSchema: z.ZodObject<{
4589
+ quality: z.ZodNumber;
4590
+ format: z.ZodEnum<{
4591
+ jpeg: "jpeg";
4592
+ webp: "webp";
4536
4593
  png: "png";
4537
4594
  avif: "avif";
4538
4595
  }>;
@@ -5170,6 +5227,121 @@ declare const VideoPlugin_base: Context.TagClass<VideoPlugin, "VideoPlugin", Vid
5170
5227
  declare class VideoPlugin extends VideoPlugin_base {}
5171
5228
  type VideoPluginLayer = Layer.Layer<VideoPlugin, never, never>;
5172
5229
  //#endregion
5230
+ //#region src/flow/plugins/virus-scan-plugin.d.ts
5231
+ /**
5232
+ * Result of a virus scan operation.
5233
+ */
5234
+ type ScanResult = {
5235
+ /**
5236
+ * Whether the file is clean (no viruses detected)
5237
+ */
5238
+ isClean: boolean;
5239
+ /**
5240
+ * Array of detected virus/malware names (empty if clean)
5241
+ */
5242
+ detectedViruses: string[];
5243
+ };
5244
+ /**
5245
+ * Comprehensive metadata about a virus scan operation.
5246
+ */
5247
+ type ScanMetadata = {
5248
+ /**
5249
+ * Whether the file was scanned
5250
+ */
5251
+ scanned: boolean;
5252
+ /**
5253
+ * Whether the file is clean (no viruses detected)
5254
+ */
5255
+ isClean: boolean;
5256
+ /**
5257
+ * Array of detected virus/malware names (empty if clean)
5258
+ */
5259
+ detectedViruses: string[];
5260
+ /**
5261
+ * ISO 8601 timestamp of when the scan was performed
5262
+ */
5263
+ scanDate: string;
5264
+ /**
5265
+ * Version of the antivirus engine used
5266
+ */
5267
+ engineVersion: string;
5268
+ /**
5269
+ * ISO 8601 timestamp of when virus definitions were last updated
5270
+ */
5271
+ definitionsDate: string;
5272
+ };
5273
+ /**
5274
+ * Shape definition for the Virus Scan Plugin interface.
5275
+ * Defines the contract that all virus scanning implementations must follow.
5276
+ */
5277
+ type VirusScanPluginShape = {
5278
+ /**
5279
+ * Scans a file for viruses and malware.
5280
+ *
5281
+ * @param input - The input file as a Uint8Array
5282
+ * @returns An Effect that resolves to ScanResult with detection information
5283
+ * @throws {UploadistaError} When virus scanning fails or ClamAV is unavailable
5284
+ *
5285
+ * @example
5286
+ * ```typescript
5287
+ * const program = Effect.gen(function* () {
5288
+ * const virusScanPlugin = yield* VirusScanPlugin;
5289
+ * const result = yield* virusScanPlugin.scan(fileData);
5290
+ * if (!result.isClean) {
5291
+ * console.log('Viruses detected:', result.detectedViruses);
5292
+ * }
5293
+ * });
5294
+ * ```
5295
+ */
5296
+ scan: (input: Uint8Array) => Effect.Effect<ScanResult, UploadistaError>;
5297
+ /**
5298
+ * Retrieves the version of the antivirus engine.
5299
+ *
5300
+ * @returns An Effect that resolves to the engine version string
5301
+ * @throws {UploadistaError} When version retrieval fails
5302
+ *
5303
+ * @example
5304
+ * ```typescript
5305
+ * const program = Effect.gen(function* () {
5306
+ * const virusScanPlugin = yield* VirusScanPlugin;
5307
+ * const version = yield* virusScanPlugin.getVersion();
5308
+ * console.log('ClamAV version:', version);
5309
+ * });
5310
+ * ```
5311
+ */
5312
+ getVersion: () => Effect.Effect<string, UploadistaError>;
5313
+ };
5314
+ declare const VirusScanPlugin_base: Context.TagClass<VirusScanPlugin, "VirusScanPlugin", VirusScanPluginShape>;
5315
+ /**
5316
+ * Context tag for the Virus Scan Plugin.
5317
+ *
5318
+ * This tag provides a type-safe way to access virus scanning functionality
5319
+ * throughout the application using Effect's dependency injection system.
5320
+ *
5321
+ * @example
5322
+ * ```typescript
5323
+ * import { VirusScanPlugin } from "@uploadista/core/flow/plugins";
5324
+ *
5325
+ * // In your flow node
5326
+ * const program = Effect.gen(function* () {
5327
+ * const virusScanPlugin = yield* VirusScanPlugin;
5328
+ * const result = yield* virusScanPlugin.scan(fileData);
5329
+ *
5330
+ * if (!result.isClean) {
5331
+ * // Handle infected file
5332
+ * return Effect.fail(new UploadistaError({
5333
+ * code: "VIRUS_DETECTED",
5334
+ * message: `Viruses detected: ${result.detectedViruses.join(', ')}`
5335
+ * }));
5336
+ * }
5337
+ *
5338
+ * return fileData;
5339
+ * });
5340
+ * ```
5341
+ */
5342
+ declare class VirusScanPlugin extends VirusScanPlugin_base {}
5343
+ type VirusScanPluginLayer = Layer.Layer<VirusScanPlugin, never, never>;
5344
+ //#endregion
5173
5345
  //#region src/flow/plugins/zip-plugin.d.ts
5174
5346
  /**
5175
5347
  * Parameters for creating a ZIP archive.
@@ -5230,8 +5402,8 @@ declare class ZipPlugin extends ZipPlugin_base {}
5230
5402
  type ZipPluginLayer = Layer.Layer<ZipPlugin, never, never>;
5231
5403
  //#endregion
5232
5404
  //#region src/flow/plugins/plugins.d.ts
5233
- type Plugin = ImagePlugin | ImageAiPlugin | VideoPlugin | CredentialProvider | ZipPlugin;
5234
- type PluginLayer = ImagePluginLayer | ImageAiPluginLayer | VideoPluginLayer | CredentialProviderLayer | ZipPluginLayer;
5405
+ type Plugin = ImagePlugin | ImageAiPlugin | VideoPlugin | DocumentPlugin | DocumentAiPlugin | VirusScanPlugin | CredentialProvider | ZipPlugin;
5406
+ type PluginLayer = ImagePluginLayer | ImageAiPluginLayer | VideoPluginLayer | DocumentPluginLayer | DocumentAiPluginLayer | VirusScanPluginLayer | CredentialProviderLayer | ZipPluginLayer;
5235
5407
  //#endregion
5236
5408
  //#region src/flow/plugins/types/describe-image-node.d.ts
5237
5409
  /**
@@ -5265,6 +5437,201 @@ declare const removeBackgroundParamsSchema: z.ZodObject<{
5265
5437
  */
5266
5438
  type RemoveBackgroundParams = z.infer<typeof removeBackgroundParamsSchema>;
5267
5439
  //#endregion
5440
+ //#region src/flow/type-guards.d.ts
5441
+ /**
5442
+ * Factory function to create type guards for specific node types.
5443
+ *
5444
+ * Creates a TypeScript type guard that validates both the type tag and
5445
+ * the data structure against the registered schema. This enables type-safe
5446
+ * narrowing of TypedOutput objects in TypeScript.
5447
+ *
5448
+ * @template T - The expected TypeScript type after narrowing
5449
+ * @param typeId - The registered type ID to check against (e.g., "storage-output-v1")
5450
+ * @returns A type guard function that narrows TypedOutput to TypedOutput<T>
5451
+ *
5452
+ * @example
5453
+ * ```typescript
5454
+ * import { createTypeGuard } from "@uploadista/core/flow";
5455
+ * import { z } from "zod";
5456
+ *
5457
+ * const descriptionSchema = z.object({
5458
+ * description: z.string(),
5459
+ * confidence: z.number(),
5460
+ * });
5461
+ *
5462
+ * type DescriptionOutput = z.infer<typeof descriptionSchema>;
5463
+ *
5464
+ * const isDescriptionOutput = createTypeGuard<DescriptionOutput>(
5465
+ * "description-output-v1"
5466
+ * );
5467
+ *
5468
+ * // Use in code
5469
+ * if (isDescriptionOutput(output)) {
5470
+ * // output.data is typed as DescriptionOutput
5471
+ * console.log(output.data.description);
5472
+ * }
5473
+ * ```
5474
+ */
5475
+ declare function createTypeGuard<T>(typeId: string): (output: TypedOutput) => output is TypedOutput<T>;
5476
+ /**
5477
+ * Type guard for storage output nodes.
5478
+ *
5479
+ * Validates that an output is from a storage node and contains valid UploadFile data.
5480
+ *
5481
+ * @param output - The output to check
5482
+ * @returns True if the output is a storage output with valid UploadFile data
5483
+ *
5484
+ * @example
5485
+ * ```typescript
5486
+ * import { isStorageOutput } from "@uploadista/core/flow";
5487
+ *
5488
+ * if (isStorageOutput(output)) {
5489
+ * // output.data is typed as UploadFile
5490
+ * console.log("File URL:", output.data.url);
5491
+ * console.log("File size:", output.data.size);
5492
+ * }
5493
+ * ```
5494
+ */
5495
+ declare const isStorageOutput: (output: TypedOutput) => output is TypedOutput<UploadFile>;
5496
+ /**
5497
+ * Filter an array of outputs to only those matching a specific type.
5498
+ *
5499
+ * This helper function filters outputs using a type guard and returns a
5500
+ * properly typed array of results. It's useful for extracting specific
5501
+ * output types from multi-output flows.
5502
+ *
5503
+ * @template T - The expected output data type
5504
+ * @param outputs - Array of typed outputs to filter
5505
+ * @param typeGuard - Type guard function to use for filtering
5506
+ * @returns Array of outputs that match the type guard, properly typed
5507
+ *
5508
+ * @example
5509
+ * ```typescript
5510
+ * import { filterOutputsByType, isStorageOutput } from "@uploadista/core/flow";
5511
+ *
5512
+ * // Get all storage outputs from a multi-output flow
5513
+ * const storageOutputs = filterOutputsByType(
5514
+ * flowResult.outputs,
5515
+ * isStorageOutput
5516
+ * );
5517
+ *
5518
+ * for (const output of storageOutputs) {
5519
+ * // Each output.data is typed as UploadFile
5520
+ * console.log("Saved file:", output.data.url);
5521
+ * }
5522
+ * ```
5523
+ */
5524
+ declare function filterOutputsByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): TypedOutput<T>[];
5525
+ /**
5526
+ * Get a single output of a specific type from an array of outputs.
5527
+ *
5528
+ * This helper function finds exactly one output matching the type guard.
5529
+ * It throws an error if no outputs match or if multiple outputs match,
5530
+ * ensuring the caller receives exactly the expected result.
5531
+ *
5532
+ * @template T - The expected output data type
5533
+ * @param outputs - Array of typed outputs to search
5534
+ * @param typeGuard - Type guard function to use for matching
5535
+ * @returns The single matching output, properly typed
5536
+ * @throws {UploadistaError} If no outputs match (OUTPUT_NOT_FOUND)
5537
+ * @throws {UploadistaError} If multiple outputs match (MULTIPLE_OUTPUTS_FOUND)
5538
+ *
5539
+ * @example
5540
+ * ```typescript
5541
+ * import { getSingleOutputByType, isStorageOutput } from "@uploadista/core/flow";
5542
+ *
5543
+ * try {
5544
+ * const storageOutput = getSingleOutputByType(
5545
+ * flowResult.outputs,
5546
+ * isStorageOutput
5547
+ * );
5548
+ * // storageOutput.data is typed as UploadFile
5549
+ * console.log("File saved at:", storageOutput.data.url);
5550
+ * } catch (error) {
5551
+ * if (error.code === "OUTPUT_NOT_FOUND") {
5552
+ * console.error("No storage output found");
5553
+ * } else if (error.code === "MULTIPLE_OUTPUTS_FOUND") {
5554
+ * console.error("Multiple storage outputs found, expected one");
5555
+ * }
5556
+ * }
5557
+ * ```
5558
+ */
5559
+ declare function getSingleOutputByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): Effect.Effect<TypedOutput<T>, UploadistaError>;
5560
+ /**
5561
+ * Get the first output of a specific type, if any exists.
5562
+ *
5563
+ * Unlike getSingleOutputByType, this function returns undefined if no outputs
5564
+ * match, and returns the first match if multiple outputs exist. This is useful
5565
+ * when you want a more lenient matching strategy.
5566
+ *
5567
+ * @template T - The expected output data type
5568
+ * @param outputs - Array of typed outputs to search
5569
+ * @param typeGuard - Type guard function to use for matching
5570
+ * @returns The first matching output, or undefined if none match
5571
+ *
5572
+ * @example
5573
+ * ```typescript
5574
+ * import { getFirstOutputByType, isStorageOutput } from "@uploadista/core/flow";
5575
+ *
5576
+ * const storageOutput = getFirstOutputByType(
5577
+ * flowResult.outputs,
5578
+ * isStorageOutput
5579
+ * );
5580
+ *
5581
+ * if (storageOutput) {
5582
+ * console.log("First storage output:", storageOutput.data.url);
5583
+ * } else {
5584
+ * console.log("No storage outputs found");
5585
+ * }
5586
+ * ```
5587
+ */
5588
+ declare function getFirstOutputByType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): TypedOutput<T> | undefined;
5589
+ /**
5590
+ * Get an output by its node ID.
5591
+ *
5592
+ * This helper finds an output produced by a specific node instance,
5593
+ * regardless of its type. Useful when you know the specific node ID
5594
+ * you're looking for.
5595
+ *
5596
+ * @param outputs - Array of typed outputs to search
5597
+ * @param nodeId - The node ID to match
5598
+ * @returns The output from the specified node, or undefined if not found
5599
+ *
5600
+ * @example
5601
+ * ```typescript
5602
+ * import { getOutputByNodeId } from "@uploadista/core/flow";
5603
+ *
5604
+ * const cdnOutput = getOutputByNodeId(flowResult.outputs, "cdn-storage");
5605
+ * if (cdnOutput) {
5606
+ * console.log("CDN output:", cdnOutput.data);
5607
+ * }
5608
+ * ```
5609
+ */
5610
+ declare function getOutputByNodeId(outputs: TypedOutput[], nodeId: string): TypedOutput | undefined;
5611
+ /**
5612
+ * Check if any outputs match a specific type.
5613
+ *
5614
+ * Simple predicate function to check if at least one output of a given
5615
+ * type exists in the results.
5616
+ *
5617
+ * @template T - The expected output data type
5618
+ * @param outputs - Array of typed outputs to check
5619
+ * @param typeGuard - Type guard function to use for checking
5620
+ * @returns True if at least one output matches the type guard
5621
+ *
5622
+ * @example
5623
+ * ```typescript
5624
+ * import { hasOutputOfType, isStorageOutput } from "@uploadista/core/flow";
5625
+ *
5626
+ * if (hasOutputOfType(flowResult.outputs, isStorageOutput)) {
5627
+ * console.log("Flow produced at least one storage output");
5628
+ * } else {
5629
+ * console.log("No storage outputs in this flow");
5630
+ * }
5631
+ * ```
5632
+ */
5633
+ declare function hasOutputOfType<T>(outputs: TypedOutput[], typeGuard: (output: TypedOutput) => output is TypedOutput<T>): boolean;
5634
+ //#endregion
5268
5635
  //#region src/flow/types/flow-file.d.ts
5269
5636
  /**
5270
5637
  * Conditional execution rules for flow nodes.
@@ -5704,5 +6071,5 @@ type ResolvedUploadMetadata = {
5704
6071
  };
5705
6072
  declare function resolveUploadMetadata(metadata: FileMetadata): ResolvedUploadMetadata;
5706
6073
  //#endregion
5707
- export { LogoTransform as $, DataStoreWriteOptions as $n, FlowEventNodeResponse as $r, FlowServerShape as $t, ZipPluginLayer as A, InputFile as An, CustomTypedOutput as Ar, ImageAiPluginLayer as At, resizeVideoParamsSchema as B, uploadEventEmitter as Bn, waitingNodeExecution as Br, StorageParams as Bt, DescribeImageParams as C, hasOutputOfType as Cn, FlowData as Cr, watermarkTransformSchema as Ct, ZipInput as D, MiddlewareNext as Dn, FlowEdge as Dr, optimizeParamsSchema as Dt, PluginLayer as E, MiddlewareContext as En, getFlowData as Er, OptimizeParams as Et, TrimVideoParams as F, FlowEventEmitter as Fn, NodeExecutionResult as Fr, ExecutionLevel as Ft, ImagePlugin as G, UploadEventType as Gn, FlowEventFlowError as Gr, createInputNode as Gt, extractFrameVideoParamsSchema as H, WebSocketMessage as Hn, FlowEvent as Hr, storageParamsSchema as Ht, trimVideoParamsSchema as I, TypedEventEmitter as In, NodeTypeMap as Ir, ParallelScheduler as It, BlurTransform as J, EventBroadcasterService as Jn, FlowEventJobEnd as Jr, FlowProvider as Jt, ImagePluginLayer as K, uploadEventSchema as Kn, FlowEventFlowPause as Kr, inputDataSchema as Kt, TranscodeVideoParams as L, UploadEventEmitter as Ln, TypeCompatibilityChecker as Lr, ParallelSchedulerConfig as Lt, VideoPlugin as M, BaseEventEmitter as Mn, FlowNode as Mr, CredentialProvider as Mt, VideoPluginLayer as N, BaseEventEmitterService as Nn, FlowNodeData as Nr, CredentialProviderLayer as Nt, ZipParams as O, MiddlewareService as On, createFlowEdge as Or, ImageAiContext as Ot, VideoPluginShape as P, EventEmitter as Pn, NodeConnectionValidator as Pr, CredentialProviderShape as Pt, GrayscaleTransform as Q, DataStoreConfig as Qn, FlowEventNodePause as Qr, FlowServerOptions as Qt, transcodeVideoParamsSchema as R, eventToMessageSerializer as Rn, TypedOutput as Rr, TransformNodeConfig as Rt, removeBackgroundParamsSchema as S, getSingleOutputByType as Sn, Flow as Sr, transformationSchema as St, Plugin as T, Middleware as Tn, createFlowWithSchema as Tr, resizeParamsSchema as Tt, DescribeVideoMetadata as U, webSocketMessageSchema as Un, FlowEventFlowCancel as Ur, InputData as Ut, ExtractFrameVideoParams as V, WebSocketConnection as Vn, EventType as Vr, createStorageNode as Vt, describeVideoMetadataSchema as W, UploadEvent as Wn, FlowEventFlowEnd as Wr, InputNodeParams as Wt, ContrastTransform as X, DataStore as Xn, FlowEventNodeEnd as Xr, FlowServer as Xt, BrightnessTransform as Y, BufferedUploadFileDataStore as Yn, FlowEventJobStart as Yr, FlowProviderShape as Yt, FlipTransform as Z, DataStoreCapabilities as Zn, FlowEventNodeError as Zr, FlowServerLayer as Zt, ExtractLayerService as _, detectMimeType as _n, FlowTypeRegistry as _r, rotateTransformSchema as _t, FlowInputMap as a, NodeType as ai, FlowJobStatus as an, isDataStore as ar, TextTransform as at, FlowCondition as b, getFirstOutputByType as bn, ValidationResult as br, textTransformSchema as bt, FlowRequirements as c, UploadFile as ci, NegotiatedStrategy as cn, FlowJobKVStore as cr, TransformationType as ct, TypedFlow as d, UploadServer as dn, UploadFileKVStore as dr, brightnessTransformSchema as dt, FlowEventNodeResume as ei, FlowWaitUntil as en, UploadFileDataStore as er, OverlayPosition as et, TypedFlowConfig as f, UploadServerOptions as fn, flowJobKvStore as fr, contrastTransformSchema as ft, ExtractEffectRequirements as g, compareMimeTypes as gn, STREAMING_INPUT_TYPE_ID as gr, resizeTransformSchema as gt, ExtractEffectError as h, uploadServer as hn, STORAGE_OUTPUT_TYPE_ID as hr, logoTransformSchema as ht, runArgsSchema as i, ConditionValue as ii, FlowJob as in, createDataStoreLayer as ir, SharpenTransform as it, ZipPluginShape as j, inputFileSchema as jn, FlowConfig as jr, ImageAiPluginShape as jt, ZipPlugin as k, MiddlewareServiceLive as kn, BuiltInTypedOutput as kr, ImageAiPlugin as kt, NodeDefinition as l, uploadFileSchema as li, UploadStrategyNegotiator as ln, KvStore as lr, WatermarkTransform as lt, createFlow as m, createUploadServer as mn, uploadFileKvStore as mr, grayscaleTransformSchema as mt, resolveUploadMetadata as n, ConditionField as ni, createFlowServer as nn, UploadFileDataStoresShape as nr, RotateTransform as nt, FlowOutputMap as o, createFlowNode as oi, FlowJobTask as on, BaseKvStore as or, TransformImageParams as ot, TypedFlowEdge as p, UploadServerShape as pn, jsonSerializer as pr, flipTransformSchema as pt, ImagePluginShape as q, EventBroadcaster as qn, FlowEventFlowStart as qr, inputNodeParamsSchema as qt, RunArgs as r, ConditionOperator as ri, flowServer as rn, UploadStrategy as rr, SepiaTransform as rt, FlowPluginRequirements as s, getNodeData as si, FlowJobTaskStatus as sn, BaseKvStoreService as sr, Transformation as st, ResolvedUploadMetadata as t, FlowEventNodeStart as ti, WaitUntilCallback as tn, UploadFileDataStores as tr, ResizeTransform as tt, NodeDefinitionsRecord as u, UploadStrategyOptions as un, TypedKvStore as ur, blurTransformSchema as ut, ExtractLayerServices as v, createTypeGuard as vn, NodeTypeCategory as vr, sepiaTransformSchema as vt, describeImageParamsSchema as w, isStorageOutput as wn, FlowExecutionResult as wr, ResizeParams as wt, RemoveBackgroundParams as x, getOutputByNodeId as xn, flowTypeRegistry as xr, transformImageParamsSchema as xt, ResolveEffect as y, filterOutputsByType as yn, NodeTypeDefinition as yr, sharpenTransformSchema as yt, ResizeVideoParams as z, flowEventEmitter as zn, completeNodeExecution as zr, createTransformNode as zt };
5708
- //# sourceMappingURL=index-CdP4c5LF.d.mts.map
6074
+ export { ExtractFrameVideoParams as $, BaseEventEmitterService as $n, FlowNodeData as $r, DocumentAiPluginLayer as $t, DescribeImageParams as A, flowServer as An, TypedKvStore as Ar, sepiaTransformSchema as At, ScanResult as B, UploadServerShape as Bn, ValidationResult as Br, ImageAiContext as Bt, getFirstOutputByType as C, ConditionOperator as Ci, FlowServer as Cn, UploadStrategy as Cr, brightnessTransformSchema as Ct, isStorageOutput as D, getNodeData as Di, FlowWaitUntil as Dn, BaseKvStoreService as Dr, logoTransformSchema as Dt, hasOutputOfType as E, createFlowNode as Ei, FlowServerShape as En, BaseKvStore as Er, grayscaleTransformSchema as Et, ZipParams as F, NegotiatedStrategy as Fn, STORAGE_OUTPUT_TYPE_ID as Fr, watermarkTransformSchema as Ft, VideoPluginLayer as G, Middleware as Gn, createFlowWithSchema as Gr, DocumentPlugin as Gt, VirusScanPluginLayer as H, uploadServer as Hn, Flow as Hr, ImageAiPluginLayer as Ht, ZipPlugin as I, UploadStrategyNegotiator as In, STREAMING_INPUT_TYPE_ID as Ir, ResizeParams as It, trimVideoParamsSchema as J, MiddlewareService as Jn, createFlowEdge as Jr, MergePdfParams as Jt, VideoPluginShape as K, MiddlewareContext as Kn, getFlowData as Kr, DocumentPluginLayer as Kt, ZipPluginLayer as L, UploadStrategyOptions as Ln, FlowTypeRegistry as Lr, resizeParamsSchema as Lt, Plugin as M, FlowJobStatus as Mn, flowJobKvStore as Mr, textTransformSchema as Mt, PluginLayer as N, FlowJobTask as Nn, jsonSerializer as Nr, transformImageParamsSchema as Nt, RemoveBackgroundParams as O, UploadFile as Oi, WaitUntilCallback as On, FlowJobKVStore as Or, resizeTransformSchema as Ot, ZipInput as P, FlowJobTaskStatus as Pn, uploadFileKvStore as Pr, transformationSchema as Pt, resizeVideoParamsSchema as Q, BaseEventEmitter as Qn, FlowNode as Qr, DocumentAiPlugin as Qt, ZipPluginShape as R, UploadServer as Rn, NodeTypeCategory as Rr, OptimizeParams as Rt, filterOutputsByType as S, ConditionField as Si, FlowProviderShape as Sn, UploadFileDataStoresShape as Sr, blurTransformSchema as St, getSingleOutputByType as T, NodeType as Ti, FlowServerOptions as Tn, isDataStore as Tr, flipTransformSchema as Tt, VirusScanPluginShape as U, compareMimeTypes as Un, FlowData as Ur, ImageAiPluginShape as Ut, VirusScanPlugin as V, createUploadServer as Vn, flowTypeRegistry as Vr, ImageAiPlugin as Vt, VideoPlugin as W, detectMimeType as Wn, FlowExecutionResult as Wr, DocumentMetadata as Wt, transcodeVideoParamsSchema as X, InputFile as Xn, CustomTypedOutput as Xr, SplitPdfResult as Xt, TranscodeVideoParams as Y, MiddlewareServiceLive as Yn, BuiltInTypedOutput as Yr, SplitPdfParams as Yt, ResizeVideoParams as Z, inputFileSchema as Zn, FlowConfig as Zr, DocumentAiContext as Zt, ExtractLayerService as _, FlowEventNodeError as _i, InputNodeParams as _n, DataStoreCapabilities as _r, TextTransform as _t, FlowInputMap as a, completeNodeExecution as ai, CredentialProvider as an, flowEventEmitter as ar, ImagePluginShape as at, FlowCondition as b, FlowEventNodeResume as bi, inputNodeParamsSchema as bn, UploadFileDataStore as br, TransformationType as bt, FlowRequirements as c, FlowEvent as ci, ExecutionLevel as cn, WebSocketMessage as cr, ContrastTransform as ct, TypedFlow as d, FlowEventFlowError as di, TransformNodeConfig as dn, UploadEventType as dr, LogoTransform as dt, NodeConnectionValidator as ei, DocumentAiPluginShape as en, EventEmitter as er, extractFrameVideoParamsSchema as et, TypedFlowConfig as f, FlowEventFlowPause as fi, createTransformNode as fn, uploadEventSchema as fr, OverlayPosition as ft, ExtractEffectRequirements as g, FlowEventNodeEnd as gi, InputData as gn, DataStore as gr, SharpenTransform as gt, ExtractEffectError as h, FlowEventJobStart as hi, storageParamsSchema as hn, BufferedUploadFileDataStore as hr, SepiaTransform as ht, runArgsSchema as i, TypedOutput as ii, OcrTaskType as in, eventToMessageSerializer as ir, ImagePluginLayer as it, describeImageParamsSchema as j, FlowJob as jn, UploadFileKVStore as jr, sharpenTransformSchema as jt, removeBackgroundParamsSchema as k, uploadFileSchema as ki, createFlowServer as kn, KvStore as kr, rotateTransformSchema as kt, NodeDefinition as l, FlowEventFlowCancel as li, ParallelScheduler as ln, webSocketMessageSchema as lr, FlipTransform as lt, createFlow as m, FlowEventJobEnd as mi, createStorageNode as mn, EventBroadcasterService as mr, RotateTransform as mt, resolveUploadMetadata as n, NodeTypeMap as ni, OcrResolution as nn, TypedEventEmitter as nr, describeVideoMetadataSchema as nt, FlowOutputMap as o, waitingNodeExecution as oi, CredentialProviderLayer as on, uploadEventEmitter as or, BlurTransform as ot, TypedFlowEdge as p, FlowEventFlowStart as pi, StorageParams as pn, EventBroadcaster as pr, ResizeTransform as pt, TrimVideoParams as q, MiddlewareNext as qn, FlowEdge as qr, DocumentPluginShape as qt, RunArgs as r, TypeCompatibilityChecker as ri, OcrResult as rn, UploadEventEmitter as rr, ImagePlugin as rt, FlowPluginRequirements as s, EventType as si, CredentialProviderShape as sn, WebSocketConnection as sr, BrightnessTransform as st, ResolvedUploadMetadata as t, NodeExecutionResult as ti, OcrParams as tn, FlowEventEmitter as tr, DescribeVideoMetadata as tt, NodeDefinitionsRecord as u, FlowEventFlowEnd as ui, ParallelSchedulerConfig as un, UploadEvent as ur, GrayscaleTransform as ut, ExtractLayerServices as v, FlowEventNodePause as vi, createInputNode as vn, DataStoreConfig as vr, TransformImageParams as vt, getOutputByNodeId as w, ConditionValue as wi, FlowServerLayer as wn, createDataStoreLayer as wr, contrastTransformSchema as wt, createTypeGuard as x, FlowEventNodeStart as xi, FlowProvider as xn, UploadFileDataStores as xr, WatermarkTransform as xt, ResolveEffect as y, FlowEventNodeResponse as yi, inputDataSchema as yn, DataStoreWriteOptions as yr, Transformation as yt, ScanMetadata as z, UploadServerOptions as zn, NodeTypeDefinition as zr, optimizeParamsSchema as zt };
6075
+ //# sourceMappingURL=index-8m7lfPuJ.d.mts.map