@better-media/plugin-validation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/index.d.mts +110 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +2957 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2949 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 abenezeratnafu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
20
|
+
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @better-media/plugin-validation
|
|
2
|
+
|
|
3
|
+
Validation plugin for the Better Media framework.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **MIME Type Validation**: Enforce allowed file types (e.g., `image/jpeg`, `video/mp4`).
|
|
8
|
+
- **File Size Validation**: Enforce minimum and maximum file dimensions.
|
|
9
|
+
- **Header Inspection**: Inspect raw bytes to verify MIME type.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @better-media/plugin-validation
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { validationPlugin } from "@better-media/plugin-validation";
|
|
21
|
+
|
|
22
|
+
const media = createBetterMedia({
|
|
23
|
+
plugins: [
|
|
24
|
+
validationPlugin({
|
|
25
|
+
maxSize: "10mb",
|
|
26
|
+
allowedMimeTypes: ["image/jpeg", "image/png"],
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For more, visit [better-media.dev/docs/plugins/validation](https://better-media.dev/docs/plugins/validation).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { PipelinePlugin } from '@better-media/core';
|
|
2
|
+
|
|
3
|
+
interface ValidationErrorItem {
|
|
4
|
+
rule: string;
|
|
5
|
+
message: string;
|
|
6
|
+
details?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Validation plugin configuration.
|
|
11
|
+
* All rules are optional; omit to skip that validation.
|
|
12
|
+
*/
|
|
13
|
+
interface ValidationPluginOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Execution mode. Default: "background".
|
|
16
|
+
* Sync: runs inline and can abort the pipeline on failure.
|
|
17
|
+
* Background: enqueues work; pipeline continues; result stored in DB.
|
|
18
|
+
*/
|
|
19
|
+
executionMode?: "sync" | "background";
|
|
20
|
+
/**
|
|
21
|
+
* When validation fails: "abort" (return ValidationResult, stop pipeline),
|
|
22
|
+
* "continue" (record failure in DB, let pipeline continue), or "custom" (invoke onFailureCallback).
|
|
23
|
+
* Applies to sync mode. Background mode always records to DB.
|
|
24
|
+
*/
|
|
25
|
+
onFailure?: "abort" | "continue" | "custom";
|
|
26
|
+
/** Called when onFailure is "custom". Receives errors; return to control pipeline (abort if ValidationResult). */
|
|
27
|
+
onFailureCallback?: (fileKey: string, errors: ValidationErrorItem[]) => void | Promise<{
|
|
28
|
+
valid: boolean;
|
|
29
|
+
message?: string;
|
|
30
|
+
} | void>;
|
|
31
|
+
/** Allowed file extensions (e.g. [".jpg", ".png"]). Omit to skip. */
|
|
32
|
+
allowedExtensions?: string[];
|
|
33
|
+
/** Allowed MIME types (e.g. ["image/jpeg", "image/png"]). Omit to skip. */
|
|
34
|
+
allowedMimeTypes?: string[];
|
|
35
|
+
/** Validate MIME via magic bytes (not extension). Requires file bytes. Default: true. */
|
|
36
|
+
useMagicBytes?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Extract critical metadata from file content and override context.file.
|
|
39
|
+
* Trust library-extracted values over caller-provided metadata.
|
|
40
|
+
* Default: true.
|
|
41
|
+
*/
|
|
42
|
+
extractMetadata?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Checksum algorithms to compute when extractMetadata is true.
|
|
45
|
+
* Default: ["sha256"].
|
|
46
|
+
*/
|
|
47
|
+
extractChecksums?: ("sha256" | "md5")[];
|
|
48
|
+
/** Min file size in bytes. Omit to skip. */
|
|
49
|
+
minBytes?: number;
|
|
50
|
+
/** Max file size in bytes. Omit to skip. */
|
|
51
|
+
maxBytes?: number;
|
|
52
|
+
/** Min width in pixels (images/video). Omit to skip. */
|
|
53
|
+
minWidth?: number;
|
|
54
|
+
/** Max width in pixels. Omit to skip. */
|
|
55
|
+
maxWidth?: number;
|
|
56
|
+
/** Min height in pixels. Omit to skip. */
|
|
57
|
+
minHeight?: number;
|
|
58
|
+
/** Max height in pixels. Omit to skip. */
|
|
59
|
+
maxHeight?: number;
|
|
60
|
+
/** Max duration in seconds (video/audio). Use customValidators for implementation. */
|
|
61
|
+
maxDurationSeconds?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Expected checksum for integrity. If provided, computed hash must match.
|
|
64
|
+
* metadata should contain the expected value (e.g. metadata.sha256).
|
|
65
|
+
*/
|
|
66
|
+
checksum?: {
|
|
67
|
+
algorithm: "sha256" | "sha512" | "md5";
|
|
68
|
+
/** Key in metadata where expected hash is stored, or a literal value. */
|
|
69
|
+
metadataKey?: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Behavior when file is not found in storage (e.g. presigned URL, upload not complete).
|
|
73
|
+
* "fail": return validation error.
|
|
74
|
+
* "retry": retry with backoff (uses retryOptions).
|
|
75
|
+
* "skip": skip validation, return valid (risky).
|
|
76
|
+
*/
|
|
77
|
+
fileNotFoundBehavior?: "fail" | "retry" | "skip";
|
|
78
|
+
/** Used when fileNotFoundBehavior is "retry". */
|
|
79
|
+
retryOptions?: {
|
|
80
|
+
maxAttempts?: number;
|
|
81
|
+
delayMs?: number;
|
|
82
|
+
backoff?: "linear" | "exponential";
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Block upload if a file with the same checksum already exists in the database.
|
|
86
|
+
* Default: false.
|
|
87
|
+
*/
|
|
88
|
+
preventDuplicates?: boolean | {
|
|
89
|
+
algorithm?: "sha256" | "md5";
|
|
90
|
+
metadataKey?: string;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Filename handling when sanitizing for storage (see `sanitizeFilename`).
|
|
94
|
+
* @default "sanitize"
|
|
95
|
+
*/
|
|
96
|
+
filenameSafety?: "sanitize" | "randomize";
|
|
97
|
+
/** Max length for sanitized filenames (default 255). */
|
|
98
|
+
maxFilenameLength?: number;
|
|
99
|
+
/** Custom validators. Receives buffer and metadata; return errors to fail. */
|
|
100
|
+
customValidators?: Array<(buffer: Buffer, metadata: Record<string, unknown>, fileKey: string) => ValidationErrorItem[] | Promise<ValidationErrorItem[]>>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validation plugin for the Better Media pipeline.
|
|
105
|
+
* Supports file type, size, dimensions, checksum, and custom validators.
|
|
106
|
+
* Configurable failure behavior and file-not-found handling (presigned URLs).
|
|
107
|
+
*/
|
|
108
|
+
declare function validationPlugin(opts?: ValidationPluginOptions): PipelinePlugin;
|
|
109
|
+
|
|
110
|
+
export { type ValidationPluginOptions, validationPlugin };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { PipelinePlugin } from '@better-media/core';
|
|
2
|
+
|
|
3
|
+
interface ValidationErrorItem {
|
|
4
|
+
rule: string;
|
|
5
|
+
message: string;
|
|
6
|
+
details?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Validation plugin configuration.
|
|
11
|
+
* All rules are optional; omit to skip that validation.
|
|
12
|
+
*/
|
|
13
|
+
interface ValidationPluginOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Execution mode. Default: "background".
|
|
16
|
+
* Sync: runs inline and can abort the pipeline on failure.
|
|
17
|
+
* Background: enqueues work; pipeline continues; result stored in DB.
|
|
18
|
+
*/
|
|
19
|
+
executionMode?: "sync" | "background";
|
|
20
|
+
/**
|
|
21
|
+
* When validation fails: "abort" (return ValidationResult, stop pipeline),
|
|
22
|
+
* "continue" (record failure in DB, let pipeline continue), or "custom" (invoke onFailureCallback).
|
|
23
|
+
* Applies to sync mode. Background mode always records to DB.
|
|
24
|
+
*/
|
|
25
|
+
onFailure?: "abort" | "continue" | "custom";
|
|
26
|
+
/** Called when onFailure is "custom". Receives errors; return to control pipeline (abort if ValidationResult). */
|
|
27
|
+
onFailureCallback?: (fileKey: string, errors: ValidationErrorItem[]) => void | Promise<{
|
|
28
|
+
valid: boolean;
|
|
29
|
+
message?: string;
|
|
30
|
+
} | void>;
|
|
31
|
+
/** Allowed file extensions (e.g. [".jpg", ".png"]). Omit to skip. */
|
|
32
|
+
allowedExtensions?: string[];
|
|
33
|
+
/** Allowed MIME types (e.g. ["image/jpeg", "image/png"]). Omit to skip. */
|
|
34
|
+
allowedMimeTypes?: string[];
|
|
35
|
+
/** Validate MIME via magic bytes (not extension). Requires file bytes. Default: true. */
|
|
36
|
+
useMagicBytes?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Extract critical metadata from file content and override context.file.
|
|
39
|
+
* Trust library-extracted values over caller-provided metadata.
|
|
40
|
+
* Default: true.
|
|
41
|
+
*/
|
|
42
|
+
extractMetadata?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Checksum algorithms to compute when extractMetadata is true.
|
|
45
|
+
* Default: ["sha256"].
|
|
46
|
+
*/
|
|
47
|
+
extractChecksums?: ("sha256" | "md5")[];
|
|
48
|
+
/** Min file size in bytes. Omit to skip. */
|
|
49
|
+
minBytes?: number;
|
|
50
|
+
/** Max file size in bytes. Omit to skip. */
|
|
51
|
+
maxBytes?: number;
|
|
52
|
+
/** Min width in pixels (images/video). Omit to skip. */
|
|
53
|
+
minWidth?: number;
|
|
54
|
+
/** Max width in pixels. Omit to skip. */
|
|
55
|
+
maxWidth?: number;
|
|
56
|
+
/** Min height in pixels. Omit to skip. */
|
|
57
|
+
minHeight?: number;
|
|
58
|
+
/** Max height in pixels. Omit to skip. */
|
|
59
|
+
maxHeight?: number;
|
|
60
|
+
/** Max duration in seconds (video/audio). Use customValidators for implementation. */
|
|
61
|
+
maxDurationSeconds?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Expected checksum for integrity. If provided, computed hash must match.
|
|
64
|
+
* metadata should contain the expected value (e.g. metadata.sha256).
|
|
65
|
+
*/
|
|
66
|
+
checksum?: {
|
|
67
|
+
algorithm: "sha256" | "sha512" | "md5";
|
|
68
|
+
/** Key in metadata where expected hash is stored, or a literal value. */
|
|
69
|
+
metadataKey?: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Behavior when file is not found in storage (e.g. presigned URL, upload not complete).
|
|
73
|
+
* "fail": return validation error.
|
|
74
|
+
* "retry": retry with backoff (uses retryOptions).
|
|
75
|
+
* "skip": skip validation, return valid (risky).
|
|
76
|
+
*/
|
|
77
|
+
fileNotFoundBehavior?: "fail" | "retry" | "skip";
|
|
78
|
+
/** Used when fileNotFoundBehavior is "retry". */
|
|
79
|
+
retryOptions?: {
|
|
80
|
+
maxAttempts?: number;
|
|
81
|
+
delayMs?: number;
|
|
82
|
+
backoff?: "linear" | "exponential";
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Block upload if a file with the same checksum already exists in the database.
|
|
86
|
+
* Default: false.
|
|
87
|
+
*/
|
|
88
|
+
preventDuplicates?: boolean | {
|
|
89
|
+
algorithm?: "sha256" | "md5";
|
|
90
|
+
metadataKey?: string;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Filename handling when sanitizing for storage (see `sanitizeFilename`).
|
|
94
|
+
* @default "sanitize"
|
|
95
|
+
*/
|
|
96
|
+
filenameSafety?: "sanitize" | "randomize";
|
|
97
|
+
/** Max length for sanitized filenames (default 255). */
|
|
98
|
+
maxFilenameLength?: number;
|
|
99
|
+
/** Custom validators. Receives buffer and metadata; return errors to fail. */
|
|
100
|
+
customValidators?: Array<(buffer: Buffer, metadata: Record<string, unknown>, fileKey: string) => ValidationErrorItem[] | Promise<ValidationErrorItem[]>>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validation plugin for the Better Media pipeline.
|
|
105
|
+
* Supports file type, size, dimensions, checksum, and custom validators.
|
|
106
|
+
* Configurable failure behavior and file-not-found handling (presigned URLs).
|
|
107
|
+
*/
|
|
108
|
+
declare function validationPlugin(opts?: ValidationPluginOptions): PipelinePlugin;
|
|
109
|
+
|
|
110
|
+
export { type ValidationPluginOptions, validationPlugin };
|