@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 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
+ }