@gzl10/ts-helpers 4.2.1
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/CHANGELOG.md +320 -0
- package/README.md +233 -0
- package/USAGE-GUIDE.md +800 -0
- package/dist/browser/async.js +15 -0
- package/dist/browser/async.js.map +1 -0
- package/dist/browser/chunk-4O7ZPIJN.js +383 -0
- package/dist/browser/chunk-4O7ZPIJN.js.map +1 -0
- package/dist/browser/chunk-75XNTC34.js +60 -0
- package/dist/browser/chunk-75XNTC34.js.map +1 -0
- package/dist/browser/chunk-C3D7YZVE.js +299 -0
- package/dist/browser/chunk-C3D7YZVE.js.map +1 -0
- package/dist/browser/chunk-CZL6C2EI.js +452 -0
- package/dist/browser/chunk-CZL6C2EI.js.map +1 -0
- package/dist/browser/chunk-D4FZFIVA.js +240 -0
- package/dist/browser/chunk-D4FZFIVA.js.map +1 -0
- package/dist/browser/chunk-IL7NG7IC.js +72 -0
- package/dist/browser/chunk-IL7NG7IC.js.map +1 -0
- package/dist/browser/chunk-NSBPE2FW.js +17 -0
- package/dist/browser/chunk-NSBPE2FW.js.map +1 -0
- package/dist/browser/chunk-SLQVNPTH.js +27 -0
- package/dist/browser/chunk-SLQVNPTH.js.map +1 -0
- package/dist/browser/chunk-WG7ILCUB.js +195 -0
- package/dist/browser/chunk-WG7ILCUB.js.map +1 -0
- package/dist/browser/chunk-WJA4JDMZ.js +278 -0
- package/dist/browser/chunk-WJA4JDMZ.js.map +1 -0
- package/dist/browser/chunk-ZFVYLUTT.js +65 -0
- package/dist/browser/chunk-ZFVYLUTT.js.map +1 -0
- package/dist/browser/chunk-ZYTSVMTI.js +263 -0
- package/dist/browser/chunk-ZYTSVMTI.js.map +1 -0
- package/dist/browser/dates.js +78 -0
- package/dist/browser/dates.js.map +1 -0
- package/dist/browser/environment-detection.js +21 -0
- package/dist/browser/environment-detection.js.map +1 -0
- package/dist/browser/environment.js +34 -0
- package/dist/browser/environment.js.map +1 -0
- package/dist/browser/errors.js +18 -0
- package/dist/browser/errors.js.map +1 -0
- package/dist/browser/index.js +412 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/math.js +51 -0
- package/dist/browser/math.js.map +1 -0
- package/dist/browser/number.js +10 -0
- package/dist/browser/number.js.map +1 -0
- package/dist/browser/objects.js +31 -0
- package/dist/browser/objects.js.map +1 -0
- package/dist/browser/strings.js +80 -0
- package/dist/browser/strings.js.map +1 -0
- package/dist/browser/validation-core.js +54 -0
- package/dist/browser/validation-core.js.map +1 -0
- package/dist/browser/validation-crypto.js +28 -0
- package/dist/browser/validation-crypto.js.map +1 -0
- package/dist/browser/validators.js +98 -0
- package/dist/browser/validators.js.map +1 -0
- package/dist/cjs/async.js +86 -0
- package/dist/cjs/async.js.map +1 -0
- package/dist/cjs/dates.js +285 -0
- package/dist/cjs/dates.js.map +1 -0
- package/dist/cjs/environment-detection.js +84 -0
- package/dist/cjs/environment-detection.js.map +1 -0
- package/dist/cjs/environment.js +261 -0
- package/dist/cjs/environment.js.map +1 -0
- package/dist/cjs/errors.js +80 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +2035 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/math.js +388 -0
- package/dist/cjs/math.js.map +1 -0
- package/dist/cjs/number.js +37 -0
- package/dist/cjs/number.js.map +1 -0
- package/dist/cjs/objects.js +249 -0
- package/dist/cjs/objects.js.map +1 -0
- package/dist/cjs/strings.js +253 -0
- package/dist/cjs/strings.js.map +1 -0
- package/dist/cjs/validation.js +450 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/esm/async.js +15 -0
- package/dist/esm/async.js.map +1 -0
- package/dist/esm/chunk-4O7ZPIJN.js +383 -0
- package/dist/esm/chunk-4O7ZPIJN.js.map +1 -0
- package/dist/esm/chunk-75XNTC34.js +60 -0
- package/dist/esm/chunk-75XNTC34.js.map +1 -0
- package/dist/esm/chunk-BDOBKBKA.js +72 -0
- package/dist/esm/chunk-BDOBKBKA.js.map +1 -0
- package/dist/esm/chunk-C3D7YZVE.js +299 -0
- package/dist/esm/chunk-C3D7YZVE.js.map +1 -0
- package/dist/esm/chunk-CZL6C2EI.js +452 -0
- package/dist/esm/chunk-CZL6C2EI.js.map +1 -0
- package/dist/esm/chunk-EBLSTOEC.js +263 -0
- package/dist/esm/chunk-EBLSTOEC.js.map +1 -0
- package/dist/esm/chunk-NSBPE2FW.js +17 -0
- package/dist/esm/chunk-NSBPE2FW.js.map +1 -0
- package/dist/esm/chunk-SLQVNPTH.js +27 -0
- package/dist/esm/chunk-SLQVNPTH.js.map +1 -0
- package/dist/esm/chunk-WG7ILCUB.js +195 -0
- package/dist/esm/chunk-WG7ILCUB.js.map +1 -0
- package/dist/esm/chunk-WJA4JDMZ.js +278 -0
- package/dist/esm/chunk-WJA4JDMZ.js.map +1 -0
- package/dist/esm/chunk-ZFVYLUTT.js +65 -0
- package/dist/esm/chunk-ZFVYLUTT.js.map +1 -0
- package/dist/esm/dates.js +78 -0
- package/dist/esm/dates.js.map +1 -0
- package/dist/esm/environment-detection.js +21 -0
- package/dist/esm/environment-detection.js.map +1 -0
- package/dist/esm/environment.js +34 -0
- package/dist/esm/environment.js.map +1 -0
- package/dist/esm/errors.js +18 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +380 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/math.js +51 -0
- package/dist/esm/math.js.map +1 -0
- package/dist/esm/number.js +10 -0
- package/dist/esm/number.js.map +1 -0
- package/dist/esm/objects.js +31 -0
- package/dist/esm/objects.js.map +1 -0
- package/dist/esm/strings.js +80 -0
- package/dist/esm/strings.js.map +1 -0
- package/dist/esm/validation.js +54 -0
- package/dist/esm/validation.js.map +1 -0
- package/dist/node/async.js +93 -0
- package/dist/node/async.js.map +1 -0
- package/dist/node/csv.js +102 -0
- package/dist/node/csv.js.map +1 -0
- package/dist/node/data.js +880 -0
- package/dist/node/data.js.map +1 -0
- package/dist/node/dates.js +324 -0
- package/dist/node/dates.js.map +1 -0
- package/dist/node/environment.js +278 -0
- package/dist/node/environment.js.map +1 -0
- package/dist/node/errors.js +89 -0
- package/dist/node/errors.js.map +1 -0
- package/dist/node/index.js +3151 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/json.js +107 -0
- package/dist/node/json.js.map +1 -0
- package/dist/node/math.js +413 -0
- package/dist/node/math.js.map +1 -0
- package/dist/node/number.js +42 -0
- package/dist/node/number.js.map +1 -0
- package/dist/node/objects.js +264 -0
- package/dist/node/objects.js.map +1 -0
- package/dist/node/strings.js +293 -0
- package/dist/node/strings.js.map +1 -0
- package/dist/node/tree.js +89 -0
- package/dist/node/tree.js.map +1 -0
- package/dist/node/validation-core.js +477 -0
- package/dist/node/validation-core.js.map +1 -0
- package/dist/node/validation-crypto.js +179 -0
- package/dist/node/validation-crypto.js.map +1 -0
- package/dist/node/validation.js +677 -0
- package/dist/node/validation.js.map +1 -0
- package/dist/node/validators.js +123 -0
- package/dist/node/validators.js.map +1 -0
- package/dist/node-esm/async.js +15 -0
- package/dist/node-esm/async.js.map +1 -0
- package/dist/node-esm/chunk-3YOF7NPT.js +299 -0
- package/dist/node-esm/chunk-3YOF7NPT.js.map +1 -0
- package/dist/node-esm/chunk-64TBXJQS.js +263 -0
- package/dist/node-esm/chunk-64TBXJQS.js.map +1 -0
- package/dist/node-esm/chunk-75XNTC34.js +60 -0
- package/dist/node-esm/chunk-75XNTC34.js.map +1 -0
- package/dist/node-esm/chunk-C4PKXIPB.js +278 -0
- package/dist/node-esm/chunk-C4PKXIPB.js.map +1 -0
- package/dist/node-esm/chunk-CMDFZME3.js +452 -0
- package/dist/node-esm/chunk-CMDFZME3.js.map +1 -0
- package/dist/node-esm/chunk-DZZPUYMP.js +74 -0
- package/dist/node-esm/chunk-DZZPUYMP.js.map +1 -0
- package/dist/node-esm/chunk-HTSEHRHI.js +195 -0
- package/dist/node-esm/chunk-HTSEHRHI.js.map +1 -0
- package/dist/node-esm/chunk-JCAUVOPH.js +27 -0
- package/dist/node-esm/chunk-JCAUVOPH.js.map +1 -0
- package/dist/node-esm/chunk-KBHE3K2F.js +505 -0
- package/dist/node-esm/chunk-KBHE3K2F.js.map +1 -0
- package/dist/node-esm/chunk-LYTET5NX.js +65 -0
- package/dist/node-esm/chunk-LYTET5NX.js.map +1 -0
- package/dist/node-esm/chunk-PZ5AY32C.js +10 -0
- package/dist/node-esm/chunk-PZ5AY32C.js.map +1 -0
- package/dist/node-esm/chunk-UKGXL2QO.js +383 -0
- package/dist/node-esm/chunk-UKGXL2QO.js.map +1 -0
- package/dist/node-esm/chunk-XAEYT23H.js +164 -0
- package/dist/node-esm/chunk-XAEYT23H.js.map +1 -0
- package/dist/node-esm/csv.js +63 -0
- package/dist/node-esm/csv.js.map +1 -0
- package/dist/node-esm/data.js +32 -0
- package/dist/node-esm/data.js.map +1 -0
- package/dist/node-esm/dates.js +78 -0
- package/dist/node-esm/dates.js.map +1 -0
- package/dist/node-esm/environment.js +34 -0
- package/dist/node-esm/environment.js.map +1 -0
- package/dist/node-esm/errors.js +18 -0
- package/dist/node-esm/errors.js.map +1 -0
- package/dist/node-esm/index.js +426 -0
- package/dist/node-esm/index.js.map +1 -0
- package/dist/node-esm/json.js +68 -0
- package/dist/node-esm/json.js.map +1 -0
- package/dist/node-esm/math.js +51 -0
- package/dist/node-esm/math.js.map +1 -0
- package/dist/node-esm/number.js +10 -0
- package/dist/node-esm/number.js.map +1 -0
- package/dist/node-esm/objects.js +31 -0
- package/dist/node-esm/objects.js.map +1 -0
- package/dist/node-esm/strings.js +80 -0
- package/dist/node-esm/strings.js.map +1 -0
- package/dist/node-esm/tree.js +8 -0
- package/dist/node-esm/tree.js.map +1 -0
- package/dist/node-esm/validation-core.js +54 -0
- package/dist/node-esm/validation-core.js.map +1 -0
- package/dist/node-esm/validation-crypto.js +26 -0
- package/dist/node-esm/validation-crypto.js.map +1 -0
- package/dist/node-esm/validation.js +606 -0
- package/dist/node-esm/validation.js.map +1 -0
- package/dist/node-esm/validators.js +98 -0
- package/dist/node-esm/validators.js.map +1 -0
- package/dist/types/async-C8gvbSG-.d.ts +453 -0
- package/dist/types/async.d.ts +1 -0
- package/dist/types/csv.d.ts +226 -0
- package/dist/types/data.d.ts +1561 -0
- package/dist/types/dates-hTiE0Z11.d.ts +298 -0
- package/dist/types/dates.d.ts +1 -0
- package/dist/types/environment-B8eLS7KT.d.ts +420 -0
- package/dist/types/environment-detection.d.ts +102 -0
- package/dist/types/environment.d.ts +1 -0
- package/dist/types/errors.d.ts +147 -0
- package/dist/types/index.d.ts +211 -0
- package/dist/types/json.d.ts +284 -0
- package/dist/types/math-BQ9Lwdp7.d.ts +2060 -0
- package/dist/types/math.d.ts +1 -0
- package/dist/types/number-CYnQfLWj.d.ts +44 -0
- package/dist/types/number.d.ts +1 -0
- package/dist/types/objects-BohS8GCS.d.ts +1185 -0
- package/dist/types/objects.d.ts +1 -0
- package/dist/types/strings-CiqRPYLL.d.ts +1349 -0
- package/dist/types/strings.d.ts +1 -0
- package/dist/types/tree.d.ts +284 -0
- package/dist/types/validation-core-DfHF8rCG.d.ts +238 -0
- package/dist/types/validation-crypto-browser.d.ts +56 -0
- package/dist/types/validation-crypto-node.d.ts +31 -0
- package/dist/types/validation.d.ts +1 -0
- package/dist/types/validators.d.ts +216 -0
- package/package.json +253 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-PZ5AY32C.js";
|
|
4
|
+
|
|
5
|
+
// src/node/validation-crypto.ts
|
|
6
|
+
var validation_crypto_exports = {};
|
|
7
|
+
__export(validation_crypto_exports, {
|
|
8
|
+
escapeShellCommand: () => escapeShellCommand,
|
|
9
|
+
generateNonce: () => generateNonce,
|
|
10
|
+
generateSecureToken: () => generateSecureToken,
|
|
11
|
+
hashString: () => hashString,
|
|
12
|
+
isSecureUrl: () => isSecureUrl,
|
|
13
|
+
isValidBase64: () => isValidBase64,
|
|
14
|
+
isValidJWTFormat: () => isValidJWTFormat,
|
|
15
|
+
removeDangerousChars: () => removeDangerousChars,
|
|
16
|
+
sanitizeHtml: () => sanitizeHtml,
|
|
17
|
+
validatePassword: () => validatePassword
|
|
18
|
+
});
|
|
19
|
+
import { createHash, randomBytes } from "crypto";
|
|
20
|
+
var validatePassword = (password, criteria = {}) => {
|
|
21
|
+
const {
|
|
22
|
+
minLength = 8,
|
|
23
|
+
requireUppercase = true,
|
|
24
|
+
requireLowercase = true,
|
|
25
|
+
requireNumbers = true,
|
|
26
|
+
requireSpecialChars = true,
|
|
27
|
+
maxLength = 128,
|
|
28
|
+
forbiddenPatterns = []
|
|
29
|
+
} = criteria;
|
|
30
|
+
const errors = [];
|
|
31
|
+
let score = 0;
|
|
32
|
+
if (password.length < minLength) {
|
|
33
|
+
errors.push(`La contrase\xF1a debe tener al menos ${minLength} caracteres`);
|
|
34
|
+
} else {
|
|
35
|
+
score += 20;
|
|
36
|
+
}
|
|
37
|
+
if (password.length > maxLength) {
|
|
38
|
+
errors.push(`La contrase\xF1a no puede tener m\xE1s de ${maxLength} caracteres`);
|
|
39
|
+
}
|
|
40
|
+
if (requireUppercase && !/[A-Z]/.test(password)) {
|
|
41
|
+
errors.push("La contrase\xF1a debe contener al menos una letra may\xFAscula");
|
|
42
|
+
} else if (/[A-Z]/.test(password)) {
|
|
43
|
+
score += 15;
|
|
44
|
+
}
|
|
45
|
+
if (requireLowercase && !/[a-z]/.test(password)) {
|
|
46
|
+
errors.push("La contrase\xF1a debe contener al menos una letra min\xFAscula");
|
|
47
|
+
} else if (/[a-z]/.test(password)) {
|
|
48
|
+
score += 15;
|
|
49
|
+
}
|
|
50
|
+
if (requireNumbers && !/\d/.test(password)) {
|
|
51
|
+
errors.push("La contrase\xF1a debe contener al menos un n\xFAmero");
|
|
52
|
+
} else if (/\d/.test(password)) {
|
|
53
|
+
score += 15;
|
|
54
|
+
}
|
|
55
|
+
if (requireSpecialChars && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
56
|
+
errors.push("La contrase\xF1a debe contener al menos un caracter especial");
|
|
57
|
+
} else if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
58
|
+
score += 15;
|
|
59
|
+
}
|
|
60
|
+
for (const pattern of forbiddenPatterns) {
|
|
61
|
+
if (password.toLowerCase().includes(pattern.toLowerCase())) {
|
|
62
|
+
errors.push(`La contrase\xF1a no puede contener: ${pattern}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (password.length >= 12) score += 10;
|
|
66
|
+
if (password.length >= 16) score += 10;
|
|
67
|
+
if (/(.)\\1{2,}/.test(password)) score -= 10;
|
|
68
|
+
if (/123|abc|qwe/i.test(password)) score -= 15;
|
|
69
|
+
score = Math.max(0, Math.min(100, score));
|
|
70
|
+
let strength;
|
|
71
|
+
if (score < 30) strength = "weak";
|
|
72
|
+
else if (score < 60) strength = "fair";
|
|
73
|
+
else if (score < 80) strength = "good";
|
|
74
|
+
else strength = "strong";
|
|
75
|
+
return {
|
|
76
|
+
isValid: errors.length === 0,
|
|
77
|
+
errors,
|
|
78
|
+
strength,
|
|
79
|
+
score
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
var sanitizeHtml = (html) => {
|
|
83
|
+
if (!html) return "";
|
|
84
|
+
let sanitized = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
|
|
85
|
+
sanitized = sanitized.replace(/ on\w+="[^"]*"/gi, "");
|
|
86
|
+
sanitized = sanitized.replace(/ on\w+='[^']*'/gi, "");
|
|
87
|
+
sanitized = sanitized.replace(/javascript:/gi, "");
|
|
88
|
+
sanitized = sanitized.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, "");
|
|
89
|
+
sanitized = sanitized.replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, "");
|
|
90
|
+
sanitized = sanitized.replace(/<embed\b[^>]*>/gi, "");
|
|
91
|
+
return sanitized.trim();
|
|
92
|
+
};
|
|
93
|
+
var isValidJWTFormat = (token) => {
|
|
94
|
+
if (!token || typeof token !== "string") return false;
|
|
95
|
+
const parts = token.split(".");
|
|
96
|
+
if (parts.length !== 3) return false;
|
|
97
|
+
try {
|
|
98
|
+
for (const part of parts) {
|
|
99
|
+
if (!part || !/^[A-Za-z0-9_-]+$/.test(part)) return false;
|
|
100
|
+
atob(part.replace(/-/g, "+").replace(/_/g, "/"));
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var hashString = (input, salt = "") => {
|
|
108
|
+
return createHash("sha256").update(input + salt).digest("hex");
|
|
109
|
+
};
|
|
110
|
+
var generateSecureToken = (length = 32) => {
|
|
111
|
+
return randomBytes(length).toString("hex");
|
|
112
|
+
};
|
|
113
|
+
var isValidBase64 = (input) => {
|
|
114
|
+
if (!input || typeof input !== "string") return false;
|
|
115
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input)) return false;
|
|
116
|
+
try {
|
|
117
|
+
const decoded = atob(input);
|
|
118
|
+
const reencoded = btoa(decoded);
|
|
119
|
+
return reencoded === input;
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var escapeShellCommand = (input) => {
|
|
125
|
+
if (!input) return "";
|
|
126
|
+
return input.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/;/g, "\\;").replace(/&/g, "\\&").replace(/\|/g, "\\|").replace(/`/g, "\\`").replace(/\$/g, "\\$").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/</g, "\\\\<").replace(/>/g, "\\\\>");
|
|
127
|
+
};
|
|
128
|
+
var isSecureUrl = (url) => {
|
|
129
|
+
if (!url || typeof url !== "string") return false;
|
|
130
|
+
try {
|
|
131
|
+
const parsed = new URL(url);
|
|
132
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var removeDangerousChars = (input, replacement = "") => {
|
|
138
|
+
if (!input) return "";
|
|
139
|
+
return input.replace(/[<>]/g, replacement).replace(/['"]/g, replacement).replace(/[&]/g, replacement).replace(/[\\x00-\\x1f\\x7f]/g, replacement);
|
|
140
|
+
};
|
|
141
|
+
var generateNonce = (length = 32) => {
|
|
142
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
143
|
+
let result = "";
|
|
144
|
+
const bytes = randomBytes(length);
|
|
145
|
+
for (let i = 0; i < length; i++) {
|
|
146
|
+
result += chars[bytes[i] % chars.length];
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
validatePassword,
|
|
153
|
+
sanitizeHtml,
|
|
154
|
+
isValidJWTFormat,
|
|
155
|
+
hashString,
|
|
156
|
+
generateSecureToken,
|
|
157
|
+
isValidBase64,
|
|
158
|
+
escapeShellCommand,
|
|
159
|
+
isSecureUrl,
|
|
160
|
+
removeDangerousChars,
|
|
161
|
+
generateNonce,
|
|
162
|
+
validation_crypto_exports
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=chunk-XAEYT23H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/node/validation-crypto.ts"],"sourcesContent":["/**\n * Node.js-specific validation utilities with crypto support\n * Uses Node.js crypto module for secure operations\n */\n\n/* eslint-disable complexity */\n\nimport { createHash, randomBytes } from 'crypto'\n\n// =============================================================================\n// PASSWORD VALIDATION (Node.js with crypto)\n// =============================================================================\n\nexport interface PasswordCriteria {\n minLength?: number\n requireUppercase?: boolean\n requireLowercase?: boolean\n requireNumbers?: boolean\n requireSpecialChars?: boolean\n maxLength?: number\n forbiddenPatterns?: string[]\n}\n\nexport interface PasswordValidationResult {\n isValid: boolean\n errors: string[]\n strength: 'weak' | 'fair' | 'good' | 'strong'\n score: number // 0-100\n}\n\nexport const validatePassword = (\n password: string,\n criteria: PasswordCriteria = {}\n): PasswordValidationResult => {\n const {\n minLength = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumbers = true,\n requireSpecialChars = true,\n maxLength = 128,\n forbiddenPatterns = [],\n } = criteria\n\n const errors: string[] = []\n let score = 0\n\n if (password.length < minLength) {\n errors.push(`La contraseña debe tener al menos ${minLength} caracteres`)\n } else {\n score += 20\n }\n\n if (password.length > maxLength) {\n errors.push(`La contraseña no puede tener más de ${maxLength} caracteres`)\n }\n\n if (requireUppercase && !/[A-Z]/.test(password)) {\n errors.push('La contraseña debe contener al menos una letra mayúscula')\n } else if (/[A-Z]/.test(password)) {\n score += 15\n }\n\n if (requireLowercase && !/[a-z]/.test(password)) {\n errors.push('La contraseña debe contener al menos una letra minúscula')\n } else if (/[a-z]/.test(password)) {\n score += 15\n }\n\n if (requireNumbers && !/\\d/.test(password)) {\n errors.push('La contraseña debe contener al menos un número')\n } else if (/\\d/.test(password)) {\n score += 15\n }\n\n if (requireSpecialChars && !/[!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?]/.test(password)) {\n errors.push('La contraseña debe contener al menos un caracter especial')\n } else if (/[!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?]/.test(password)) {\n score += 15\n }\n\n for (const pattern of forbiddenPatterns) {\n if (password.toLowerCase().includes(pattern.toLowerCase())) {\n errors.push(`La contraseña no puede contener: ${pattern}`)\n }\n }\n\n if (password.length >= 12) score += 10\n if (password.length >= 16) score += 10\n\n if (/(.)\\\\1{2,}/.test(password)) score -= 10\n if (/123|abc|qwe/i.test(password)) score -= 15\n\n score = Math.max(0, Math.min(100, score))\n\n let strength: 'weak' | 'fair' | 'good' | 'strong'\n if (score < 30) strength = 'weak'\n else if (score < 60) strength = 'fair'\n else if (score < 80) strength = 'good'\n else strength = 'strong'\n\n return {\n isValid: errors.length === 0,\n errors,\n strength,\n score,\n }\n}\n\n// =============================================================================\n// SECURITY FUNCTIONS (Node.js crypto)\n// =============================================================================\n\nexport const sanitizeHtml = (html: string): string => {\n if (!html) return ''\n\n let sanitized = html\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '')\n\n sanitized = sanitized.replace(/ on\\w+=\"[^\"]*\"/gi, '')\n sanitized = sanitized.replace(/ on\\w+='[^']*'/gi, '')\n sanitized = sanitized.replace(/javascript:/gi, '')\n sanitized = sanitized.replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '')\n sanitized = sanitized.replace(/<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi, '')\n sanitized = sanitized.replace(/<embed\\b[^>]*>/gi, '')\n\n return sanitized.trim()\n}\n\nexport const isValidJWTFormat = (token: string): boolean => {\n if (!token || typeof token !== 'string') return false\n\n const parts = token.split('.')\n if (parts.length !== 3) return false\n\n try {\n for (const part of parts) {\n if (!part || !/^[A-Za-z0-9_-]+$/.test(part)) return false\n atob(part.replace(/-/g, '+').replace(/_/g, '/'))\n }\n return true\n } catch {\n return false\n }\n}\n\nexport const hashString = (input: string, salt = ''): string => {\n return createHash('sha256')\n .update(input + salt)\n .digest('hex')\n}\n\nexport const generateSecureToken = (length = 32): string => {\n return randomBytes(length).toString('hex')\n}\n\nexport const isValidBase64 = (input: string): boolean => {\n if (!input || typeof input !== 'string') return false\n\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input)) return false\n\n try {\n const decoded = atob(input)\n const reencoded = btoa(decoded)\n return reencoded === input\n } catch {\n return false\n }\n}\n\nexport const escapeShellCommand = (input: string): string => {\n if (!input) return ''\n\n return input\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\"/g, '\\\\\"')\n .replace(/;/g, '\\\\;')\n .replace(/&/g, '\\\\&')\n .replace(/\\|/g, '\\\\|')\n .replace(/`/g, '\\\\`')\n .replace(/\\$/g, '\\\\$')\n .replace(/\\(/g, '\\\\(')\n .replace(/\\)/g, '\\\\)')\n .replace(/</g, '\\\\\\\\<')\n .replace(/>/g, '\\\\\\\\>')\n}\n\nexport const isSecureUrl = (url: string): boolean => {\n if (!url || typeof url !== 'string') return false\n\n try {\n const parsed = new URL(url)\n return (\n parsed.protocol === 'https:' ||\n (parsed.protocol === 'http:' &&\n (parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1'))\n )\n } catch {\n return false\n }\n}\n\nexport const removeDangerousChars = (input: string, replacement = ''): string => {\n if (!input) return ''\n\n return input\n .replace(/[<>]/g, replacement)\n .replace(/['\"]/g, replacement)\n .replace(/[&]/g, replacement)\n .replace(/[\\\\x00-\\\\x1f\\\\x7f]/g, replacement)\n}\n\nexport const generateNonce = (length = 32): string => {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n let result = ''\n\n const bytes = randomBytes(length)\n for (let i = 0; i < length; i++) {\n result += chars[bytes[i] % chars.length]\n }\n\n return result\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isNode
|
|
3
|
+
} from "./chunk-64TBXJQS.js";
|
|
4
|
+
import "./chunk-PZ5AY32C.js";
|
|
5
|
+
|
|
6
|
+
// src/csv.ts
|
|
7
|
+
import Papa from "papaparse";
|
|
8
|
+
async function exportCSV(data, filePath, options) {
|
|
9
|
+
if (data == null) {
|
|
10
|
+
throw new TypeError("Data cannot be null or undefined");
|
|
11
|
+
}
|
|
12
|
+
if (!Array.isArray(data)) {
|
|
13
|
+
throw new TypeError("Data must be an array");
|
|
14
|
+
}
|
|
15
|
+
if (data.length === 0) {
|
|
16
|
+
throw new Error("Data array cannot be empty");
|
|
17
|
+
}
|
|
18
|
+
if (!filePath || typeof filePath !== "string" || filePath.trim() === "") {
|
|
19
|
+
throw new TypeError("File path must be a non-empty string");
|
|
20
|
+
}
|
|
21
|
+
const csvText = Papa.unparse(data, {
|
|
22
|
+
delimiter: ";",
|
|
23
|
+
header: true,
|
|
24
|
+
...options
|
|
25
|
+
});
|
|
26
|
+
if (isNode()) {
|
|
27
|
+
const fs = await import("fs/promises");
|
|
28
|
+
await fs.writeFile(filePath, `\uFEFF${csvText}`, { encoding: "utf-8" });
|
|
29
|
+
} else {
|
|
30
|
+
const blob = new Blob([`\uFEFF${csvText}`], { type: "text/csv;charset=utf-8" });
|
|
31
|
+
const url = URL.createObjectURL(blob);
|
|
32
|
+
const link = document.createElement("a");
|
|
33
|
+
link.href = url;
|
|
34
|
+
link.download = filePath.split("/").pop() || "data.csv";
|
|
35
|
+
document.body.appendChild(link);
|
|
36
|
+
link.click();
|
|
37
|
+
document.body.removeChild(link);
|
|
38
|
+
URL.revokeObjectURL(url);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function importCSV(filePath, options) {
|
|
42
|
+
if (!filePath || typeof filePath !== "string" || filePath.trim() === "") {
|
|
43
|
+
throw new TypeError("File path must be a non-empty string");
|
|
44
|
+
}
|
|
45
|
+
if (isNode()) {
|
|
46
|
+
const fs = await import("fs/promises");
|
|
47
|
+
const content = await fs.readFile(filePath, { encoding: "utf-8" });
|
|
48
|
+
const parseResult = Papa.parse(content, {
|
|
49
|
+
header: true,
|
|
50
|
+
delimiter: ";",
|
|
51
|
+
skipEmptyLines: true,
|
|
52
|
+
...options
|
|
53
|
+
});
|
|
54
|
+
return parseResult.data || [];
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error("CSV import not supported in browser. Use readFileAsText() with a File object.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
exportCSV,
|
|
61
|
+
importCSV
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/csv.ts"],"sourcesContent":["/**\n * CSV Import/Export utilities\n *\n * Provides reliable CSV operations for both Node.js and Browser environments using PapaParse.\n * Features:\n * - UTF-8 BOM encoding for Excel compatibility\n * - Semicolon delimiter by default (European standard)\n * - Automatic header detection\n * - Dual-mode: filesystem (Node.js) vs download trigger (Browser)\n *\n * @module csv\n */\n\nimport Papa from 'papaparse'\nimport { isNode } from './environment'\n\n/**\n * Exports data as CSV file with UTF-8 BOM encoding\n *\n * Works in both Node.js (writes to filesystem) and Browser (triggers download).\n * Uses PapaParse library for reliable CSV generation with proper escaping and formatting.\n *\n * Features:\n * - UTF-8 BOM prepended (\\\\ufeff) for Excel compatibility\n * - Semicolon delimiter by default (European/Spanish standard)\n * - Automatic header row from object keys\n * - Custom delimiters and options via PapaParse config\n *\n * Environment behavior:\n * - **Node.js**: Writes file to filesystem at specified path\n * - **Browser**: Triggers automatic download with filename extracted from path\n *\n * @param data - Array of objects or array of arrays to export as CSV\n * @param filePath - File path (Node.js) or download filename (Browser)\n * @param options - PapaParse unparse options (optional)\n * @param options.delimiter - Column separator (default: ';' semicolon)\n * @param options.header - Include header row (default: true)\n * @param options.quotes - Quote all fields (default: false)\n * @param options.newline - Line ending (default: '\\\\r\\\\n')\n * @returns Promise that resolves when export completes\n *\n * @example\n * ```typescript\n * // Basic export - Array of objects\n * const users = [\n * { name: 'Alice', age: 30, city: 'Madrid' },\n * { name: 'Bob', age: 25, city: 'Barcelona' },\n * { name: 'Carlos', age: 35, city: 'Valencia' }\n * ]\n *\n * // Node.js - Write to file\n * await exportCSV(users, './reports/users.csv')\n * // Creates: ./reports/users.csv with BOM and semicolon delimiter\n *\n * // Browser - Trigger download\n * await exportCSV(users, 'users.csv')\n * // Downloads: users.csv to browser's download folder\n *\n * // Custom delimiter (comma for international)\n * await exportCSV(users, 'users_intl.csv', { delimiter: ',' })\n * ```\n *\n * @example\n * ```typescript\n * // Array of arrays (no header auto-detection)\n * const matrix = [\n * ['Name', 'Age', 'City'], // Header row\n * ['Alice', 30, 'Madrid'],\n * ['Bob', 25, 'Barcelona']\n * ]\n * await exportCSV(matrix, 'matrix.csv')\n *\n * // Without header row\n * const data = [['A1', 'B1'], ['A2', 'B2']]\n * await exportCSV(data, 'no_header.csv', { header: false })\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Export sales report\n * async function exportSalesReport(sales: Sale[]) {\n * const reportData = sales.map(sale => ({\n * Fecha: formatDate(sale.date),\n * Cliente: sale.customerName,\n * Producto: sale.productName,\n * Cantidad: sale.quantity,\n * Total: `${sale.total.toFixed(2)}€`\n * }))\n *\n * const filename = `ventas_${new Date().toISOString().split('T')[0]}.csv`\n * await exportCSV(reportData, filename)\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Custom PapaParse options\n * await exportCSV(data, 'quotes.csv', {\n * delimiter: ',',\n * quotes: true, // Quote all fields\n * quoteChar: '\"',\n * escapeChar: '\"',\n * newline: '\\\\n' // Unix line endings\n * })\n * ```\n *\n * @throws {Error} If file write fails in Node.js\n * @see {@link importCSV} for importing CSV files\n * @see {@link https://www.papaparse.com/docs#unparse PapaParse Unparse Documentation}\n */\nexport async function exportCSV(data: any[], filePath: string, options?: any): Promise<void> {\n // ✅ Input validation\n if (data == null) {\n throw new TypeError('Data cannot be null or undefined')\n }\n\n if (!Array.isArray(data)) {\n throw new TypeError('Data must be an array')\n }\n\n if (data.length === 0) {\n throw new Error('Data array cannot be empty')\n }\n\n if (!filePath || typeof filePath !== 'string' || filePath.trim() === '') {\n throw new TypeError('File path must be a non-empty string')\n }\n\n const csvText = Papa.unparse(data, {\n delimiter: ';',\n header: true,\n ...options,\n })\n\n if (isNode()) {\n const fs = await import('fs/promises')\n await fs.writeFile(filePath, `\\ufeff${csvText}`, { encoding: 'utf-8' })\n } else {\n const blob = new Blob([`\\ufeff${csvText}`], { type: 'text/csv;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = filePath.split('/').pop() || 'data.csv'\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n URL.revokeObjectURL(url)\n }\n}\n\n/**\n * Imports CSV file and parses it to array of objects\n *\n * Reads CSV file from filesystem (Node.js only) and parses using PapaParse.\n * Automatically detects headers and converts rows to objects.\n *\n * Features:\n * - Automatic header detection from first row\n * - Semicolon delimiter by default (European standard)\n * - Empty line skipping\n * - Type inference for numbers and booleans\n * - UTF-8 BOM handling\n *\n * ⚠️ BROWSER LIMITATION: File reading from filesystem is not supported in browsers\n * for security reasons. For browser file uploads, use `readFileAsText()` with a File object\n * obtained from an input[type=\"file\"] element.\n *\n * @param filePath - Path to CSV file (Node.js only)\n * @param options - PapaParse parse options (optional)\n * @param options.delimiter - Column separator (default: ';' semicolon)\n * @param options.header - Parse first row as headers (default: true)\n * @param options.skipEmptyLines - Skip empty rows (default: true)\n * @param options.dynamicTyping - Convert numeric/boolean values (default: false)\n * @returns Promise<Array<Object>> Array of objects with keys from header row\n *\n * @example\n * ```typescript\n * // Basic import - Node.js only\n * const users = await importCSV('./data/users.csv')\n * // Returns: [\n * // { name: 'Alice', age: '30', city: 'Madrid' },\n * // { name: 'Bob', age: '25', city: 'Barcelona' }\n * // ]\n *\n * // Custom delimiter (comma)\n * const intlData = await importCSV('./data/users_intl.csv', {\n * delimiter: ','\n * })\n *\n * // With type conversion\n * const typed = await importCSV('./data/sales.csv', {\n * dynamicTyping: true // Converts '123' → 123, 'true' → true\n * })\n * // Returns: { quantity: 10, total: 299.99, active: true }\n * ```\n *\n * @example\n * ```typescript\n * // Real-world: Import and process sales data\n * async function importSalesReport(filePath: string) {\n * try {\n * const sales = await importCSV(filePath, {\n * delimiter: ';',\n * dynamicTyping: true,\n * skipEmptyLines: true\n * })\n *\n * // Process imported data\n * const totalSales = sales.reduce((sum, sale) =>\n * sum + (sale.total || 0), 0\n * )\n *\n * console.log(`Imported ${sales.length} sales, total: €${totalSales}`)\n * return sales\n * } catch (error) {\n * console.error('Failed to import CSV:', error)\n * throw error\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Browser alternative using File API\n * // HTML: <input type=\"file\" id=\"csvFile\" accept=\".csv\">\n *\n * document.getElementById('csvFile').addEventListener('change', async (e) => {\n * const file = e.target.files[0]\n *\n * // Read file content\n * const content = await readFileAsText(file)\n *\n * // Parse with PapaParse\n * const parsed = Papa.parse(content, {\n * header: true,\n * delimiter: ';',\n * skipEmptyLines: true\n * })\n *\n * const data = parsed.data\n * console.log('Imported data:', data)\n * })\n * ```\n *\n * @example\n * ```typescript\n * // Handle parsing errors\n * const result = await importCSV('./malformed.csv')\n * .catch(error => {\n * if (error.message.includes('not supported in browser')) {\n * console.error('Use File API for browser uploads')\n * } else if (error.code === 'ENOENT') {\n * console.error('File not found')\n * } else {\n * console.error('CSV parsing failed:', error)\n * }\n * return [] // Return empty array as fallback\n * })\n * ```\n *\n * @throws {Error} 'CSV import not supported in browser' when called in browser environment\n * @throws {Error} File system errors (ENOENT, EACCES, etc.) in Node.js\n * @see {@link exportCSV} for exporting CSV files\n * @see {@link readFileAsText} for browser file reading\n * @see {@link https://www.papaparse.com/docs#parse PapaParse Parse Documentation}\n */\nexport async function importCSV(filePath: string, options?: any): Promise<any[]> {\n // ✅ Input validation\n if (!filePath || typeof filePath !== 'string' || filePath.trim() === '') {\n throw new TypeError('File path must be a non-empty string')\n }\n\n if (isNode()) {\n const fs = await import('fs/promises')\n const content = await fs.readFile(filePath, { encoding: 'utf-8' })\n const parseResult = Papa.parse(content, {\n header: true,\n delimiter: ';',\n skipEmptyLines: true,\n ...options,\n }) as any\n return parseResult.data || []\n } else {\n throw new Error('CSV import not supported in browser. Use readFileAsText() with a File object.')\n }\n}\n"],"mappings":";;;;;;AAaA,OAAO,UAAU;AAiGjB,eAAsB,UAAU,MAAa,UAAkB,SAA8B;AAE3F,MAAI,QAAQ,MAAM;AAChB,UAAM,IAAI,UAAU,kCAAkC;AAAA,EACxD;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,UAAM,IAAI,UAAU,uBAAuB;AAAA,EAC7C;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAEA,MAAI,CAAC,YAAY,OAAO,aAAa,YAAY,SAAS,KAAK,MAAM,IAAI;AACvE,UAAM,IAAI,UAAU,sCAAsC;AAAA,EAC5D;AAEA,QAAM,UAAU,KAAK,QAAQ,MAAM;AAAA,IACjC,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,GAAG;AAAA,EACL,CAAC;AAED,MAAI,OAAO,GAAG;AACZ,UAAM,KAAK,MAAM,OAAO,aAAa;AACrC,UAAM,GAAG,UAAU,UAAU,SAAS,OAAO,IAAI,EAAE,UAAU,QAAQ,CAAC;AAAA,EACxE,OAAO;AACL,UAAM,OAAO,IAAI,KAAK,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9E,UAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,UAAM,OAAO,SAAS,cAAc,GAAG;AACvC,SAAK,OAAO;AACZ,SAAK,WAAW,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAC7C,aAAS,KAAK,YAAY,IAAI;AAC9B,SAAK,MAAM;AACX,aAAS,KAAK,YAAY,IAAI;AAC9B,QAAI,gBAAgB,GAAG;AAAA,EACzB;AACF;AAsHA,eAAsB,UAAU,UAAkB,SAA+B;AAE/E,MAAI,CAAC,YAAY,OAAO,aAAa,YAAY,SAAS,KAAK,MAAM,IAAI;AACvE,UAAM,IAAI,UAAU,sCAAsC;AAAA,EAC5D;AAEA,MAAI,OAAO,GAAG;AACZ,UAAM,KAAK,MAAM,OAAO,aAAa;AACrC,UAAM,UAAU,MAAM,GAAG,SAAS,UAAU,EAAE,UAAU,QAAQ,CAAC;AACjE,UAAM,cAAc,KAAK,MAAM,SAAS;AAAA,MACtC,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL,CAAC;AACD,WAAO,YAAY,QAAQ,CAAC;AAAA,EAC9B,OAAO;AACL,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AACF;","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectFileExtension,
|
|
3
|
+
detectFormatFromFilename,
|
|
4
|
+
detectUniversalFormat,
|
|
5
|
+
exportData,
|
|
6
|
+
exportTree,
|
|
7
|
+
exportTxt,
|
|
8
|
+
importData,
|
|
9
|
+
importTree,
|
|
10
|
+
importTxt,
|
|
11
|
+
readFileAsText,
|
|
12
|
+
validateCSVData,
|
|
13
|
+
validateExportData
|
|
14
|
+
} from "./chunk-KBHE3K2F.js";
|
|
15
|
+
import "./chunk-75XNTC34.js";
|
|
16
|
+
import "./chunk-64TBXJQS.js";
|
|
17
|
+
import "./chunk-PZ5AY32C.js";
|
|
18
|
+
export {
|
|
19
|
+
detectFileExtension,
|
|
20
|
+
detectFormatFromFilename,
|
|
21
|
+
detectUniversalFormat,
|
|
22
|
+
exportData,
|
|
23
|
+
exportTree,
|
|
24
|
+
exportTxt,
|
|
25
|
+
importData,
|
|
26
|
+
importTree,
|
|
27
|
+
importTxt,
|
|
28
|
+
readFileAsText,
|
|
29
|
+
validateCSVData,
|
|
30
|
+
validateExportData
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addDays,
|
|
3
|
+
addMonths,
|
|
4
|
+
addNowDays,
|
|
5
|
+
addNowMonths,
|
|
6
|
+
addNowSeconds,
|
|
7
|
+
addNowYears,
|
|
8
|
+
addSeconds,
|
|
9
|
+
addYears,
|
|
10
|
+
areDatesEqualWithTolerance,
|
|
11
|
+
dayOfWeek,
|
|
12
|
+
diffBusinessDays,
|
|
13
|
+
diffDays,
|
|
14
|
+
diffMilliSeconds,
|
|
15
|
+
diffMonths,
|
|
16
|
+
diffYears,
|
|
17
|
+
excelToDate,
|
|
18
|
+
format,
|
|
19
|
+
formatForMysql,
|
|
20
|
+
formatNow,
|
|
21
|
+
fromNow,
|
|
22
|
+
getFirstDayOfYear,
|
|
23
|
+
getFirstWorkdayAfterMonths,
|
|
24
|
+
getFirstWorkdayOfMonth,
|
|
25
|
+
getLastDayOfYear,
|
|
26
|
+
getLastWorkdayOfMonth,
|
|
27
|
+
isDateTime,
|
|
28
|
+
isEqualsDateTimeByDay,
|
|
29
|
+
isExpired,
|
|
30
|
+
isNew,
|
|
31
|
+
isWeekday,
|
|
32
|
+
longString,
|
|
33
|
+
now,
|
|
34
|
+
toDate,
|
|
35
|
+
toDateFromString,
|
|
36
|
+
toISO,
|
|
37
|
+
weekOfYear
|
|
38
|
+
} from "./chunk-3YOF7NPT.js";
|
|
39
|
+
import "./chunk-PZ5AY32C.js";
|
|
40
|
+
export {
|
|
41
|
+
addDays,
|
|
42
|
+
addMonths,
|
|
43
|
+
addNowDays,
|
|
44
|
+
addNowMonths,
|
|
45
|
+
addNowSeconds,
|
|
46
|
+
addNowYears,
|
|
47
|
+
addSeconds,
|
|
48
|
+
addYears,
|
|
49
|
+
areDatesEqualWithTolerance,
|
|
50
|
+
dayOfWeek,
|
|
51
|
+
diffBusinessDays,
|
|
52
|
+
diffDays,
|
|
53
|
+
diffMilliSeconds,
|
|
54
|
+
diffMonths,
|
|
55
|
+
diffYears,
|
|
56
|
+
excelToDate,
|
|
57
|
+
format,
|
|
58
|
+
formatForMysql,
|
|
59
|
+
formatNow,
|
|
60
|
+
fromNow,
|
|
61
|
+
getFirstDayOfYear,
|
|
62
|
+
getFirstWorkdayAfterMonths,
|
|
63
|
+
getFirstWorkdayOfMonth,
|
|
64
|
+
getLastDayOfYear,
|
|
65
|
+
getLastWorkdayOfMonth,
|
|
66
|
+
isDateTime,
|
|
67
|
+
isEqualsDateTimeByDay,
|
|
68
|
+
isExpired,
|
|
69
|
+
isNew,
|
|
70
|
+
isWeekday,
|
|
71
|
+
longString,
|
|
72
|
+
now,
|
|
73
|
+
toDate,
|
|
74
|
+
toDateFromString,
|
|
75
|
+
toISO,
|
|
76
|
+
weekOfYear
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=dates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectHostname,
|
|
3
|
+
detectProtocol,
|
|
4
|
+
getEnvironmentInfo,
|
|
5
|
+
isBrowser,
|
|
6
|
+
isBrowserEnvironment,
|
|
7
|
+
isDevelopment,
|
|
8
|
+
isLocalhost,
|
|
9
|
+
isNode,
|
|
10
|
+
isNodeEnvironment,
|
|
11
|
+
isNonProduction,
|
|
12
|
+
isPrivateIP,
|
|
13
|
+
isProduction,
|
|
14
|
+
isTest,
|
|
15
|
+
parseEnvValue
|
|
16
|
+
} from "./chunk-64TBXJQS.js";
|
|
17
|
+
import "./chunk-PZ5AY32C.js";
|
|
18
|
+
export {
|
|
19
|
+
detectHostname,
|
|
20
|
+
detectProtocol,
|
|
21
|
+
getEnvironmentInfo,
|
|
22
|
+
isBrowser,
|
|
23
|
+
isBrowserEnvironment,
|
|
24
|
+
isDevelopment,
|
|
25
|
+
isLocalhost,
|
|
26
|
+
isNode,
|
|
27
|
+
isNodeEnvironment,
|
|
28
|
+
isNonProduction,
|
|
29
|
+
isPrivateIP,
|
|
30
|
+
isProduction,
|
|
31
|
+
isTest,
|
|
32
|
+
parseEnvValue
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataError,
|
|
3
|
+
TsHelpersError,
|
|
4
|
+
TsHelpersErrorCode,
|
|
5
|
+
createCryptoError,
|
|
6
|
+
createMathError,
|
|
7
|
+
createValidationError
|
|
8
|
+
} from "./chunk-75XNTC34.js";
|
|
9
|
+
import "./chunk-PZ5AY32C.js";
|
|
10
|
+
export {
|
|
11
|
+
DataError,
|
|
12
|
+
TsHelpersError,
|
|
13
|
+
TsHelpersErrorCode,
|
|
14
|
+
createCryptoError,
|
|
15
|
+
createMathError,
|
|
16
|
+
createValidationError
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|