easier-http-request 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.
@@ -0,0 +1,127 @@
1
+ import { Timer } from './Timer.js'
2
+
3
+ export function writeToStderr(message: any) {
4
+ process.stderr.write(message)
5
+ }
6
+
7
+ export function logToStderr(message: any) {
8
+ writeToStderr(message)
9
+ writeToStderr('\n')
10
+ }
11
+
12
+ export function formatIntegerWithLeadingZeros(num: number, minDigitCount: number) {
13
+ num = Math.floor(num)
14
+
15
+ let numAsString = `${num}`
16
+
17
+ while (numAsString.length < minDigitCount) {
18
+ numAsString = `0${numAsString}`
19
+ }
20
+
21
+ return numAsString
22
+ }
23
+
24
+ export function roundToDigits(val: number, digits = 3) {
25
+ const multiplier = 10 ** digits
26
+
27
+ return Math.round(val * multiplier) / multiplier
28
+ }
29
+
30
+ export function sleep(timeMs: number) {
31
+ const timer = new Timer()
32
+
33
+ return new Promise<void>((resolve) => {
34
+ const tickCallback = () => {
35
+ if (timer.elapsedTime < timeMs) {
36
+ //setImmediate(tickCallback)
37
+ setTimeout(tickCallback, 0)
38
+ } else {
39
+ resolve()
40
+ }
41
+ }
42
+
43
+ //setImmediate(tickCallback)
44
+ setTimeout(tickCallback, 0)
45
+ })
46
+ }
47
+
48
+ export function parseUrlOrPath(inputString: string, baseUrl = 'https://dummy.com') {
49
+ try {
50
+ // Attempt 1: Try parsing as an absolute URL
51
+ const url = new URL(inputString)
52
+
53
+ return url
54
+ } catch (error) {
55
+ // If it failed, it's likely a relative URL.
56
+ // Attempt 2: Try parsing with a base URL.
57
+ // The base URL can be a real one (e.g., your server's origin)
58
+ // or a dummy one if you only care about path/query/hash.
59
+ try {
60
+ const url = new URL(inputString, baseUrl)
61
+
62
+ return url
63
+ } catch (relativeError: any) {
64
+ // If it fails even with a base, it's truly malformed or unparseable.
65
+ throw new Error(`Failed to parse URL '${inputString}' even with base '${baseUrl}': ${relativeError.message}`)
66
+ }
67
+ }
68
+ }
69
+
70
+ export function getDomainName(url: string) {
71
+ try {
72
+ const hostname = (new URL(url)).hostname
73
+ const parts = hostname.split('.')
74
+
75
+ if (parts.length < 2) {
76
+ return url
77
+ }
78
+
79
+ return parts.slice(parts.length - 2).join('.')
80
+ } catch {
81
+ return ''
82
+ }
83
+ }
84
+
85
+ export function yieldToEventLoop() {
86
+ return new Promise((resolve) => {
87
+ setImmediate(resolve)
88
+ })
89
+ }
90
+
91
+ export function isValidHttpUrl(urlString: string): boolean {
92
+ // 1. Basic type check and trim: Ensure the input is actually a non-empty string.
93
+ // While TypeScript handles type at compile time, this adds runtime robustness.
94
+ if (typeof urlString !== 'string' || urlString.trim() === '') {
95
+ return false;
96
+ }
97
+
98
+ try {
99
+ // 2. Attempt to construct a URL object.
100
+ // The URL constructor throws a TypeError if the URL is not valid
101
+ // (e.g., malformed, relative without a base, etc.).
102
+ const url = new URL(urlString);
103
+
104
+ // 3. Additional robustness: Restrict allowed protocols.
105
+ // The URL constructor accepts many protocols (e.g., 'ftp:', 'file:', 'data:', 'javascript:').
106
+ // For typical web applications, we usually only want 'http:' or 'https:'.
107
+ // The `protocol` property includes the trailing colon.
108
+ const allowedProtocols = ['http:', 'https:'];
109
+ if (!allowedProtocols.includes(url.protocol)) {
110
+ return false;
111
+ }
112
+
113
+ // 4. Optional but often desired: Ensure a non-empty hostname.
114
+ // URLs like "http://" or "https://" are technically valid URL objects
115
+ // but have an empty hostname, which might not be desired for a "valid" URL.
116
+ if (!url.hostname) {
117
+ return false;
118
+ }
119
+
120
+ // All checks passed
121
+ return true;
122
+ } catch (error) {
123
+ // If the URL constructor throws an error, it's not a valid URL.
124
+ // console.error("URL validation error:", error); // Uncomment for debugging if needed
125
+ return false;
126
+ }
127
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ // File Layout
5
+ "rootDir": "./src",
6
+ "outDir": "./dist",
7
+
8
+ // Environment Settings
9
+ // See also https://aka.ms/tsconfig/module
10
+ "module": "nodenext",
11
+ "target": "esnext",
12
+ "types": ["node"],
13
+ // For nodejs:
14
+ // "lib": ["esnext"],
15
+ // "types": ["node"],
16
+ // and npm install -D @types/node
17
+
18
+ // Other Outputs
19
+ "sourceMap": true,
20
+ "declaration": true,
21
+ "declarationMap": true,
22
+
23
+ // Stricter Typechecking Options
24
+ // "noUncheckedIndexedAccess": true,
25
+ // "exactOptionalPropertyTypes": true,
26
+
27
+ // Style Options
28
+ "noImplicitReturns": true,
29
+ // "noImplicitOverride": true,
30
+ // "noUnusedLocals": true,
31
+ // "noUnusedParameters": true,
32
+ // "noFallthroughCasesInSwitch": true,
33
+ // "noPropertyAccessFromIndexSignature": true,
34
+
35
+ // Recommended Options
36
+ "strict": true,
37
+ "jsx": "react-jsx",
38
+ // "verbatimModuleSyntax": true,
39
+ "isolatedModules": true,
40
+ "noUncheckedSideEffectImports": true,
41
+ "moduleDetection": "force",
42
+ "skipLibCheck": true,
43
+
44
+ // Extended options not in generated tsconfig.json
45
+ "newLine": "lf",
46
+ "forceConsistentCasingInFileNames": true,
47
+ "alwaysStrict": true,
48
+
49
+ "noImplicitThis": true,
50
+ "strictBindCallApply": true,
51
+ "strictFunctionTypes": true,
52
+
53
+ "noErrorTruncation": true,
54
+ }
55
+ }