@stryke/http 0.12.25 → 0.12.26
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 +6 -0
- package/dist/_virtual/rolldown_runtime.cjs +29 -1
- package/dist/agent.cjs +96 -2
- package/dist/agent.mjs +93 -2
- package/dist/agent.mjs.map +1 -1
- package/dist/fetch.cjs +30 -1
- package/dist/fetch.mjs +28 -1
- package/dist/fetch.mjs.map +1 -1
- package/dist/format-data-uri.cjs +70 -1
- package/dist/format-data-uri.mjs +68 -1
- package/dist/format-data-uri.mjs.map +1 -1
- package/dist/get-free-port.cjs +23 -1
- package/dist/get-free-port.mjs +22 -1
- package/dist/get-free-port.mjs.map +1 -1
- package/dist/http-proxy.cjs +82 -3
- package/dist/http-proxy.mjs +79 -3
- package/dist/http-proxy.mjs.map +1 -1
- package/dist/https-proxy.cjs +106 -1
- package/dist/https-proxy.mjs +102 -1
- package/dist/https-proxy.mjs.map +1 -1
- package/dist/index.cjs +19 -1
- package/dist/index.mjs +10 -1
- package/dist/parse-response.cjs +83 -4
- package/dist/parse-response.mjs +82 -4
- package/dist/parse-response.mjs.map +1 -1
- package/dist/proxy-agent.cjs +18 -1
- package/dist/proxy-agent.mjs +18 -1
- package/dist/proxy-agent.mjs.map +1 -1
- package/dist/type-checks/src/index.cjs +10 -1
- package/dist/type-checks/src/index.mjs +12 -1
- package/dist/type-checks/src/is-boolean.cjs +18 -1
- package/dist/type-checks/src/is-boolean.mjs +17 -1
- package/dist/type-checks/src/is-boolean.mjs.map +1 -1
- package/dist/type-checks/src/is-buffer.cjs +12 -1
- package/dist/type-checks/src/is-buffer.mjs +11 -1
- package/dist/type-checks/src/is-buffer.mjs.map +1 -1
- package/dist/type-checks/src/is-collection.cjs +1 -1
- package/dist/type-checks/src/is-collection.mjs +3 -1
- package/dist/type-checks/src/is-empty.cjs +20 -1
- package/dist/type-checks/src/is-empty.mjs +20 -1
- package/dist/type-checks/src/is-empty.mjs.map +1 -1
- package/dist/type-checks/src/is-null.cjs +12 -1
- package/dist/type-checks/src/is-null.mjs +11 -1
- package/dist/type-checks/src/is-null.mjs.map +1 -1
- package/dist/type-checks/src/is-set-string.cjs +20 -1
- package/dist/type-checks/src/is-set-string.mjs +20 -1
- package/dist/type-checks/src/is-set-string.mjs.map +1 -1
- package/dist/type-checks/src/is-set.cjs +19 -1
- package/dist/type-checks/src/is-set.mjs +19 -1
- package/dist/type-checks/src/is-set.mjs.map +1 -1
- package/dist/type-checks/src/is-string.cjs +12 -1
- package/dist/type-checks/src/is-string.mjs +11 -1
- package/dist/type-checks/src/is-string.mjs.map +1 -1
- package/dist/type-checks/src/is-undefined.cjs +8 -1
- package/dist/type-checks/src/is-undefined.mjs +7 -1
- package/dist/type-checks/src/is-undefined.mjs.map +1 -1
- package/dist/type-checks/src/type-detect.cjs +15 -1
- package/dist/type-checks/src/type-detect.mjs +16 -1
- package/dist/type-checks/src/type-detect.mjs.map +1 -1
- package/dist/url/src/helpers.cjs +14 -1
- package/dist/url/src/helpers.mjs +13 -1
- package/dist/url/src/helpers.mjs.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog for Stryke - HTTP
|
|
4
4
|
|
|
5
|
+
## [0.12.25](https://github.com/storm-software/stryke/releases/tag/http%400.12.25) (01/16/2026)
|
|
6
|
+
|
|
7
|
+
### Updated Dependencies
|
|
8
|
+
|
|
9
|
+
- Updated **url** to **v0.3.26**
|
|
10
|
+
|
|
5
11
|
## [0.12.24](https://github.com/storm-software/stryke/releases/tag/http%400.12.24) (01/16/2026)
|
|
6
12
|
|
|
7
13
|
### Updated Dependencies
|
|
@@ -1 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
|
|
29
|
+
exports.__toESM = __toESM;
|
package/dist/agent.cjs
CHANGED
|
@@ -1,2 +1,96 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_is_boolean = require('./type-checks/src/is-boolean.cjs');
|
|
3
|
+
const require_is_string = require('./type-checks/src/is-string.cjs');
|
|
4
|
+
require('./type-checks/src/index.cjs');
|
|
5
|
+
let node_http = require("node:http");
|
|
6
|
+
node_http = require_rolldown_runtime.__toESM(node_http);
|
|
7
|
+
let node_net = require("node:net");
|
|
8
|
+
node_net = require_rolldown_runtime.__toESM(node_net);
|
|
9
|
+
|
|
10
|
+
//#region src/agent.ts
|
|
11
|
+
const SYMBOL_INTERNAL = Symbol("Agent");
|
|
12
|
+
var Agent = class extends node_http.Agent {
|
|
13
|
+
[SYMBOL_INTERNAL];
|
|
14
|
+
options;
|
|
15
|
+
keepAlive;
|
|
16
|
+
constructor(opts) {
|
|
17
|
+
super(opts);
|
|
18
|
+
this[SYMBOL_INTERNAL] = {};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Determine whether this is an `http` or `https` request.
|
|
22
|
+
*/
|
|
23
|
+
isSecureEndpoint(options) {
|
|
24
|
+
if (options) {
|
|
25
|
+
if (require_is_boolean.isBoolean(options.secureEndpoint)) return options.secureEndpoint;
|
|
26
|
+
if (require_is_string.isString(options.protocol)) return options.protocol === "https:";
|
|
27
|
+
}
|
|
28
|
+
const { stack } = /* @__PURE__ */ new Error(" ");
|
|
29
|
+
if (!require_is_string.isString(stack)) return false;
|
|
30
|
+
return stack.split("\n").some((l) => l.includes("(https.js:") || l.includes("node:https:"));
|
|
31
|
+
}
|
|
32
|
+
incrementSockets(name) {
|
|
33
|
+
if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) return null;
|
|
34
|
+
this.sockets[name] ??= [];
|
|
35
|
+
const fakeSocket = new node_net.Socket({ writable: false });
|
|
36
|
+
this.sockets[name].push(fakeSocket);
|
|
37
|
+
this.totalSocketCount++;
|
|
38
|
+
return fakeSocket;
|
|
39
|
+
}
|
|
40
|
+
decrementSockets(name, socket) {
|
|
41
|
+
if (!this.sockets[name] || socket === null) return;
|
|
42
|
+
const sockets = this.sockets[name];
|
|
43
|
+
const index = sockets.indexOf(socket);
|
|
44
|
+
if (index !== -1) {
|
|
45
|
+
sockets.splice(index, 1);
|
|
46
|
+
this.totalSocketCount--;
|
|
47
|
+
if (sockets.length === 0) delete this.sockets[name];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
getName(options) {
|
|
51
|
+
if (this.isSecureEndpoint(options)) return HttpsAgent.prototype.getName.call(this, options);
|
|
52
|
+
return super.getName(options);
|
|
53
|
+
}
|
|
54
|
+
createSocket(req, options, cb) {
|
|
55
|
+
const connectOpts = {
|
|
56
|
+
...options,
|
|
57
|
+
secureEndpoint: this.isSecureEndpoint(options)
|
|
58
|
+
};
|
|
59
|
+
const name = this.getName(connectOpts);
|
|
60
|
+
const fakeSocket = this.incrementSockets(name);
|
|
61
|
+
Promise.resolve().then(async () => this.connect(req, connectOpts)).then((socket) => {
|
|
62
|
+
this.decrementSockets(name, fakeSocket);
|
|
63
|
+
if (socket instanceof node_http.Agent) try {
|
|
64
|
+
return socket.addRequest(req, connectOpts);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return cb(err);
|
|
67
|
+
}
|
|
68
|
+
this[SYMBOL_INTERNAL].currentSocket = socket;
|
|
69
|
+
super.createSocket(req, options, cb);
|
|
70
|
+
}, (err) => {
|
|
71
|
+
this.decrementSockets(name, fakeSocket);
|
|
72
|
+
cb(err);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
createConnection() {
|
|
76
|
+
const socket = this[SYMBOL_INTERNAL].currentSocket;
|
|
77
|
+
this[SYMBOL_INTERNAL].currentSocket = void 0;
|
|
78
|
+
if (!socket) throw new Error("No socket was returned in the `connect()` function");
|
|
79
|
+
return socket;
|
|
80
|
+
}
|
|
81
|
+
get defaultPort() {
|
|
82
|
+
return this[SYMBOL_INTERNAL].defaultPort ?? (this.protocol === "https:" ? 443 : 80);
|
|
83
|
+
}
|
|
84
|
+
set defaultPort(v) {
|
|
85
|
+
if (this[SYMBOL_INTERNAL]) this[SYMBOL_INTERNAL].defaultPort = v;
|
|
86
|
+
}
|
|
87
|
+
get protocol() {
|
|
88
|
+
return this[SYMBOL_INTERNAL].protocol ?? (this.isSecureEndpoint() ? "https:" : "http:");
|
|
89
|
+
}
|
|
90
|
+
set protocol(v) {
|
|
91
|
+
if (this[SYMBOL_INTERNAL]) this[SYMBOL_INTERNAL].protocol = v;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
exports.Agent = Agent;
|
package/dist/agent.mjs
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
|
-
import{isBoolean
|
|
2
|
-
|
|
1
|
+
import { isBoolean } from "./type-checks/src/is-boolean.mjs";
|
|
2
|
+
import { isString } from "./type-checks/src/is-string.mjs";
|
|
3
|
+
import "./type-checks/src/index.mjs";
|
|
4
|
+
import * as http from "node:http";
|
|
5
|
+
import * as net from "node:net";
|
|
6
|
+
|
|
7
|
+
//#region src/agent.ts
|
|
8
|
+
const SYMBOL_INTERNAL = Symbol("Agent");
|
|
9
|
+
var Agent = class extends http.Agent {
|
|
10
|
+
[SYMBOL_INTERNAL];
|
|
11
|
+
options;
|
|
12
|
+
keepAlive;
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
super(opts);
|
|
15
|
+
this[SYMBOL_INTERNAL] = {};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Determine whether this is an `http` or `https` request.
|
|
19
|
+
*/
|
|
20
|
+
isSecureEndpoint(options) {
|
|
21
|
+
if (options) {
|
|
22
|
+
if (isBoolean(options.secureEndpoint)) return options.secureEndpoint;
|
|
23
|
+
if (isString(options.protocol)) return options.protocol === "https:";
|
|
24
|
+
}
|
|
25
|
+
const { stack } = /* @__PURE__ */ new Error(" ");
|
|
26
|
+
if (!isString(stack)) return false;
|
|
27
|
+
return stack.split("\n").some((l) => l.includes("(https.js:") || l.includes("node:https:"));
|
|
28
|
+
}
|
|
29
|
+
incrementSockets(name) {
|
|
30
|
+
if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) return null;
|
|
31
|
+
this.sockets[name] ??= [];
|
|
32
|
+
const fakeSocket = new net.Socket({ writable: false });
|
|
33
|
+
this.sockets[name].push(fakeSocket);
|
|
34
|
+
this.totalSocketCount++;
|
|
35
|
+
return fakeSocket;
|
|
36
|
+
}
|
|
37
|
+
decrementSockets(name, socket) {
|
|
38
|
+
if (!this.sockets[name] || socket === null) return;
|
|
39
|
+
const sockets = this.sockets[name];
|
|
40
|
+
const index = sockets.indexOf(socket);
|
|
41
|
+
if (index !== -1) {
|
|
42
|
+
sockets.splice(index, 1);
|
|
43
|
+
this.totalSocketCount--;
|
|
44
|
+
if (sockets.length === 0) delete this.sockets[name];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
getName(options) {
|
|
48
|
+
if (this.isSecureEndpoint(options)) return HttpsAgent.prototype.getName.call(this, options);
|
|
49
|
+
return super.getName(options);
|
|
50
|
+
}
|
|
51
|
+
createSocket(req, options, cb) {
|
|
52
|
+
const connectOpts = {
|
|
53
|
+
...options,
|
|
54
|
+
secureEndpoint: this.isSecureEndpoint(options)
|
|
55
|
+
};
|
|
56
|
+
const name = this.getName(connectOpts);
|
|
57
|
+
const fakeSocket = this.incrementSockets(name);
|
|
58
|
+
Promise.resolve().then(async () => this.connect(req, connectOpts)).then((socket) => {
|
|
59
|
+
this.decrementSockets(name, fakeSocket);
|
|
60
|
+
if (socket instanceof http.Agent) try {
|
|
61
|
+
return socket.addRequest(req, connectOpts);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
return cb(err);
|
|
64
|
+
}
|
|
65
|
+
this[SYMBOL_INTERNAL].currentSocket = socket;
|
|
66
|
+
super.createSocket(req, options, cb);
|
|
67
|
+
}, (err) => {
|
|
68
|
+
this.decrementSockets(name, fakeSocket);
|
|
69
|
+
cb(err);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
createConnection() {
|
|
73
|
+
const socket = this[SYMBOL_INTERNAL].currentSocket;
|
|
74
|
+
this[SYMBOL_INTERNAL].currentSocket = void 0;
|
|
75
|
+
if (!socket) throw new Error("No socket was returned in the `connect()` function");
|
|
76
|
+
return socket;
|
|
77
|
+
}
|
|
78
|
+
get defaultPort() {
|
|
79
|
+
return this[SYMBOL_INTERNAL].defaultPort ?? (this.protocol === "https:" ? 443 : 80);
|
|
80
|
+
}
|
|
81
|
+
set defaultPort(v) {
|
|
82
|
+
if (this[SYMBOL_INTERNAL]) this[SYMBOL_INTERNAL].defaultPort = v;
|
|
83
|
+
}
|
|
84
|
+
get protocol() {
|
|
85
|
+
return this[SYMBOL_INTERNAL].protocol ?? (this.isSecureEndpoint() ? "https:" : "http:");
|
|
86
|
+
}
|
|
87
|
+
set protocol(v) {
|
|
88
|
+
if (this[SYMBOL_INTERNAL]) this[SYMBOL_INTERNAL].protocol = v;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { Agent };
|
|
3
94
|
//# sourceMappingURL=agent.mjs.map
|
package/dist/agent.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.mjs","names":["err: unknown"],"sources":["../src/agent.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isBoolean, isString } from \"@stryke/type-checks\";\nimport * as http from \"node:http\";\nimport type { Agent as HttpsAgent } from \"node:https\";\nimport * as net from \"node:net\";\nimport type { Duplex } from \"node:stream\";\nimport type * as tls from \"node:tls\";\n\ninterface HttpConnectOpts extends net.TcpNetConnectOpts {\n secureEndpoint: false;\n protocol?: string;\n}\n\ninterface HttpsConnectOpts extends tls.ConnectionOptions {\n secureEndpoint: true;\n protocol?: string;\n port: number;\n}\n\nexport type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts;\n\nconst SYMBOL_INTERNAL = Symbol(\"Agent\");\n\ninterface InternalState {\n defaultPort?: number;\n protocol?: string;\n currentSocket?: Duplex;\n}\n\nexport abstract class Agent extends http.Agent {\n private [SYMBOL_INTERNAL]: InternalState;\n\n // Set by `http.Agent` - missing from `@types/node`\n options!: Partial<net.TcpNetConnectOpts & tls.ConnectionOptions>;\n\n keepAlive!: boolean;\n\n constructor(opts?: http.AgentOptions) {\n super(opts);\n this[SYMBOL_INTERNAL] = {};\n }\n\n abstract connect(\n req: http.ClientRequest,\n options: AgentConnectOpts\n ): Promise<Duplex | http.Agent> | Duplex | http.Agent;\n\n /**\n * Determine whether this is an `http` or `https` request.\n */\n isSecureEndpoint(options?: AgentConnectOpts): boolean {\n if (options) {\n // First check the `secureEndpoint` property explicitly, since this\n // means that a parent `Agent` is \"passing through\" to this instance.\n if (isBoolean((options as any).secureEndpoint)) {\n return options.secureEndpoint;\n }\n\n // If no explicit `secure` endpoint, check if `protocol` property is\n // set. This will usually be the case since using a full string URL\n // or `URL` instance should be the most common usage.\n if (isString(options.protocol)) {\n return options.protocol === \"https:\";\n }\n }\n\n // Finally, if no `protocol` property was set, then fall back to\n // checking the stack trace of the current call stack, and try to\n // detect the \"https\" module.\n const { stack } = new Error(\" \");\n if (!isString(stack)) {\n return false;\n }\n\n return stack\n .split(\"\\n\")\n .some(l => l.includes(\"(https.js:\") || l.includes(\"node:https:\"));\n }\n\n // In order to support async signatures in `connect()` and Node's native\n // connection pooling in `http.Agent`, the array of sockets for each origin\n // has to be updated synchronously. This is so the length of the array is\n // accurate when `addRequest()` is next called. We achieve this by creating a\n // fake socket and adding it to `sockets[origin]` and incrementing\n // `totalSocketCount`.\n private incrementSockets(name: string) {\n // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no\n // need to create a fake socket because Node.js native connection pooling\n // will never be invoked.\n if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) {\n return null;\n }\n // All instances of `sockets` are expected TypeScript errors. The\n // alternative is to add it as a private property of this class but that\n // will break TypeScript sub-classing.\n\n // @ts-expect-error `sockets` is readonly in `@types/node`\n this.sockets[name] ??= [];\n\n const fakeSocket = new net.Socket({ writable: false });\n this.sockets[name].push(fakeSocket);\n // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`\n this.totalSocketCount++;\n return fakeSocket;\n }\n\n private decrementSockets(name: string, socket: null | net.Socket) {\n if (!this.sockets[name] || socket === null) {\n return;\n }\n const sockets = this.sockets[name];\n const index = sockets.indexOf(socket);\n if (index !== -1) {\n sockets.splice(index, 1);\n // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`\n this.totalSocketCount--;\n if (sockets.length === 0) {\n // @ts-expect-error `sockets` is readonly in `@types/node`\n delete this.sockets[name];\n }\n }\n }\n\n // In order to properly update the socket pool, we need to call `getName()` on\n // the core `https.Agent` if it is a secureEndpoint.\n override getName(options?: AgentConnectOpts): string {\n const secureEndpoint = this.isSecureEndpoint(options);\n if (secureEndpoint) {\n // @ts-expect-error `getName()` isn't defined in `@types/node`\n return HttpsAgent.prototype.getName.call(this, options);\n }\n\n return super.getName(options);\n }\n\n createSocket(\n req: http.ClientRequest,\n options: AgentConnectOpts,\n cb: (err: Error | null, s?: Duplex) => void\n ) {\n const connectOpts = {\n ...options,\n secureEndpoint: this.isSecureEndpoint(options)\n };\n const name = this.getName(connectOpts);\n const fakeSocket = this.incrementSockets(name);\n Promise.resolve()\n .then(async () => this.connect(req, connectOpts))\n .then(\n socket => {\n this.decrementSockets(name, fakeSocket);\n if (socket instanceof http.Agent) {\n try {\n // @ts-expect-error `addRequest()` isn't defined in `@types/node`\n // eslint-disable-next-line ts/no-unsafe-call\n return socket.addRequest(req, connectOpts);\n } catch (err: unknown) {\n return cb(err as Error);\n }\n }\n this[SYMBOL_INTERNAL].currentSocket = socket;\n // @ts-expect-error `createSocket()` isn't defined in `@types/node`\n // eslint-disable-next-line ts/no-unsafe-call\n super.createSocket(req, options, cb);\n },\n err => {\n this.decrementSockets(name, fakeSocket);\n cb(err);\n }\n );\n }\n\n override createConnection(): Duplex {\n const socket = this[SYMBOL_INTERNAL].currentSocket;\n this[SYMBOL_INTERNAL].currentSocket = undefined;\n if (!socket) {\n throw new Error(\"No socket was returned in the `connect()` function\");\n }\n return socket;\n }\n\n get defaultPort(): number {\n return (\n this[SYMBOL_INTERNAL].defaultPort ??\n (this.protocol === \"https:\" ? 443 : 80)\n );\n }\n\n set defaultPort(v: number) {\n if (this[SYMBOL_INTERNAL]) {\n this[SYMBOL_INTERNAL].defaultPort = v;\n }\n }\n\n get protocol(): string {\n return (\n this[SYMBOL_INTERNAL].protocol ??\n (this.isSecureEndpoint() ? \"https:\" : \"http:\")\n );\n }\n\n set protocol(v: string) {\n if (this[SYMBOL_INTERNAL]) {\n this[SYMBOL_INTERNAL].protocol = v;\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.mjs","names":["err: unknown"],"sources":["../src/agent.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isBoolean, isString } from \"@stryke/type-checks\";\nimport * as http from \"node:http\";\nimport type { Agent as HttpsAgent } from \"node:https\";\nimport * as net from \"node:net\";\nimport type { Duplex } from \"node:stream\";\nimport type * as tls from \"node:tls\";\n\ninterface HttpConnectOpts extends net.TcpNetConnectOpts {\n secureEndpoint: false;\n protocol?: string;\n}\n\ninterface HttpsConnectOpts extends tls.ConnectionOptions {\n secureEndpoint: true;\n protocol?: string;\n port: number;\n}\n\nexport type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts;\n\nconst SYMBOL_INTERNAL = Symbol(\"Agent\");\n\ninterface InternalState {\n defaultPort?: number;\n protocol?: string;\n currentSocket?: Duplex;\n}\n\nexport abstract class Agent extends http.Agent {\n private [SYMBOL_INTERNAL]: InternalState;\n\n // Set by `http.Agent` - missing from `@types/node`\n options!: Partial<net.TcpNetConnectOpts & tls.ConnectionOptions>;\n\n keepAlive!: boolean;\n\n constructor(opts?: http.AgentOptions) {\n super(opts);\n this[SYMBOL_INTERNAL] = {};\n }\n\n abstract connect(\n req: http.ClientRequest,\n options: AgentConnectOpts\n ): Promise<Duplex | http.Agent> | Duplex | http.Agent;\n\n /**\n * Determine whether this is an `http` or `https` request.\n */\n isSecureEndpoint(options?: AgentConnectOpts): boolean {\n if (options) {\n // First check the `secureEndpoint` property explicitly, since this\n // means that a parent `Agent` is \"passing through\" to this instance.\n if (isBoolean((options as any).secureEndpoint)) {\n return options.secureEndpoint;\n }\n\n // If no explicit `secure` endpoint, check if `protocol` property is\n // set. This will usually be the case since using a full string URL\n // or `URL` instance should be the most common usage.\n if (isString(options.protocol)) {\n return options.protocol === \"https:\";\n }\n }\n\n // Finally, if no `protocol` property was set, then fall back to\n // checking the stack trace of the current call stack, and try to\n // detect the \"https\" module.\n const { stack } = new Error(\" \");\n if (!isString(stack)) {\n return false;\n }\n\n return stack\n .split(\"\\n\")\n .some(l => l.includes(\"(https.js:\") || l.includes(\"node:https:\"));\n }\n\n // In order to support async signatures in `connect()` and Node's native\n // connection pooling in `http.Agent`, the array of sockets for each origin\n // has to be updated synchronously. This is so the length of the array is\n // accurate when `addRequest()` is next called. We achieve this by creating a\n // fake socket and adding it to `sockets[origin]` and incrementing\n // `totalSocketCount`.\n private incrementSockets(name: string) {\n // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no\n // need to create a fake socket because Node.js native connection pooling\n // will never be invoked.\n if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) {\n return null;\n }\n // All instances of `sockets` are expected TypeScript errors. The\n // alternative is to add it as a private property of this class but that\n // will break TypeScript sub-classing.\n\n // @ts-expect-error `sockets` is readonly in `@types/node`\n this.sockets[name] ??= [];\n\n const fakeSocket = new net.Socket({ writable: false });\n this.sockets[name].push(fakeSocket);\n // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`\n this.totalSocketCount++;\n return fakeSocket;\n }\n\n private decrementSockets(name: string, socket: null | net.Socket) {\n if (!this.sockets[name] || socket === null) {\n return;\n }\n const sockets = this.sockets[name];\n const index = sockets.indexOf(socket);\n if (index !== -1) {\n sockets.splice(index, 1);\n // @ts-expect-error `totalSocketCount` isn't defined in `@types/node`\n this.totalSocketCount--;\n if (sockets.length === 0) {\n // @ts-expect-error `sockets` is readonly in `@types/node`\n delete this.sockets[name];\n }\n }\n }\n\n // In order to properly update the socket pool, we need to call `getName()` on\n // the core `https.Agent` if it is a secureEndpoint.\n override getName(options?: AgentConnectOpts): string {\n const secureEndpoint = this.isSecureEndpoint(options);\n if (secureEndpoint) {\n // @ts-expect-error `getName()` isn't defined in `@types/node`\n return HttpsAgent.prototype.getName.call(this, options);\n }\n\n return super.getName(options);\n }\n\n createSocket(\n req: http.ClientRequest,\n options: AgentConnectOpts,\n cb: (err: Error | null, s?: Duplex) => void\n ) {\n const connectOpts = {\n ...options,\n secureEndpoint: this.isSecureEndpoint(options)\n };\n const name = this.getName(connectOpts);\n const fakeSocket = this.incrementSockets(name);\n Promise.resolve()\n .then(async () => this.connect(req, connectOpts))\n .then(\n socket => {\n this.decrementSockets(name, fakeSocket);\n if (socket instanceof http.Agent) {\n try {\n // @ts-expect-error `addRequest()` isn't defined in `@types/node`\n // eslint-disable-next-line ts/no-unsafe-call\n return socket.addRequest(req, connectOpts);\n } catch (err: unknown) {\n return cb(err as Error);\n }\n }\n this[SYMBOL_INTERNAL].currentSocket = socket;\n // @ts-expect-error `createSocket()` isn't defined in `@types/node`\n // eslint-disable-next-line ts/no-unsafe-call\n super.createSocket(req, options, cb);\n },\n err => {\n this.decrementSockets(name, fakeSocket);\n cb(err);\n }\n );\n }\n\n override createConnection(): Duplex {\n const socket = this[SYMBOL_INTERNAL].currentSocket;\n this[SYMBOL_INTERNAL].currentSocket = undefined;\n if (!socket) {\n throw new Error(\"No socket was returned in the `connect()` function\");\n }\n return socket;\n }\n\n get defaultPort(): number {\n return (\n this[SYMBOL_INTERNAL].defaultPort ??\n (this.protocol === \"https:\" ? 443 : 80)\n );\n }\n\n set defaultPort(v: number) {\n if (this[SYMBOL_INTERNAL]) {\n this[SYMBOL_INTERNAL].defaultPort = v;\n }\n }\n\n get protocol(): string {\n return (\n this[SYMBOL_INTERNAL].protocol ??\n (this.isSecureEndpoint() ? \"https:\" : \"http:\")\n );\n }\n\n set protocol(v: string) {\n if (this[SYMBOL_INTERNAL]) {\n this[SYMBOL_INTERNAL].protocol = v;\n }\n }\n}\n"],"mappings":";;;;;;;AAsCA,MAAM,kBAAkB,OAAO,QAAQ;AAQvC,IAAsB,QAAtB,cAAoC,KAAK,MAAM;CAC7C,CAAS;CAGT;CAEA;CAEA,YAAY,MAA0B;AACpC,QAAM,KAAK;AACX,OAAK,mBAAmB,EAAE;;;;;CAW5B,iBAAiB,SAAqC;AACpD,MAAI,SAAS;AAGX,OAAI,UAAW,QAAgB,eAAe,CAC5C,QAAO,QAAQ;AAMjB,OAAI,SAAS,QAAQ,SAAS,CAC5B,QAAO,QAAQ,aAAa;;EAOhC,MAAM,EAAE,0BAAU,IAAI,MAAM,IAAI;AAChC,MAAI,CAAC,SAAS,MAAM,CAClB,QAAO;AAGT,SAAO,MACJ,MAAM,KAAK,CACX,MAAK,MAAK,EAAE,SAAS,aAAa,IAAI,EAAE,SAAS,cAAc,CAAC;;CASrE,AAAQ,iBAAiB,MAAc;AAIrC,MAAI,KAAK,eAAe,YAAY,KAAK,oBAAoB,SAC3D,QAAO;AAOT,OAAK,QAAQ,UAAU,EAAE;EAEzB,MAAM,aAAa,IAAI,IAAI,OAAO,EAAE,UAAU,OAAO,CAAC;AACtD,OAAK,QAAQ,MAAM,KAAK,WAAW;AAEnC,OAAK;AACL,SAAO;;CAGT,AAAQ,iBAAiB,MAAc,QAA2B;AAChE,MAAI,CAAC,KAAK,QAAQ,SAAS,WAAW,KACpC;EAEF,MAAM,UAAU,KAAK,QAAQ;EAC7B,MAAM,QAAQ,QAAQ,QAAQ,OAAO;AACrC,MAAI,UAAU,IAAI;AAChB,WAAQ,OAAO,OAAO,EAAE;AAExB,QAAK;AACL,OAAI,QAAQ,WAAW,EAErB,QAAO,KAAK,QAAQ;;;CAO1B,AAAS,QAAQ,SAAoC;AAEnD,MADuB,KAAK,iBAAiB,QAAQ,CAGnD,QAAO,WAAW,UAAU,QAAQ,KAAK,MAAM,QAAQ;AAGzD,SAAO,MAAM,QAAQ,QAAQ;;CAG/B,aACE,KACA,SACA,IACA;EACA,MAAM,cAAc;GAClB,GAAG;GACH,gBAAgB,KAAK,iBAAiB,QAAQ;GAC/C;EACD,MAAM,OAAO,KAAK,QAAQ,YAAY;EACtC,MAAM,aAAa,KAAK,iBAAiB,KAAK;AAC9C,UAAQ,SAAS,CACd,KAAK,YAAY,KAAK,QAAQ,KAAK,YAAY,CAAC,CAChD,MACC,WAAU;AACR,QAAK,iBAAiB,MAAM,WAAW;AACvC,OAAI,kBAAkB,KAAK,MACzB,KAAI;AAGF,WAAO,OAAO,WAAW,KAAK,YAAY;YACnCA,KAAc;AACrB,WAAO,GAAG,IAAa;;AAG3B,QAAK,iBAAiB,gBAAgB;AAGtC,SAAM,aAAa,KAAK,SAAS,GAAG;MAEtC,QAAO;AACL,QAAK,iBAAiB,MAAM,WAAW;AACvC,MAAG,IAAI;IAEV;;CAGL,AAAS,mBAA2B;EAClC,MAAM,SAAS,KAAK,iBAAiB;AACrC,OAAK,iBAAiB,gBAAgB;AACtC,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,qDAAqD;AAEvE,SAAO;;CAGT,IAAI,cAAsB;AACxB,SACE,KAAK,iBAAiB,gBACrB,KAAK,aAAa,WAAW,MAAM;;CAIxC,IAAI,YAAY,GAAW;AACzB,MAAI,KAAK,iBACP,MAAK,iBAAiB,cAAc;;CAIxC,IAAI,WAAmB;AACrB,SACE,KAAK,iBAAiB,aACrB,KAAK,kBAAkB,GAAG,WAAW;;CAI1C,IAAI,SAAS,GAAW;AACtB,MAAI,KAAK,iBACP,MAAK,iBAAiB,WAAW"}
|
package/dist/fetch.cjs
CHANGED
|
@@ -1 +1,30 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_is_set_string = require('./type-checks/src/is-set-string.cjs');
|
|
3
|
+
const require_helpers = require('./url/src/helpers.cjs');
|
|
4
|
+
const require_proxy_agent = require('./proxy-agent.cjs');
|
|
5
|
+
let defu = require("defu");
|
|
6
|
+
let undici = require("undici");
|
|
7
|
+
|
|
8
|
+
//#region src/fetch.ts
|
|
9
|
+
/**
|
|
10
|
+
* Fetches a resource from a URL.
|
|
11
|
+
*
|
|
12
|
+
* @param input - The URL to fetch.
|
|
13
|
+
* @param options - Additional fetch options.
|
|
14
|
+
* @returns The fetched response.
|
|
15
|
+
*/
|
|
16
|
+
async function fetchRequest(input, options = {}) {
|
|
17
|
+
if (require_is_set_string.isSetString(input) && !require_helpers.isValidURL(input)) throw new Error(`Invalid URL format provided: ${input}`);
|
|
18
|
+
const abort = new AbortController();
|
|
19
|
+
setTimeout(() => abort.abort(), options.timeout ?? 5e3);
|
|
20
|
+
return (0, undici.fetch)(input, (0, defu.defu)(options, {
|
|
21
|
+
agent: require_proxy_agent.getProxyAgent(),
|
|
22
|
+
signal: abort.signal,
|
|
23
|
+
headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" }
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
const fetch = fetchRequest;
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
exports.fetch = fetch;
|
|
30
|
+
exports.fetchRequest = fetchRequest;
|
package/dist/fetch.mjs
CHANGED
|
@@ -1,2 +1,29 @@
|
|
|
1
|
-
import{isSetString
|
|
1
|
+
import { isSetString } from "./type-checks/src/is-set-string.mjs";
|
|
2
|
+
import { isValidURL } from "./url/src/helpers.mjs";
|
|
3
|
+
import { getProxyAgent } from "./proxy-agent.mjs";
|
|
4
|
+
import { defu } from "defu";
|
|
5
|
+
import { fetch as fetch$1 } from "undici";
|
|
6
|
+
|
|
7
|
+
//#region src/fetch.ts
|
|
8
|
+
/**
|
|
9
|
+
* Fetches a resource from a URL.
|
|
10
|
+
*
|
|
11
|
+
* @param input - The URL to fetch.
|
|
12
|
+
* @param options - Additional fetch options.
|
|
13
|
+
* @returns The fetched response.
|
|
14
|
+
*/
|
|
15
|
+
async function fetchRequest(input, options = {}) {
|
|
16
|
+
if (isSetString(input) && !isValidURL(input)) throw new Error(`Invalid URL format provided: ${input}`);
|
|
17
|
+
const abort = new AbortController();
|
|
18
|
+
setTimeout(() => abort.abort(), options.timeout ?? 5e3);
|
|
19
|
+
return fetch$1(input, defu(options, {
|
|
20
|
+
agent: getProxyAgent(),
|
|
21
|
+
signal: abort.signal,
|
|
22
|
+
headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" }
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
const fetch = fetchRequest;
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { fetch, fetchRequest };
|
|
2
29
|
//# sourceMappingURL=fetch.mjs.map
|
package/dist/fetch.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.mjs","names":["undiciFetch"],"sources":["../src/fetch.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isValidURL } from \"@stryke/url/helpers\";\nimport { defu } from \"defu\";\nimport type { RequestInfo } from \"undici\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { getProxyAgent } from \"./proxy-agent\";\n\nexport type FetchRequestOptions = RequestInit & {\n /**\n * Timeout in milliseconds\n *\n * @defaultValue 5000\n */\n timeout?: number;\n};\n\n/**\n * Fetches a resource from a URL.\n *\n * @param input - The URL to fetch.\n * @param options - Additional fetch options.\n * @returns The fetched response.\n */\nexport async function fetchRequest(\n input: RequestInfo,\n options: FetchRequestOptions = {}\n) {\n if (isSetString(input) && !isValidURL(input)) {\n throw new Error(`Invalid URL format provided: ${input}`);\n }\n\n const abort = new AbortController();\n setTimeout(() => abort.abort(), options.timeout ?? 5000);\n\n return undiciFetch(\n input,\n defu(options, {\n agent: getProxyAgent(),\n signal: abort.signal,\n headers: {\n // The file format is based off of the user agent, make sure woff2 files are fetched\n \"User-Agent\":\n \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) \" +\n \"AppleWebKit/537.36 (KHTML, like Gecko) \" +\n \"Chrome/104.0.0.0 Safari/537.36\"\n }\n })\n );\n}\n\nexport const fetch = fetchRequest;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.mjs","names":["undiciFetch"],"sources":["../src/fetch.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isValidURL } from \"@stryke/url/helpers\";\nimport { defu } from \"defu\";\nimport type { RequestInfo } from \"undici\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { getProxyAgent } from \"./proxy-agent\";\n\nexport type FetchRequestOptions = RequestInit & {\n /**\n * Timeout in milliseconds\n *\n * @defaultValue 5000\n */\n timeout?: number;\n};\n\n/**\n * Fetches a resource from a URL.\n *\n * @param input - The URL to fetch.\n * @param options - Additional fetch options.\n * @returns The fetched response.\n */\nexport async function fetchRequest(\n input: RequestInfo,\n options: FetchRequestOptions = {}\n) {\n if (isSetString(input) && !isValidURL(input)) {\n throw new Error(`Invalid URL format provided: ${input}`);\n }\n\n const abort = new AbortController();\n setTimeout(() => abort.abort(), options.timeout ?? 5000);\n\n return undiciFetch(\n input,\n defu(options, {\n agent: getProxyAgent(),\n signal: abort.signal,\n headers: {\n // The file format is based off of the user agent, make sure woff2 files are fetched\n \"User-Agent\":\n \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) \" +\n \"AppleWebKit/537.36 (KHTML, like Gecko) \" +\n \"Chrome/104.0.0.0 Safari/537.36\"\n }\n })\n );\n}\n\nexport const fetch = fetchRequest;\n"],"mappings":";;;;;;;;;;;;;;AAyCA,eAAsB,aACpB,OACA,UAA+B,EAAE,EACjC;AACA,KAAI,YAAY,MAAM,IAAI,CAAC,WAAW,MAAM,CAC1C,OAAM,IAAI,MAAM,gCAAgC,QAAQ;CAG1D,MAAM,QAAQ,IAAI,iBAAiB;AACnC,kBAAiB,MAAM,OAAO,EAAE,QAAQ,WAAW,IAAK;AAExD,QAAOA,QACL,OACA,KAAK,SAAS;EACZ,OAAO,eAAe;EACtB,QAAQ,MAAM;EACd,SAAS,EAEP,cACE,yHAGH;EACF,CAAC,CACH;;AAGH,MAAa,QAAQ"}
|
package/dist/format-data-uri.cjs
CHANGED
|
@@ -1 +1,70 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
//#region src/format-data-uri.ts
|
|
3
|
+
/**
|
|
4
|
+
* Creates a data URI from a string of data.
|
|
5
|
+
*
|
|
6
|
+
* @param data - The data to convert to a data URI.
|
|
7
|
+
* @param mime - The MIME type of the data.
|
|
8
|
+
* @returns The data URI.
|
|
9
|
+
*/
|
|
10
|
+
const formatDataURI = (data, mime) => `data:${mime};utf8,${encodeURIComponent(data)}`;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a `Buffer` instance from the given data URI `uri`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { makeDataUriToBuffer } from "@stryke/core/http";
|
|
17
|
+
*
|
|
18
|
+
* const dataUriToBuffer = makeDataUriToBuffer({
|
|
19
|
+
* base64ToArrayBuffer: (base64) => Buffer.from(base64, "base64").buffer,
|
|
20
|
+
* stringToBuffer: (str) => Buffer.from(str, "utf8")https://avatars.githubusercontent.com/u/99053093?s=64&v=4.buffer,
|
|
21
|
+
* });
|
|
22
|
+
* const parsed = dataUriToBuffer("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==");
|
|
23
|
+
* console.log(parsed);
|
|
24
|
+
* // {
|
|
25
|
+
* // type: 'text/plain',
|
|
26
|
+
* // typeFull: 'text/plain;base64',
|
|
27
|
+
* // charset: '',
|
|
28
|
+
* // buffer: ArrayBuffer { ... }
|
|
29
|
+
* // }
|
|
30
|
+
* console.log(Buffer.from(parsed.buffer).toString("utf8"));
|
|
31
|
+
* // Hello, World!
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param convert - Conversion functions
|
|
35
|
+
* @returns An object containing the parsed data URI properties and the decoded data as a Buffer instance.
|
|
36
|
+
* @throws `TypeError` if `uri` is not a valid Data URI
|
|
37
|
+
*/
|
|
38
|
+
const makeDataUriToBuffer = (convert) => (uri) => {
|
|
39
|
+
uri = String(uri);
|
|
40
|
+
if (!/^data:/i.test(uri)) throw new Error("`uri` does not appear to be a Data URI (must begin with \"data:\")");
|
|
41
|
+
uri = uri.replace(/\r?\n/g, "");
|
|
42
|
+
const firstComma = uri.indexOf(",");
|
|
43
|
+
if (firstComma === -1 || firstComma <= 4) throw new Error("malformed data: URI");
|
|
44
|
+
const meta = uri.substring(5, firstComma).split(";");
|
|
45
|
+
let charset = "";
|
|
46
|
+
let base64 = false;
|
|
47
|
+
const type = meta[0] || "text/plain";
|
|
48
|
+
let typeFull = type;
|
|
49
|
+
for (let i = 1; i < meta.length; i++) if (meta[i] === "base64") base64 = true;
|
|
50
|
+
else if (meta[i]) {
|
|
51
|
+
typeFull += `;${meta[i]}`;
|
|
52
|
+
if (meta[i]?.indexOf("charset=") === 0) charset = meta[i].substring(8);
|
|
53
|
+
}
|
|
54
|
+
if (!meta[0] && !charset.length) {
|
|
55
|
+
typeFull += ";charset=US-ASCII";
|
|
56
|
+
charset = "US-ASCII";
|
|
57
|
+
}
|
|
58
|
+
const data = unescape(uri.substring(firstComma + 1));
|
|
59
|
+
const buffer = base64 ? convert.base64ToArrayBuffer(data) : convert.stringToBuffer(data);
|
|
60
|
+
return {
|
|
61
|
+
type,
|
|
62
|
+
typeFull,
|
|
63
|
+
charset,
|
|
64
|
+
buffer
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
exports.formatDataURI = formatDataURI;
|
|
70
|
+
exports.makeDataUriToBuffer = makeDataUriToBuffer;
|
package/dist/format-data-uri.mjs
CHANGED
|
@@ -1,2 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/format-data-uri.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates a data URI from a string of data.
|
|
4
|
+
*
|
|
5
|
+
* @param data - The data to convert to a data URI.
|
|
6
|
+
* @param mime - The MIME type of the data.
|
|
7
|
+
* @returns The data URI.
|
|
8
|
+
*/
|
|
9
|
+
const formatDataURI = (data, mime) => `data:${mime};utf8,${encodeURIComponent(data)}`;
|
|
10
|
+
/**
|
|
11
|
+
* Returns a `Buffer` instance from the given data URI `uri`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { makeDataUriToBuffer } from "@stryke/core/http";
|
|
16
|
+
*
|
|
17
|
+
* const dataUriToBuffer = makeDataUriToBuffer({
|
|
18
|
+
* base64ToArrayBuffer: (base64) => Buffer.from(base64, "base64").buffer,
|
|
19
|
+
* stringToBuffer: (str) => Buffer.from(str, "utf8")https://avatars.githubusercontent.com/u/99053093?s=64&v=4.buffer,
|
|
20
|
+
* });
|
|
21
|
+
* const parsed = dataUriToBuffer("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==");
|
|
22
|
+
* console.log(parsed);
|
|
23
|
+
* // {
|
|
24
|
+
* // type: 'text/plain',
|
|
25
|
+
* // typeFull: 'text/plain;base64',
|
|
26
|
+
* // charset: '',
|
|
27
|
+
* // buffer: ArrayBuffer { ... }
|
|
28
|
+
* // }
|
|
29
|
+
* console.log(Buffer.from(parsed.buffer).toString("utf8"));
|
|
30
|
+
* // Hello, World!
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param convert - Conversion functions
|
|
34
|
+
* @returns An object containing the parsed data URI properties and the decoded data as a Buffer instance.
|
|
35
|
+
* @throws `TypeError` if `uri` is not a valid Data URI
|
|
36
|
+
*/
|
|
37
|
+
const makeDataUriToBuffer = (convert) => (uri) => {
|
|
38
|
+
uri = String(uri);
|
|
39
|
+
if (!/^data:/i.test(uri)) throw new Error("`uri` does not appear to be a Data URI (must begin with \"data:\")");
|
|
40
|
+
uri = uri.replace(/\r?\n/g, "");
|
|
41
|
+
const firstComma = uri.indexOf(",");
|
|
42
|
+
if (firstComma === -1 || firstComma <= 4) throw new Error("malformed data: URI");
|
|
43
|
+
const meta = uri.substring(5, firstComma).split(";");
|
|
44
|
+
let charset = "";
|
|
45
|
+
let base64 = false;
|
|
46
|
+
const type = meta[0] || "text/plain";
|
|
47
|
+
let typeFull = type;
|
|
48
|
+
for (let i = 1; i < meta.length; i++) if (meta[i] === "base64") base64 = true;
|
|
49
|
+
else if (meta[i]) {
|
|
50
|
+
typeFull += `;${meta[i]}`;
|
|
51
|
+
if (meta[i]?.indexOf("charset=") === 0) charset = meta[i].substring(8);
|
|
52
|
+
}
|
|
53
|
+
if (!meta[0] && !charset.length) {
|
|
54
|
+
typeFull += ";charset=US-ASCII";
|
|
55
|
+
charset = "US-ASCII";
|
|
56
|
+
}
|
|
57
|
+
const data = unescape(uri.substring(firstComma + 1));
|
|
58
|
+
const buffer = base64 ? convert.base64ToArrayBuffer(data) : convert.stringToBuffer(data);
|
|
59
|
+
return {
|
|
60
|
+
type,
|
|
61
|
+
typeFull,
|
|
62
|
+
charset,
|
|
63
|
+
buffer
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
export { formatDataURI, makeDataUriToBuffer };
|
|
2
69
|
//# sourceMappingURL=format-data-uri.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-data-uri.mjs","names":[],"sources":["../src/format-data-uri.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\n/**\n * Creates a data URI from a string of data.\n *\n * @param data - The data to convert to a data URI.\n * @param mime - The MIME type of the data.\n * @returns The data URI.\n */\nexport const formatDataURI = (data: string, mime: string): string =>\n `data:${mime};utf8,${encodeURIComponent(data)}`;\n\nexport interface ParsedDataURI {\n type: string;\n typeFull: string;\n charset: string;\n buffer: ArrayBuffer;\n}\n\nexport interface BufferConversionsInterface {\n base64ToArrayBuffer: (base64: string) => ArrayBuffer;\n stringToBuffer: (str: string) => ArrayBuffer;\n}\n\n/**\n * Returns a `Buffer` instance from the given data URI `uri`.\n *\n * @example\n * ```typescript\n * import { makeDataUriToBuffer } from \"@stryke/core/http\";\n *\n * const dataUriToBuffer = makeDataUriToBuffer({\n * base64ToArrayBuffer: (base64) => Buffer.from(base64, \"base64\").buffer,\n * stringToBuffer: (str) => Buffer.from(str, \"utf8\")https://avatars.githubusercontent.com/u/99053093?s=64&v=4.buffer,\n * });\n * const parsed = dataUriToBuffer(\"data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==\");\n * console.log(parsed);\n * // {\n * // type: 'text/plain',\n * // typeFull: 'text/plain;base64',\n * // charset: '',\n * // buffer: ArrayBuffer { ... }\n * // }\n * console.log(Buffer.from(parsed.buffer).toString(\"utf8\"));\n * // Hello, World!\n * ```\n *\n * @param convert - Conversion functions\n * @returns An object containing the parsed data URI properties and the decoded data as a Buffer instance.\n * @throws `TypeError` if `uri` is not a valid Data URI\n */\nexport const makeDataUriToBuffer =\n (convert: BufferConversionsInterface) =>\n (uri: string | URL): ParsedDataURI => {\n uri = String(uri);\n\n if (!/^data:/i.test(uri)) {\n throw new Error(\n '`uri` does not appear to be a Data URI (must begin with \"data:\")'\n );\n }\n\n // strip newlines\n uri = uri.replace(/\\r?\\n/g, \"\");\n\n // split the URI up into the \"metadata\" and the \"data\" portions\n const firstComma = uri.indexOf(\",\");\n if (firstComma === -1 || firstComma <= 4) {\n throw new Error(\"malformed data: URI\");\n }\n\n // remove the \"data:\" scheme and parse the metadata\n const meta = uri.substring(5, firstComma).split(\";\");\n\n let charset = \"\";\n let base64 = false;\n const type = meta[0] || \"text/plain\";\n let typeFull = type;\n for (let i = 1; i < meta.length; i++) {\n if (meta[i] === \"base64\") {\n base64 = true;\n } else if (meta[i]) {\n typeFull += `;${meta[i]}`;\n if (meta[i]?.indexOf(\"charset=\") === 0) {\n charset = meta[i]!.substring(8);\n }\n }\n }\n\n // defaults to US-ASCII only if type is not provided\n if (!meta[0] && !charset.length) {\n typeFull += \";charset=US-ASCII\";\n charset = \"US-ASCII\";\n }\n\n // get the encoded data portion and decode URI-encoded chars\n const data = unescape(uri.substring(firstComma + 1));\n const buffer = base64\n ? convert.base64ToArrayBuffer(data)\n : convert.stringToBuffer(data);\n\n return {\n type,\n typeFull,\n charset,\n buffer\n };\n };\n"],"mappings":"AAyBA,MAAa,
|
|
1
|
+
{"version":3,"file":"format-data-uri.mjs","names":[],"sources":["../src/format-data-uri.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\n/**\n * Creates a data URI from a string of data.\n *\n * @param data - The data to convert to a data URI.\n * @param mime - The MIME type of the data.\n * @returns The data URI.\n */\nexport const formatDataURI = (data: string, mime: string): string =>\n `data:${mime};utf8,${encodeURIComponent(data)}`;\n\nexport interface ParsedDataURI {\n type: string;\n typeFull: string;\n charset: string;\n buffer: ArrayBuffer;\n}\n\nexport interface BufferConversionsInterface {\n base64ToArrayBuffer: (base64: string) => ArrayBuffer;\n stringToBuffer: (str: string) => ArrayBuffer;\n}\n\n/**\n * Returns a `Buffer` instance from the given data URI `uri`.\n *\n * @example\n * ```typescript\n * import { makeDataUriToBuffer } from \"@stryke/core/http\";\n *\n * const dataUriToBuffer = makeDataUriToBuffer({\n * base64ToArrayBuffer: (base64) => Buffer.from(base64, \"base64\").buffer,\n * stringToBuffer: (str) => Buffer.from(str, \"utf8\")https://avatars.githubusercontent.com/u/99053093?s=64&v=4.buffer,\n * });\n * const parsed = dataUriToBuffer(\"data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==\");\n * console.log(parsed);\n * // {\n * // type: 'text/plain',\n * // typeFull: 'text/plain;base64',\n * // charset: '',\n * // buffer: ArrayBuffer { ... }\n * // }\n * console.log(Buffer.from(parsed.buffer).toString(\"utf8\"));\n * // Hello, World!\n * ```\n *\n * @param convert - Conversion functions\n * @returns An object containing the parsed data URI properties and the decoded data as a Buffer instance.\n * @throws `TypeError` if `uri` is not a valid Data URI\n */\nexport const makeDataUriToBuffer =\n (convert: BufferConversionsInterface) =>\n (uri: string | URL): ParsedDataURI => {\n uri = String(uri);\n\n if (!/^data:/i.test(uri)) {\n throw new Error(\n '`uri` does not appear to be a Data URI (must begin with \"data:\")'\n );\n }\n\n // strip newlines\n uri = uri.replace(/\\r?\\n/g, \"\");\n\n // split the URI up into the \"metadata\" and the \"data\" portions\n const firstComma = uri.indexOf(\",\");\n if (firstComma === -1 || firstComma <= 4) {\n throw new Error(\"malformed data: URI\");\n }\n\n // remove the \"data:\" scheme and parse the metadata\n const meta = uri.substring(5, firstComma).split(\";\");\n\n let charset = \"\";\n let base64 = false;\n const type = meta[0] || \"text/plain\";\n let typeFull = type;\n for (let i = 1; i < meta.length; i++) {\n if (meta[i] === \"base64\") {\n base64 = true;\n } else if (meta[i]) {\n typeFull += `;${meta[i]}`;\n if (meta[i]?.indexOf(\"charset=\") === 0) {\n charset = meta[i]!.substring(8);\n }\n }\n }\n\n // defaults to US-ASCII only if type is not provided\n if (!meta[0] && !charset.length) {\n typeFull += \";charset=US-ASCII\";\n charset = \"US-ASCII\";\n }\n\n // get the encoded data portion and decode URI-encoded chars\n const data = unescape(uri.substring(firstComma + 1));\n const buffer = base64\n ? convert.base64ToArrayBuffer(data)\n : convert.stringToBuffer(data);\n\n return {\n type,\n typeFull,\n charset,\n buffer\n };\n };\n"],"mappings":";;;;;;;;AAyBA,MAAa,iBAAiB,MAAc,SAC1C,QAAQ,KAAK,QAAQ,mBAAmB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyC/C,MAAa,uBACV,aACA,QAAqC;AACpC,OAAM,OAAO,IAAI;AAEjB,KAAI,CAAC,UAAU,KAAK,IAAI,CACtB,OAAM,IAAI,MACR,qEACD;AAIH,OAAM,IAAI,QAAQ,UAAU,GAAG;CAG/B,MAAM,aAAa,IAAI,QAAQ,IAAI;AACnC,KAAI,eAAe,MAAM,cAAc,EACrC,OAAM,IAAI,MAAM,sBAAsB;CAIxC,MAAM,OAAO,IAAI,UAAU,GAAG,WAAW,CAAC,MAAM,IAAI;CAEpD,IAAI,UAAU;CACd,IAAI,SAAS;CACb,MAAM,OAAO,KAAK,MAAM;CACxB,IAAI,WAAW;AACf,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,IAC/B,KAAI,KAAK,OAAO,SACd,UAAS;UACA,KAAK,IAAI;AAClB,cAAY,IAAI,KAAK;AACrB,MAAI,KAAK,IAAI,QAAQ,WAAW,KAAK,EACnC,WAAU,KAAK,GAAI,UAAU,EAAE;;AAMrC,KAAI,CAAC,KAAK,MAAM,CAAC,QAAQ,QAAQ;AAC/B,cAAY;AACZ,YAAU;;CAIZ,MAAM,OAAO,SAAS,IAAI,UAAU,aAAa,EAAE,CAAC;CACpD,MAAM,SAAS,SACX,QAAQ,oBAAoB,KAAK,GACjC,QAAQ,eAAe,KAAK;AAEhC,QAAO;EACL;EACA;EACA;EACA;EACD"}
|
package/dist/get-free-port.cjs
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let node_http = require("node:http");
|
|
3
|
+
|
|
4
|
+
//#region src/get-free-port.ts
|
|
5
|
+
/**
|
|
6
|
+
* Finds and returns a free port on the local machine by creating a temporary server that listens on port 0. The operating system assigns an available port, which is then retrieved and returned.
|
|
7
|
+
*
|
|
8
|
+
* @returns A promise that resolves to a free port number.
|
|
9
|
+
*/
|
|
10
|
+
async function getFreePort() {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const server = (0, node_http.createServer)(() => {});
|
|
13
|
+
server.listen(0, () => {
|
|
14
|
+
const address = server.address();
|
|
15
|
+
server.close();
|
|
16
|
+
if (address && typeof address === "object") resolve(address.port);
|
|
17
|
+
else reject(/* @__PURE__ */ new Error(`invalid address from server: ${address?.toString()}`));
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.getFreePort = getFreePort;
|
package/dist/get-free-port.mjs
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
import{createServer
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
|
|
3
|
+
//#region src/get-free-port.ts
|
|
4
|
+
/**
|
|
5
|
+
* Finds and returns a free port on the local machine by creating a temporary server that listens on port 0. The operating system assigns an available port, which is then retrieved and returned.
|
|
6
|
+
*
|
|
7
|
+
* @returns A promise that resolves to a free port number.
|
|
8
|
+
*/
|
|
9
|
+
async function getFreePort() {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const server = createServer(() => {});
|
|
12
|
+
server.listen(0, () => {
|
|
13
|
+
const address = server.address();
|
|
14
|
+
server.close();
|
|
15
|
+
if (address && typeof address === "object") resolve(address.port);
|
|
16
|
+
else reject(/* @__PURE__ */ new Error(`invalid address from server: ${address?.toString()}`));
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { getFreePort };
|
|
2
23
|
//# sourceMappingURL=get-free-port.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-free-port.mjs","names":[],"sources":["../src/get-free-port.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { createServer } from \"node:http\";\n\n/**\n * Finds and returns a free port on the local machine by creating a temporary server that listens on port 0. The operating system assigns an available port, which is then retrieved and returned.\n *\n * @returns A promise that resolves to a free port number.\n */\nexport async function getFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer(() => {});\n server.listen(0, () => {\n const address = server.address();\n server.close();\n\n if (address && typeof address === \"object\") {\n resolve(address.port);\n } else {\n reject(\n new Error(`invalid address from server: ${address?.toString()}`)\n );\n }\n });\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-free-port.mjs","names":[],"sources":["../src/get-free-port.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { createServer } from \"node:http\";\n\n/**\n * Finds and returns a free port on the local machine by creating a temporary server that listens on port 0. The operating system assigns an available port, which is then retrieved and returned.\n *\n * @returns A promise that resolves to a free port number.\n */\nexport async function getFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer(() => {});\n server.listen(0, () => {\n const address = server.address();\n server.close();\n\n if (address && typeof address === \"object\") {\n resolve(address.port);\n } else {\n reject(\n new Error(`invalid address from server: ${address?.toString()}`)\n );\n }\n });\n });\n}\n"],"mappings":";;;;;;;;AAyBA,eAAsB,cAA+B;AACnD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,SAAS,mBAAmB,GAAG;AACrC,SAAO,OAAO,SAAS;GACrB,MAAM,UAAU,OAAO,SAAS;AAChC,UAAO,OAAO;AAEd,OAAI,WAAW,OAAO,YAAY,SAChC,SAAQ,QAAQ,KAAK;OAErB,wBACE,IAAI,MAAM,gCAAgC,SAAS,UAAU,GAAG,CACjE;IAEH;GACF"}
|