effect 4.0.2 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Context.js +3 -3
- package/dist/Context.js.map +1 -1
- package/dist/Crypto.d.ts +33 -5
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +8 -2
- package/dist/Crypto.js.map +1 -1
- package/dist/DateTime.d.ts +9 -6
- package/dist/DateTime.d.ts.map +1 -1
- package/dist/DateTime.js +9 -6
- package/dist/DateTime.js.map +1 -1
- package/dist/Duration.d.ts +6 -6
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +27 -8
- package/dist/Duration.js.map +1 -1
- package/dist/FileSystem.d.ts +44 -2
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js.map +1 -1
- package/dist/Schema.d.ts +473 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +355 -4
- package/dist/Schema.js.map +1 -1
- package/dist/Stdio.d.ts +7 -1
- package/dist/Stdio.d.ts.map +1 -1
- package/dist/Stdio.js +1 -0
- package/dist/Stdio.js.map +1 -1
- package/dist/Stream.d.ts +11 -11
- package/dist/Stream.js +5 -5
- package/dist/ai/McpServer.d.ts +6 -0
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +65 -23
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +5 -0
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +1 -0
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/cli/CliOutput.d.ts +27 -0
- package/dist/cli/CliOutput.d.ts.map +1 -1
- package/dist/cli/CliOutput.js +33 -10
- package/dist/cli/CliOutput.js.map +1 -1
- package/dist/cli/Command.d.ts.map +1 -1
- package/dist/cli/Command.js +6 -3
- package/dist/cli/Command.js.map +1 -1
- package/dist/cli/Completions.d.ts +3 -3
- package/dist/cli/Completions.d.ts.map +1 -1
- package/dist/cli/Completions.js +8 -5
- package/dist/cli/Completions.js.map +1 -1
- package/dist/cli/GlobalFlag.d.ts +5 -4
- package/dist/cli/GlobalFlag.d.ts.map +1 -1
- package/dist/cli/GlobalFlag.js +3 -3
- package/dist/cli/GlobalFlag.js.map +1 -1
- package/dist/cli/Prompt.d.ts +17 -1
- package/dist/cli/Prompt.d.ts.map +1 -1
- package/dist/cli/Prompt.js +119 -114
- package/dist/cli/Prompt.js.map +1 -1
- package/dist/cli/internal/ansi.d.ts +0 -1
- package/dist/cli/internal/ansi.d.ts.map +1 -1
- package/dist/cli/internal/ansi.js +20 -3
- package/dist/cli/internal/ansi.js.map +1 -1
- package/dist/cli/internal/completions/powershell.d.ts +2 -0
- package/dist/cli/internal/completions/powershell.d.ts.map +1 -0
- package/dist/cli/internal/completions/powershell.js +273 -0
- package/dist/cli/internal/completions/powershell.js.map +1 -0
- package/dist/cli/internal/completions/zsh.js +3 -2
- package/dist/cli/internal/completions/zsh.js.map +1 -1
- package/dist/cli/internal/wizard.d.ts +3 -3
- package/dist/cli/internal/wizard.d.ts.map +1 -1
- package/dist/cli/internal/wizard.js +21 -18
- package/dist/cli/internal/wizard.js.map +1 -1
- package/dist/cluster/ClusterSchema.d.ts +28 -0
- package/dist/cluster/ClusterSchema.d.ts.map +1 -1
- package/dist/cluster/ClusterSchema.js +30 -0
- package/dist/cluster/ClusterSchema.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +10 -18
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +18 -3
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +31 -11
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +8 -2
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +181 -62
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts +59 -19
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +84 -55
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts +68 -19
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +191 -113
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +104 -37
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/http/FindMyWay/internal/router.js +3 -6
- package/dist/http/FindMyWay/internal/router.js.map +1 -1
- package/dist/http/HttpClient.d.ts +6 -0
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +39 -2
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +4 -2
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/internal/effect.js +12 -7
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/net/AddressResolver.d.ts +145 -0
- package/dist/net/AddressResolver.d.ts.map +1 -0
- package/dist/net/AddressResolver.js +114 -0
- package/dist/net/AddressResolver.js.map +1 -0
- package/dist/net/Dns.d.ts +596 -0
- package/dist/net/Dns.d.ts.map +1 -0
- package/dist/net/Dns.js +549 -0
- package/dist/net/Dns.js.map +1 -0
- package/dist/net/Host.d.ts +320 -0
- package/dist/net/Host.d.ts.map +1 -0
- package/dist/net/Host.js +342 -0
- package/dist/net/Host.js.map +1 -0
- package/dist/net/IpInterface.d.ts +76 -3
- package/dist/net/IpInterface.d.ts.map +1 -1
- package/dist/net/IpInterface.js +53 -4
- package/dist/net/IpInterface.js.map +1 -1
- package/dist/net/IpNetwork.d.ts +82 -8
- package/dist/net/IpNetwork.d.ts.map +1 -1
- package/dist/net/IpNetwork.js +60 -4
- package/dist/net/IpNetwork.js.map +1 -1
- package/dist/net/NetAddress.d.ts +388 -35
- package/dist/net/NetAddress.d.ts.map +1 -1
- package/dist/net/NetAddress.js +350 -34
- package/dist/net/NetAddress.js.map +1 -1
- package/dist/net/index.d.ts +15 -0
- package/dist/net/index.d.ts.map +1 -1
- package/dist/net/index.js +15 -0
- package/dist/net/index.js.map +1 -1
- package/dist/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/observability/OtlpMetrics.js +15 -21
- package/dist/observability/OtlpMetrics.js.map +1 -1
- package/dist/observability/PrometheusMetrics.js +1 -0
- package/dist/observability/PrometheusMetrics.js.map +1 -1
- package/dist/persistence/PersistedQueue.d.ts +32 -3
- package/dist/persistence/PersistedQueue.d.ts.map +1 -1
- package/dist/persistence/PersistedQueue.js +75 -16
- package/dist/persistence/PersistedQueue.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +22 -6
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +12 -5
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts +6 -0
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +42 -20
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/socket/DatagramSocket.d.ts +456 -0
- package/dist/socket/DatagramSocket.d.ts.map +1 -0
- package/dist/socket/DatagramSocket.js +535 -0
- package/dist/socket/DatagramSocket.js.map +1 -0
- package/dist/socket/Socket.d.ts +14 -1
- package/dist/socket/Socket.d.ts.map +1 -1
- package/dist/socket/Socket.js +9 -1
- package/dist/socket/Socket.js.map +1 -1
- package/dist/socket/index.d.ts +5 -0
- package/dist/socket/index.d.ts.map +1 -1
- package/dist/socket/index.js +5 -0
- package/dist/socket/index.js.map +1 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +7 -2
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +7 -1
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +31 -6
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/testing/TestCrypto.d.ts +73 -0
- package/dist/testing/TestCrypto.d.ts.map +1 -0
- package/dist/testing/TestCrypto.js +87 -0
- package/dist/testing/TestCrypto.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/workflow/DurableDeferred.d.ts +54 -0
- package/dist/workflow/DurableDeferred.d.ts.map +1 -1
- package/dist/workflow/DurableDeferred.js +78 -49
- package/dist/workflow/DurableDeferred.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +2 -1
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Context.ts +3 -3
- package/src/Crypto.ts +43 -9
- package/src/DateTime.ts +9 -6
- package/src/Duration.ts +36 -16
- package/src/FileSystem.ts +48 -2
- package/src/Schema.ts +669 -5
- package/src/Stdio.ts +9 -2
- package/src/Stream.ts +11 -11
- package/src/ai/McpServer.ts +63 -23
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +5 -0
- package/src/ai/internal/mcpProtocol.ts +3 -0
- package/src/ai/internal/mcpRuntime.ts +2 -0
- package/src/cli/CliOutput.ts +33 -16
- package/src/cli/Command.ts +4 -3
- package/src/cli/Completions.ts +9 -6
- package/src/cli/GlobalFlag.ts +19 -11
- package/src/cli/Prompt.ts +159 -149
- package/src/cli/internal/ansi.ts +26 -3
- package/src/cli/internal/completions/powershell.ts +322 -0
- package/src/cli/internal/completions/zsh.ts +4 -2
- package/src/cli/internal/wizard.ts +34 -26
- package/src/cluster/ClusterSchema.ts +32 -0
- package/src/cluster/ClusterWorkflowEngine.ts +13 -24
- package/src/cluster/MessageStorage.ts +45 -14
- package/src/cluster/Runners.ts +8 -2
- package/src/cluster/Sharding.ts +207 -49
- package/src/cluster/SqlMessageStorage.ts +118 -84
- package/src/cluster/SqlRunnerStorage.ts +224 -128
- package/src/cluster/internal/entityManager.ts +151 -55
- package/src/http/FindMyWay/internal/router.ts +4 -7
- package/src/http/HttpClient.ts +56 -2
- package/src/http/HttpTraceContext.ts +8 -2
- package/src/internal/effect.ts +15 -13
- package/src/internal/version.ts +1 -1
- package/src/net/AddressResolver.ts +222 -0
- package/src/net/Dns.ts +1035 -0
- package/src/net/Host.ts +472 -0
- package/src/net/IpInterface.ts +117 -7
- package/src/net/IpNetwork.ts +116 -17
- package/src/net/NetAddress.ts +611 -76
- package/src/net/index.ts +18 -0
- package/src/observability/OtlpMetrics.ts +12 -23
- package/src/observability/PrometheusMetrics.ts +1 -0
- package/src/persistence/PersistedQueue.ts +146 -53
- package/src/rpc/RpcClient.ts +41 -19
- package/src/rpc/RpcServer.ts +60 -25
- package/src/socket/DatagramSocket.ts +919 -0
- package/src/socket/Socket.ts +22 -2
- package/src/socket/index.ts +6 -0
- package/src/sql/Migrator.ts +21 -5
- package/src/sql/SqlClient.ts +39 -15
- package/src/testing/TestCrypto.ts +94 -0
- package/src/testing/index.ts +6 -0
- package/src/workflow/DurableDeferred.ts +123 -48
- package/src/workflow/WorkflowEngine.ts +2 -1
package/dist/net/NetAddress.js
CHANGED
|
@@ -2,9 +2,9 @@ import * as Data from "../Data.js";
|
|
|
2
2
|
import * as Equal from "../Equal.js";
|
|
3
3
|
import { dual } from "../Function.js";
|
|
4
4
|
import * as Hash from "../Hash.js";
|
|
5
|
-
import
|
|
5
|
+
import * as Inspectable from "../Inspectable.js";
|
|
6
6
|
import * as Option from "../Option.js";
|
|
7
|
-
import { hasProperty } from "../Predicate.js";
|
|
7
|
+
import { hasProperty, isTupleOf } from "../Predicate.js";
|
|
8
8
|
import * as Result from "../Result.js";
|
|
9
9
|
const TypeId = "~effect/net/NetAddress";
|
|
10
10
|
const MulticastTypeId = "~effect/net/NetAddress/MulticastAddress";
|
|
@@ -71,6 +71,32 @@ export const isIpAddress = u => isIpv4Address(u) || isIpv6Address(u);
|
|
|
71
71
|
* @since 4.0.0
|
|
72
72
|
*/
|
|
73
73
|
export const width = address => isIpv4Address(address) ? 32 : 128;
|
|
74
|
+
/**
|
|
75
|
+
* Returns the family of an IP address or internet address.
|
|
76
|
+
*
|
|
77
|
+
* **Example** (Reading address families)
|
|
78
|
+
*
|
|
79
|
+
* ```ts import.meta.vitest
|
|
80
|
+
* import { NetAddress } from "effect/net"
|
|
81
|
+
*
|
|
82
|
+
* NetAddress.familyOf(NetAddress.ipv4Loopback) // => "IPv4"
|
|
83
|
+
* NetAddress.familyOf(NetAddress.inetAddressFromStringUnsafe("[::1]:80")) // => "IPv6"
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @stability experimental
|
|
87
|
+
* @category getters
|
|
88
|
+
* @since 4.0.0
|
|
89
|
+
*/
|
|
90
|
+
export const familyOf = self => isIpv4Address(self) || isInetAddressV4(self) ? "IPv4" : "IPv6";
|
|
91
|
+
/**
|
|
92
|
+
* Returns `true` when an IP address or internet address belongs to a family,
|
|
93
|
+
* narrowing it to that family.
|
|
94
|
+
*
|
|
95
|
+
* @stability experimental
|
|
96
|
+
* @category predicates
|
|
97
|
+
* @since 4.0.0
|
|
98
|
+
*/
|
|
99
|
+
export const isFamily = /*#__PURE__*/dual(2, (self, family) => familyOf(self) === family);
|
|
74
100
|
/**
|
|
75
101
|
* Returns `true` when a value is a MAC address.
|
|
76
102
|
*
|
|
@@ -120,6 +146,7 @@ export const isUnixPathAddress = u => isAddress(u) && u._tag === "UnixPathAddres
|
|
|
120
146
|
*/
|
|
121
147
|
export const isSocketAddress = u => isInetAddress(u) || isUnixPathAddress(u);
|
|
122
148
|
const Ipv4Proto = {
|
|
149
|
+
...Inspectable.BaseProto,
|
|
123
150
|
_tag: "Ipv4Address",
|
|
124
151
|
[TypeId]: TypeId,
|
|
125
152
|
[Equal.symbol](that) {
|
|
@@ -133,12 +160,10 @@ const Ipv4Proto = {
|
|
|
133
160
|
},
|
|
134
161
|
toJSON() {
|
|
135
162
|
return this.toString();
|
|
136
|
-
},
|
|
137
|
-
[NodeInspectSymbol]() {
|
|
138
|
-
return this.toJSON();
|
|
139
163
|
}
|
|
140
164
|
};
|
|
141
165
|
const Ipv6Proto = {
|
|
166
|
+
...Inspectable.BaseProto,
|
|
142
167
|
_tag: "Ipv6Address",
|
|
143
168
|
[TypeId]: TypeId,
|
|
144
169
|
[Equal.symbol](that) {
|
|
@@ -159,12 +184,10 @@ const Ipv6Proto = {
|
|
|
159
184
|
},
|
|
160
185
|
toJSON() {
|
|
161
186
|
return this.toString();
|
|
162
|
-
},
|
|
163
|
-
[NodeInspectSymbol]() {
|
|
164
|
-
return this.toJSON();
|
|
165
187
|
}
|
|
166
188
|
};
|
|
167
189
|
const MacProto = {
|
|
190
|
+
...Inspectable.BaseProto,
|
|
168
191
|
_tag: "MacAddress",
|
|
169
192
|
[TypeId]: TypeId,
|
|
170
193
|
[Equal.symbol](that) {
|
|
@@ -178,9 +201,6 @@ const MacProto = {
|
|
|
178
201
|
},
|
|
179
202
|
toJSON() {
|
|
180
203
|
return this.toString();
|
|
181
|
-
},
|
|
182
|
-
[NodeInspectSymbol]() {
|
|
183
|
-
return this.toJSON();
|
|
184
204
|
}
|
|
185
205
|
};
|
|
186
206
|
const bytesEqual = (self, that) => {
|
|
@@ -275,6 +295,14 @@ const addressError = (input, message) => Result.fail(new NetAddressError({
|
|
|
275
295
|
input,
|
|
276
296
|
message
|
|
277
297
|
}));
|
|
298
|
+
// Checks by index because `every` skips holes in sparse arrays.
|
|
299
|
+
const allIntegersInRange = (values, max) => {
|
|
300
|
+
for (let i = 0; i < values.length; i++) {
|
|
301
|
+
const n = values[i];
|
|
302
|
+
if (!Number.isInteger(n) || n < 0 || n > max) return false;
|
|
303
|
+
}
|
|
304
|
+
return true;
|
|
305
|
+
};
|
|
278
306
|
/**
|
|
279
307
|
* Creates an IPv4 address from four checked octets.
|
|
280
308
|
*
|
|
@@ -283,7 +311,7 @@ const addressError = (input, message) => Result.fail(new NetAddressError({
|
|
|
283
311
|
* @since 4.0.0
|
|
284
312
|
*/
|
|
285
313
|
export const ipv4FromOctets = octets => {
|
|
286
|
-
if (!octets
|
|
314
|
+
if (!allIntegersInRange(octets, 255)) {
|
|
287
315
|
return addressError(octets, "octets must be integers from 0 through 255");
|
|
288
316
|
}
|
|
289
317
|
return Result.succeed(makeIpv4(packOctets(octets[0], octets[1], octets[2], octets[3])));
|
|
@@ -296,7 +324,7 @@ export const ipv4FromOctets = octets => {
|
|
|
296
324
|
* @since 4.0.0
|
|
297
325
|
*/
|
|
298
326
|
export const ipv6FromSegments = segments => {
|
|
299
|
-
if (!segments
|
|
327
|
+
if (!allIntegersInRange(segments, 0xffff)) {
|
|
300
328
|
return addressError(segments, "segments must be integers from 0 through 65535");
|
|
301
329
|
}
|
|
302
330
|
return Result.succeed(makeIpv6(segments[0] * 0x10000 + segments[1], segments[2] * 0x10000 + segments[3], segments[4] * 0x10000 + segments[5], segments[6] * 0x10000 + segments[7]));
|
|
@@ -309,7 +337,7 @@ export const ipv6FromSegments = segments => {
|
|
|
309
337
|
* @since 4.0.0
|
|
310
338
|
*/
|
|
311
339
|
export const macAddressFromOctets = octets => {
|
|
312
|
-
if (!octets
|
|
340
|
+
if (!allIntegersInRange(octets, 255)) {
|
|
313
341
|
return addressError(octets, "octets must be integers from 0 through 255");
|
|
314
342
|
}
|
|
315
343
|
return Result.succeed(makeMac(new Uint8Array(octets)));
|
|
@@ -335,6 +363,29 @@ export const macAddressFromString = input => {
|
|
|
335
363
|
* @since 4.0.0
|
|
336
364
|
*/
|
|
337
365
|
export const macAddressFromStringUnsafe = input => Result.getOrThrow(macAddressFromString(input));
|
|
366
|
+
/**
|
|
367
|
+
* Converts a `MacAddressInput` to a MAC address, parsing strings like
|
|
368
|
+
* `macAddressFromString`, checking octets like `macAddressFromOctets`, and
|
|
369
|
+
* returning MAC addresses unchanged.
|
|
370
|
+
*
|
|
371
|
+
* @stability unstable
|
|
372
|
+
* @category constructors
|
|
373
|
+
* @since 4.0.0
|
|
374
|
+
*/
|
|
375
|
+
export const macAddressFromInput = input => {
|
|
376
|
+
if (isMacAddress(input)) return Result.succeed(input);
|
|
377
|
+
if (typeof input === "string") return macAddressFromString(input);
|
|
378
|
+
if (Array.isArray(input) && isTupleOf(input, 6)) return macAddressFromOctets(input);
|
|
379
|
+
return addressError(input, "expected a MAC address, string, or 6 octets");
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* Converts a trusted `MacAddressInput` to a MAC address, throwing on failure.
|
|
383
|
+
*
|
|
384
|
+
* @stability unstable
|
|
385
|
+
* @category unsafe
|
|
386
|
+
* @since 4.0.0
|
|
387
|
+
*/
|
|
388
|
+
export const macAddressFromInputUnsafe = input => Result.getOrThrow(macAddressFromInput(input));
|
|
338
389
|
/**
|
|
339
390
|
* Parses a strict dotted-decimal IPv4 address.
|
|
340
391
|
*
|
|
@@ -426,6 +477,127 @@ export const ipFromString = input => {
|
|
|
426
477
|
* @since 4.0.0
|
|
427
478
|
*/
|
|
428
479
|
export const ipFromStringUnsafe = input => Result.getOrThrow(ipFromString(input));
|
|
480
|
+
/**
|
|
481
|
+
* Converts an `IpAddressInput` to an IP address, returning IP addresses
|
|
482
|
+
* unchanged.
|
|
483
|
+
*
|
|
484
|
+
* **Details**
|
|
485
|
+
*
|
|
486
|
+
* Strings are parsed like `ipFromString`. Four octets or bytes make an IPv4
|
|
487
|
+
* address, and eight segments or sixteen bytes make an IPv6 address.
|
|
488
|
+
*
|
|
489
|
+
* **Example** (Converting IP address inputs)
|
|
490
|
+
*
|
|
491
|
+
* ```ts import.meta.vitest
|
|
492
|
+
* import { Result } from "effect"
|
|
493
|
+
* import { NetAddress } from "effect/net"
|
|
494
|
+
*
|
|
495
|
+
* const address = Result.getOrThrow(NetAddress.ipFromInput("192.0.2.1"))
|
|
496
|
+
* NetAddress.formatIp(address) // => "192.0.2.1"
|
|
497
|
+
* Result.getOrThrow(NetAddress.ipFromInput(address)) === address // => true
|
|
498
|
+
* NetAddress.formatIp(Result.getOrThrow(NetAddress.ipFromInput([192, 0, 2, 1]))) // => "192.0.2.1"
|
|
499
|
+
* Result.isFailure(NetAddress.ipFromInput("example.com")) // => true
|
|
500
|
+
* ```
|
|
501
|
+
*
|
|
502
|
+
* @stability unstable
|
|
503
|
+
* @category constructors
|
|
504
|
+
* @since 4.0.0
|
|
505
|
+
*/
|
|
506
|
+
export const ipFromInput = input => {
|
|
507
|
+
if (isIpAddress(input)) return Result.succeed(input);
|
|
508
|
+
if (typeof input === "string") return ipFromString(input);
|
|
509
|
+
if (input instanceof Uint8Array && input.length === 4) return Result.succeed(ipv4FromBytesUnsafe(input));
|
|
510
|
+
if (input instanceof Uint8Array && input.length === 16) return Result.succeed(ipv6FromBytesUnsafe(input));
|
|
511
|
+
if (Array.isArray(input) && isTupleOf(input, 4)) return ipv4FromOctets(input);
|
|
512
|
+
if (Array.isArray(input) && isTupleOf(input, 8)) return ipv6FromSegments(input);
|
|
513
|
+
return addressError(input, "expected an IP address, string, 4 octets, 8 segments, or 4 or 16 bytes");
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* Converts a trusted `IpAddressInput` to an IP address, throwing on failure.
|
|
517
|
+
*
|
|
518
|
+
* @stability unstable
|
|
519
|
+
* @category unsafe
|
|
520
|
+
* @since 4.0.0
|
|
521
|
+
*/
|
|
522
|
+
export const ipFromInputUnsafe = input => Result.getOrThrow(ipFromInput(input));
|
|
523
|
+
/**
|
|
524
|
+
* Converts an `Ipv4AddressInput` to an IPv4 address, parsing strings like
|
|
525
|
+
* `ipv4FromString`, checking octets like `ipv4FromOctets`, and returning IPv4
|
|
526
|
+
* addresses unchanged.
|
|
527
|
+
*
|
|
528
|
+
* @stability unstable
|
|
529
|
+
* @category constructors
|
|
530
|
+
* @since 4.0.0
|
|
531
|
+
*/
|
|
532
|
+
export const ipv4FromInput = input => {
|
|
533
|
+
if (isIpv4Address(input)) return Result.succeed(input);
|
|
534
|
+
if (typeof input === "string") return ipv4FromString(input);
|
|
535
|
+
if (input instanceof Uint8Array && input.length === 4) return Result.succeed(ipv4FromBytesUnsafe(input));
|
|
536
|
+
if (Array.isArray(input) && isTupleOf(input, 4)) return ipv4FromOctets(input);
|
|
537
|
+
return addressError(input, "expected an IPv4 address, string, 4 octets, or 4 bytes");
|
|
538
|
+
};
|
|
539
|
+
/**
|
|
540
|
+
* Converts an `Ipv6AddressInput` to an IPv6 address, parsing strings like
|
|
541
|
+
* `ipv6FromString`, checking segments like `ipv6FromSegments`, and returning
|
|
542
|
+
* IPv6 addresses unchanged.
|
|
543
|
+
*
|
|
544
|
+
* @stability unstable
|
|
545
|
+
* @category constructors
|
|
546
|
+
* @since 4.0.0
|
|
547
|
+
*/
|
|
548
|
+
export const ipv6FromInput = input => {
|
|
549
|
+
if (isIpv6Address(input)) return Result.succeed(input);
|
|
550
|
+
if (typeof input === "string") return ipv6FromString(input);
|
|
551
|
+
if (input instanceof Uint8Array && input.length === 16) return Result.succeed(ipv6FromBytesUnsafe(input));
|
|
552
|
+
if (Array.isArray(input) && isTupleOf(input, 8)) return ipv6FromSegments(input);
|
|
553
|
+
return addressError(input, "expected an IPv6 address, string, 8 segments, or 16 bytes");
|
|
554
|
+
};
|
|
555
|
+
/**
|
|
556
|
+
* Returns `true` when a value is a canonical scoped IPv6 literal.
|
|
557
|
+
*
|
|
558
|
+
* @stability experimental
|
|
559
|
+
* @category guards
|
|
560
|
+
* @since 4.0.0
|
|
561
|
+
*/
|
|
562
|
+
export const isScopedIpv6Literal = u => {
|
|
563
|
+
if (typeof u !== "string" || !u.includes("%")) return false;
|
|
564
|
+
const result = scopedIpv6LiteralFromString(u);
|
|
565
|
+
return Result.isSuccess(result) && result.success === u;
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* Parses an IPv6 literal with a numeric or named zone, such as `fe80::1%eth0`.
|
|
569
|
+
*
|
|
570
|
+
* @stability experimental
|
|
571
|
+
* @category decoding
|
|
572
|
+
* @since 4.0.0
|
|
573
|
+
*/
|
|
574
|
+
export const scopedIpv6LiteralFromString = input => {
|
|
575
|
+
const separator = input.indexOf("%");
|
|
576
|
+
if (separator === -1) return addressError(input, "expected an IPv6 zone");
|
|
577
|
+
let zone = input.slice(separator + 1);
|
|
578
|
+
if (zone.length === 0 || /[%[\]/\s\p{Cc}]/u.test(zone)) {
|
|
579
|
+
return addressError(input, "invalid IPv6 scope identifier");
|
|
580
|
+
}
|
|
581
|
+
if (/^\d+$/.test(zone)) {
|
|
582
|
+
const scopeId = Number(zone);
|
|
583
|
+
if (scopeId > 0xffffffff) return addressError(input, "scope identifier must be an unsigned 32-bit integer");
|
|
584
|
+
zone = String(scopeId);
|
|
585
|
+
}
|
|
586
|
+
return Result.map(ipv6FromString(input.slice(0, separator)), address => `${formatIp(address)}%${zone}`);
|
|
587
|
+
};
|
|
588
|
+
/**
|
|
589
|
+
* Converts a `ScopedIpv6LiteralInput` to a scoped IPv6 literal, parsing it
|
|
590
|
+
* like `scopedIpv6LiteralFromString`.
|
|
591
|
+
*
|
|
592
|
+
* **Details**
|
|
593
|
+
*
|
|
594
|
+
* Scoped IPv6 literals are strings, so every input is parsed.
|
|
595
|
+
*
|
|
596
|
+
* @stability experimental
|
|
597
|
+
* @category constructors
|
|
598
|
+
* @since 4.0.0
|
|
599
|
+
*/
|
|
600
|
+
export const scopedIpv6LiteralFromInput = input => scopedIpv6LiteralFromString(input);
|
|
429
601
|
/**
|
|
430
602
|
* Returns the four numeric octets of an IPv4 address in a fresh tuple.
|
|
431
603
|
*
|
|
@@ -738,6 +910,7 @@ export function toCanonical(self) {
|
|
|
738
910
|
return isIpv6Address(self) ? Option.getOrElse(fromIpv4Mapped(self), () => self) : self;
|
|
739
911
|
}
|
|
740
912
|
const InetV4Proto = {
|
|
913
|
+
...Inspectable.BaseProto,
|
|
741
914
|
_tag: "InetAddressV4",
|
|
742
915
|
[TypeId]: TypeId,
|
|
743
916
|
[Equal.symbol](that) {
|
|
@@ -751,12 +924,10 @@ const InetV4Proto = {
|
|
|
751
924
|
},
|
|
752
925
|
toJSON() {
|
|
753
926
|
return this.toString();
|
|
754
|
-
},
|
|
755
|
-
[NodeInspectSymbol]() {
|
|
756
|
-
return this.toJSON();
|
|
757
927
|
}
|
|
758
928
|
};
|
|
759
929
|
const InetV6Proto = {
|
|
930
|
+
...Inspectable.BaseProto,
|
|
760
931
|
_tag: "InetAddressV6",
|
|
761
932
|
[TypeId]: TypeId,
|
|
762
933
|
[Equal.symbol](that) {
|
|
@@ -770,9 +941,6 @@ const InetV6Proto = {
|
|
|
770
941
|
},
|
|
771
942
|
toJSON() {
|
|
772
943
|
return this.toString();
|
|
773
|
-
},
|
|
774
|
-
[NodeInspectSymbol]() {
|
|
775
|
-
return this.toJSON();
|
|
776
944
|
}
|
|
777
945
|
};
|
|
778
946
|
const checkPort = port => Number.isInteger(port) && port >= 0 && port <= 0xffff;
|
|
@@ -857,6 +1025,103 @@ export const inetAddressFromIpString = (address, port) => {
|
|
|
857
1025
|
* @since 4.0.0
|
|
858
1026
|
*/
|
|
859
1027
|
export const inetAddressFromIpStringUnsafe = (address, port) => Result.getOrThrow(inetAddressFromIpString(address, port));
|
|
1028
|
+
/**
|
|
1029
|
+
* Creates an internet address from a trusted native numeric host and port.
|
|
1030
|
+
* Named IPv6 zones are resolved using the supplied interface-to-scope map.
|
|
1031
|
+
* Use only for runtime-supplied socket addresses: this skips input validation,
|
|
1032
|
+
* so malformed strings or ports may silently produce incorrect values. An
|
|
1033
|
+
* unknown named IPv6 zone throws rather than losing its scope.
|
|
1034
|
+
*
|
|
1035
|
+
* @stability unstable
|
|
1036
|
+
* @category unsafe
|
|
1037
|
+
* @since 4.0.0
|
|
1038
|
+
*/
|
|
1039
|
+
export const inetAddressFromNativeUnsafe = (host, port, scopeIds) => {
|
|
1040
|
+
const zoneStart = host.indexOf("%");
|
|
1041
|
+
const end = zoneStart === -1 ? host.length : zoneStart;
|
|
1042
|
+
if (host.indexOf(":") === -1) {
|
|
1043
|
+
const self = Object.create(InetV4Proto);
|
|
1044
|
+
self.address = makeIpv4(parseNativeIpv4(host, 0, end));
|
|
1045
|
+
self.port = port;
|
|
1046
|
+
return Object.freeze(self);
|
|
1047
|
+
}
|
|
1048
|
+
let scopeId = 0;
|
|
1049
|
+
if (zoneStart !== -1) {
|
|
1050
|
+
const zone = host.slice(zoneStart + 1);
|
|
1051
|
+
const resolved = numericZone.test(zone) ? Number(zone) : scopeIds?.get(zone);
|
|
1052
|
+
if (resolved === undefined) throw new Error(`unknown IPv6 interface: ${zone}`);
|
|
1053
|
+
scopeId = resolved;
|
|
1054
|
+
}
|
|
1055
|
+
let w0 = 0;
|
|
1056
|
+
let w1 = 0;
|
|
1057
|
+
let w2 = 0;
|
|
1058
|
+
let w3 = 0;
|
|
1059
|
+
let segment = 0;
|
|
1060
|
+
let i = 0;
|
|
1061
|
+
while (i < end) {
|
|
1062
|
+
if (host.charCodeAt(i) === 58) {
|
|
1063
|
+
// The rest of a compressed address is anchored at the last segment.
|
|
1064
|
+
i += 2;
|
|
1065
|
+
if (i === end) break;
|
|
1066
|
+
let remaining = 1;
|
|
1067
|
+
for (let j = i; j < end; j++) {
|
|
1068
|
+
if (host.charCodeAt(j) === 58) remaining++;
|
|
1069
|
+
}
|
|
1070
|
+
const dot = host.indexOf(".", i);
|
|
1071
|
+
if (dot !== -1 && dot < end) remaining++;
|
|
1072
|
+
segment = 8 - remaining;
|
|
1073
|
+
}
|
|
1074
|
+
const start = i;
|
|
1075
|
+
let value = 0;
|
|
1076
|
+
while (i < end) {
|
|
1077
|
+
const ch = host.charCodeAt(i);
|
|
1078
|
+
if (ch === 58 || ch === 46) break;
|
|
1079
|
+
value = value << 4 | (ch <= 57 ? ch - 48 : (ch & 0x5f) - 55);
|
|
1080
|
+
i++;
|
|
1081
|
+
}
|
|
1082
|
+
if (i < end && host.charCodeAt(i) === 46) {
|
|
1083
|
+
w3 = parseNativeIpv4(host, start, end);
|
|
1084
|
+
break;
|
|
1085
|
+
}
|
|
1086
|
+
// even segments fill the high half of their 32-bit word
|
|
1087
|
+
const shifted = value << (1 - (segment & 1)) * 16;
|
|
1088
|
+
switch (segment >>> 1) {
|
|
1089
|
+
case 0:
|
|
1090
|
+
w0 |= shifted;
|
|
1091
|
+
break;
|
|
1092
|
+
case 1:
|
|
1093
|
+
w1 |= shifted;
|
|
1094
|
+
break;
|
|
1095
|
+
case 2:
|
|
1096
|
+
w2 |= shifted;
|
|
1097
|
+
break;
|
|
1098
|
+
default:
|
|
1099
|
+
w3 |= shifted;
|
|
1100
|
+
}
|
|
1101
|
+
segment++;
|
|
1102
|
+
if (i < end && host.charCodeAt(i + 1) !== 58) i++;
|
|
1103
|
+
}
|
|
1104
|
+
const self = Object.create(InetV6Proto);
|
|
1105
|
+
self.address = makeIpv6(w0, w1, w2, w3);
|
|
1106
|
+
self.port = port;
|
|
1107
|
+
self.scopeId = scopeId;
|
|
1108
|
+
return Object.freeze(self);
|
|
1109
|
+
};
|
|
1110
|
+
const numericZone = /^\d+$/;
|
|
1111
|
+
const parseNativeIpv4 = (host, start, end) => {
|
|
1112
|
+
let value = 0;
|
|
1113
|
+
let octet = 0;
|
|
1114
|
+
for (let i = start; i < end; i++) {
|
|
1115
|
+
const ch = host.charCodeAt(i);
|
|
1116
|
+
if (ch === 46) {
|
|
1117
|
+
value = value << 8 | octet;
|
|
1118
|
+
octet = 0;
|
|
1119
|
+
} else {
|
|
1120
|
+
octet = octet * 10 + ch - 48;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return (value << 8 | octet) >>> 0;
|
|
1124
|
+
};
|
|
860
1125
|
/**
|
|
861
1126
|
* Parses an unbracketed numeric host and port, resolving named IPv6 zones using
|
|
862
1127
|
* a supplied map of interface names to numeric scope IDs.
|
|
@@ -889,6 +1154,29 @@ export const inetAddressFromHostString = (host, port, scopeIds) => {
|
|
|
889
1154
|
}
|
|
890
1155
|
return inetAddressFromString(host.includes(":") ? `[${host}]:${port}` : `${host}:${port}`);
|
|
891
1156
|
};
|
|
1157
|
+
/**
|
|
1158
|
+
* Returns the IPv6 scope ID of a network interface from its addresses.
|
|
1159
|
+
*
|
|
1160
|
+
* **Details**
|
|
1161
|
+
*
|
|
1162
|
+
* The first IPv6 address with a positive scope ID supplies the result. Accepts
|
|
1163
|
+
* the addresses of one interface, such as `os.networkInterfaces()[name]` or the
|
|
1164
|
+
* entries of `Deno.networkInterfaces()` with that name, without performing any
|
|
1165
|
+
* operating-system lookup itself.
|
|
1166
|
+
*
|
|
1167
|
+
* @see {@link scopeIdsFromInterfaces} for mapping every interface at once
|
|
1168
|
+
* @stability experimental
|
|
1169
|
+
* @category converting
|
|
1170
|
+
* @since 4.0.0
|
|
1171
|
+
*/
|
|
1172
|
+
export const scopeIdFromInterface = addresses => {
|
|
1173
|
+
for (const address of addresses ?? []) {
|
|
1174
|
+
if (address.family === "IPv6" && typeof address.scopeid === "number" && address.scopeid > 0) {
|
|
1175
|
+
return Option.some(address.scopeid);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return Option.none();
|
|
1179
|
+
};
|
|
892
1180
|
/**
|
|
893
1181
|
* Creates a map from interface names to IPv6 scope IDs using supplied interface
|
|
894
1182
|
* entries.
|
|
@@ -909,8 +1197,8 @@ export const inetAddressFromHostString = (host, port, scopeIds) => {
|
|
|
909
1197
|
export const scopeIdsFromInterfaces = interfaces => {
|
|
910
1198
|
const scopeIds = new Map();
|
|
911
1199
|
for (const [name, addresses] of interfaces) {
|
|
912
|
-
const
|
|
913
|
-
if (
|
|
1200
|
+
const scopeId = scopeIdFromInterface(addresses);
|
|
1201
|
+
if (Option.isSome(scopeId)) scopeIds.set(name, scopeId.value);
|
|
914
1202
|
}
|
|
915
1203
|
return scopeIds;
|
|
916
1204
|
};
|
|
@@ -976,6 +1264,40 @@ export const inetAddressFromString = input => {
|
|
|
976
1264
|
* @since 4.0.0
|
|
977
1265
|
*/
|
|
978
1266
|
export const inetAddressFromStringUnsafe = input => Result.getOrThrow(inetAddressFromString(input));
|
|
1267
|
+
/**
|
|
1268
|
+
* Converts an `InetAddressInput` to an internet address, parsing strings like
|
|
1269
|
+
* `inetAddressFromString`, converting parts like `inetAddressV4` and
|
|
1270
|
+
* `inetAddressV6`, and returning internet addresses unchanged.
|
|
1271
|
+
*
|
|
1272
|
+
* @stability unstable
|
|
1273
|
+
* @category constructors
|
|
1274
|
+
* @since 4.0.0
|
|
1275
|
+
*/
|
|
1276
|
+
export const inetAddressFromInput = input => {
|
|
1277
|
+
if (isInetAddress(input)) return Result.succeed(input);
|
|
1278
|
+
if (typeof input === "string") return inetAddressFromString(input);
|
|
1279
|
+
if (!hasProperty(input, "address") || !hasProperty(input, "port")) {
|
|
1280
|
+
return addressError(input, "expected an address and port");
|
|
1281
|
+
}
|
|
1282
|
+
const {
|
|
1283
|
+
port,
|
|
1284
|
+
scopeId
|
|
1285
|
+
} = input;
|
|
1286
|
+
return Result.flatMap(ipFromInput(input.address), address => {
|
|
1287
|
+
if (isIpv6Address(address)) return inetAddressV6(address, port, {
|
|
1288
|
+
scopeId
|
|
1289
|
+
});
|
|
1290
|
+
return (scopeId ?? 0) === 0 ? inetAddressV4(address, port) : addressError(input, "scopeId requires an IPv6 address");
|
|
1291
|
+
});
|
|
1292
|
+
};
|
|
1293
|
+
/**
|
|
1294
|
+
* Converts a trusted `InetAddressInput` to an internet address, throwing on failure.
|
|
1295
|
+
*
|
|
1296
|
+
* @stability unstable
|
|
1297
|
+
* @category unsafe
|
|
1298
|
+
* @since 4.0.0
|
|
1299
|
+
*/
|
|
1300
|
+
export const inetAddressFromInputUnsafe = input => Result.getOrThrow(inetAddressFromInput(input));
|
|
979
1301
|
/**
|
|
980
1302
|
* Formats the numeric host of an internet address without brackets or a port,
|
|
981
1303
|
* preserving a nonzero IPv6 scope ID as a `%` suffix.
|
|
@@ -1137,6 +1459,7 @@ export const formatUrlUnsafe = (self, scheme = "http") => Result.getOrThrow(form
|
|
|
1137
1459
|
*/
|
|
1138
1460
|
export const formatUrlHostString = host => host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
1139
1461
|
const UnixPathProto = {
|
|
1462
|
+
...Inspectable.BaseProto,
|
|
1140
1463
|
_tag: "UnixPathAddress",
|
|
1141
1464
|
[TypeId]: TypeId,
|
|
1142
1465
|
[Equal.symbol](that) {
|
|
@@ -1150,9 +1473,6 @@ const UnixPathProto = {
|
|
|
1150
1473
|
},
|
|
1151
1474
|
toJSON() {
|
|
1152
1475
|
return this.toString();
|
|
1153
|
-
},
|
|
1154
|
-
[NodeInspectSymbol]() {
|
|
1155
|
-
return this.toJSON();
|
|
1156
1476
|
}
|
|
1157
1477
|
};
|
|
1158
1478
|
/**
|
|
@@ -1185,24 +1505,20 @@ export const formatUnixPath = self => `unix://${self.path}`;
|
|
|
1185
1505
|
*
|
|
1186
1506
|
* **Details**
|
|
1187
1507
|
*
|
|
1188
|
-
*
|
|
1189
|
-
* literals, ports, and input shapes return a
|
|
1508
|
+
* Internet addresses are converted like `inetAddressFromInput`, without
|
|
1509
|
+
* hostname resolution. Invalid IP literals, ports, and input shapes return a
|
|
1510
|
+
* `NetAddressError`.
|
|
1190
1511
|
*
|
|
1191
1512
|
* @stability unstable
|
|
1192
1513
|
* @category constructors
|
|
1193
1514
|
* @since 4.0.0
|
|
1194
1515
|
*/
|
|
1195
1516
|
export const socketAddressFromInput = input => {
|
|
1196
|
-
if (
|
|
1197
|
-
if (typeof input === "string") return inetAddressFromString(input);
|
|
1517
|
+
if (isUnixPathAddress(input)) return Result.succeed(input);
|
|
1198
1518
|
if (hasProperty(input, "path")) {
|
|
1199
1519
|
return typeof input.path === "string" ? Result.succeed(unixPathAddress(input.path)) : addressError(input, "path must be a string");
|
|
1200
1520
|
}
|
|
1201
|
-
|
|
1202
|
-
return addressError(input, "expected an address and port or a Unix path");
|
|
1203
|
-
}
|
|
1204
|
-
const address = typeof input.address === "string" ? ipFromString(input.address) : isIpAddress(input.address) ? Result.succeed(input.address) : addressError(input, "address must be an IP address or numeric IP string");
|
|
1205
|
-
return Result.flatMap(address, address => inetAddress(address, input.port));
|
|
1521
|
+
return inetAddressFromInput(input);
|
|
1206
1522
|
};
|
|
1207
1523
|
/**
|
|
1208
1524
|
* Converts a trusted `SocketAddress.Input` to a concrete socket address,
|