@reliverse/utils 2.3.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/dist/mod.d.ts +1 -0
- package/dist/mod.js +1 -0
- package/dist/validation.d.ts +56 -0
- package/dist/validation.js +123 -0
- package/package.json +30 -0
package/dist/mod.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validation.js.js";
|
package/dist/mod.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validation.js";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
/**
|
|
3
|
+
* Common validation utilities using arktype for consistent error handling
|
|
4
|
+
* and type safety across the codebase.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* File path validation with safety checks
|
|
8
|
+
*/
|
|
9
|
+
export declare const SafePath: import("arktype/out/variants/string").StringType<string, {}>;
|
|
10
|
+
/**
|
|
11
|
+
* URL validation with protocol checking
|
|
12
|
+
*/
|
|
13
|
+
export declare const SafeUrl: import("arktype/out/variants/string").StringType<string, {}>;
|
|
14
|
+
/**
|
|
15
|
+
* Email validation using arktype built-in constraints
|
|
16
|
+
*/
|
|
17
|
+
export declare const Email: import("arktype/out/variants/string").StringType<string, {}>;
|
|
18
|
+
/**
|
|
19
|
+
* Port number validation with common service warnings
|
|
20
|
+
*/
|
|
21
|
+
export declare const Port: import("arktype/out/variants/number").NumberType<number, {}>;
|
|
22
|
+
/**
|
|
23
|
+
* Semver validation using arktype built-in constraints
|
|
24
|
+
*/
|
|
25
|
+
export declare const Semver: import("arktype/out/variants/string").StringType<string, {}>;
|
|
26
|
+
/**
|
|
27
|
+
* Non-empty string validation
|
|
28
|
+
*/
|
|
29
|
+
export declare const NonEmptyString: import("arktype/out/variants/string").StringType<string, {}>;
|
|
30
|
+
/**
|
|
31
|
+
* Positive integer validation
|
|
32
|
+
*/
|
|
33
|
+
export declare const PositiveInteger: import("arktype/out/variants/number").NumberType<number, {}>;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a validated array with minimum and maximum length constraints
|
|
36
|
+
*/
|
|
37
|
+
export declare const createConstrainedArray: (itemType: "string" | "number" | "boolean", constraints?: {
|
|
38
|
+
minLength?: number;
|
|
39
|
+
maxLength?: number;
|
|
40
|
+
}) => import("arktype/out/variants/array").ArrayType<(string | number | boolean)[], {}>;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a union type with custom error messages
|
|
43
|
+
*/
|
|
44
|
+
export declare const createUnionWithMessages: <T extends readonly [string, ...string[]]>(literals: T, descriptions?: Record<string, string>) => import("arktype").BaseType<any, {}>;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a morph that transforms data with validation
|
|
47
|
+
*/
|
|
48
|
+
export declare const createSafeMorph: <In, Out>(transformer: (input: In) => Out | Error, errorMessage?: string) => (input: In) => Out;
|
|
49
|
+
/**
|
|
50
|
+
* Type guard helper for arktype validation results
|
|
51
|
+
*/
|
|
52
|
+
export declare const isValid: <T>(result: T | type.errors) => result is T;
|
|
53
|
+
/**
|
|
54
|
+
* Type assertion helper that throws on validation failure
|
|
55
|
+
*/
|
|
56
|
+
export declare const assertValid: <T>(result: T | type.errors, context?: string) => T;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
export const SafePath = type("string").configure({
|
|
3
|
+
description: "a safe file path"
|
|
4
|
+
}).narrow((path, ctx) => {
|
|
5
|
+
if (!path.trim()) {
|
|
6
|
+
return ctx.reject("path cannot be empty or only whitespace");
|
|
7
|
+
}
|
|
8
|
+
if (path.includes("../") || path.includes("..\\")) {
|
|
9
|
+
return ctx.reject("path contains directory traversal which is not allowed");
|
|
10
|
+
}
|
|
11
|
+
if (path.startsWith("/")) {
|
|
12
|
+
console.warn("absolute paths may not work across different environments");
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
});
|
|
16
|
+
export const SafeUrl = type("string").configure({
|
|
17
|
+
description: "a valid URL with allowed protocols"
|
|
18
|
+
}).narrow((url, ctx) => {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = new URL(url);
|
|
21
|
+
const allowedProtocols = ["http:", "https:", "ftp:"];
|
|
22
|
+
if (!allowedProtocols.includes(parsed.protocol)) {
|
|
23
|
+
return ctx.reject({
|
|
24
|
+
expected: `URL with protocol: ${allowedProtocols.join(", ")}`,
|
|
25
|
+
actual: parsed.protocol
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
} catch {
|
|
30
|
+
return ctx.reject("invalid URL format");
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
export const Email = type("string.email").configure({
|
|
34
|
+
description: "a valid email address"
|
|
35
|
+
});
|
|
36
|
+
export const Port = type("number.integer > 0 & number.integer < 65536").configure({
|
|
37
|
+
description: "a valid port number"
|
|
38
|
+
}).narrow((port) => {
|
|
39
|
+
const commonPorts = {
|
|
40
|
+
22: "SSH",
|
|
41
|
+
25: "SMTP",
|
|
42
|
+
53: "DNS",
|
|
43
|
+
80: "HTTP",
|
|
44
|
+
110: "POP3",
|
|
45
|
+
143: "IMAP",
|
|
46
|
+
443: "HTTPS",
|
|
47
|
+
993: "IMAPS",
|
|
48
|
+
995: "POP3S",
|
|
49
|
+
3306: "MySQL",
|
|
50
|
+
5432: "PostgreSQL",
|
|
51
|
+
6379: "Redis",
|
|
52
|
+
8080: "HTTP Alt",
|
|
53
|
+
8443: "HTTPS Alt"
|
|
54
|
+
};
|
|
55
|
+
if (commonPorts[port]) {
|
|
56
|
+
console.warn(`Port ${port} is commonly used by ${commonPorts[port]} - potential conflicts`);
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
export const Semver = type("string.semver").configure({
|
|
61
|
+
description: "a valid semantic version"
|
|
62
|
+
}).narrow((version) => {
|
|
63
|
+
if (version.includes("-")) {
|
|
64
|
+
console.warn("pre-release version detected - ensure compatibility requirements");
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
export const NonEmptyString = type("string").configure({
|
|
69
|
+
description: "a non-empty string"
|
|
70
|
+
}).narrow((str, ctx) => {
|
|
71
|
+
return str.trim().length > 0 || ctx.reject("string cannot be empty or only whitespace");
|
|
72
|
+
});
|
|
73
|
+
export const PositiveInteger = type("number.integer > 0").configure({
|
|
74
|
+
description: "a positive integer"
|
|
75
|
+
});
|
|
76
|
+
export const createConstrainedArray = (itemType, constraints = {}) => {
|
|
77
|
+
const { minLength, maxLength } = constraints;
|
|
78
|
+
return type(itemType).array().configure({
|
|
79
|
+
description: `array of items${minLength ? ` (min ${minLength})` : ""}${maxLength ? ` (max ${maxLength})` : ""}`
|
|
80
|
+
}).narrow((arr, ctx) => {
|
|
81
|
+
if (minLength && arr.length < minLength) {
|
|
82
|
+
return ctx.reject(`array must have at least ${minLength} items`);
|
|
83
|
+
}
|
|
84
|
+
if (maxLength && arr.length > maxLength) {
|
|
85
|
+
return ctx.reject(`array must have at most ${maxLength} items`);
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
export const createUnionWithMessages = (literals, descriptions) => {
|
|
91
|
+
const unionString = literals.map((l) => `'${l}'`).join(" | ");
|
|
92
|
+
return type(unionString).configure({
|
|
93
|
+
description: descriptions ? Object.values(descriptions).join(" | ") : `one of: ${literals.join(", ")}`
|
|
94
|
+
}).narrow((value, ctx) => {
|
|
95
|
+
if (!literals.includes(value)) {
|
|
96
|
+
const expected = descriptions ? Object.entries(descriptions).map(([k, v]) => `${k}: ${v}`).join(", ") : literals.join(", ");
|
|
97
|
+
return ctx.reject({
|
|
98
|
+
expected: `one of: ${expected}`,
|
|
99
|
+
actual: value
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
export const createSafeMorph = (transformer, errorMessage) => {
|
|
106
|
+
return (input) => {
|
|
107
|
+
const result = transformer(input);
|
|
108
|
+
if (result instanceof Error) {
|
|
109
|
+
throw new Error(errorMessage || result.message);
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
export const isValid = (result) => {
|
|
115
|
+
return !(result instanceof type.errors);
|
|
116
|
+
};
|
|
117
|
+
export const assertValid = (result, context) => {
|
|
118
|
+
if (result instanceof type.errors) {
|
|
119
|
+
const message = context ? `${context}: ${result.summary}` : result.summary;
|
|
120
|
+
throw new Error(message);
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reliverse/utils",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "Shared utilities for Reliverse packages",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.d.ts",
|
|
9
|
+
"default": "./dist/mod.js"
|
|
10
|
+
},
|
|
11
|
+
"./validation": {
|
|
12
|
+
"types": "./dist/validation.d.d.ts",
|
|
13
|
+
"default": "./dist/validation.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"arktype": "^2.1.29"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"typescript": ">=5.9.3"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"package.json"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT"
|
|
30
|
+
}
|