@apifuse/provider-sdk 2.2.0-beta.15 → 2.2.0-beta.17
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/AUTHORING.md +92 -13
- package/CHANGELOG.md +10 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +59 -28
- package/dist/define.js +20 -1
- package/dist/error-resolution.d.ts +2 -0
- package/dist/error-resolution.js +90 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/native-egress-policy.d.ts +1 -0
- package/dist/native-egress-policy.js +34 -21
- package/dist/native-ipv4.d.ts +22 -0
- package/dist/native-ipv4.js +98 -0
- package/dist/provider.d.ts +2 -2
- package/dist/provider.js +1 -1
- package/dist/runtime/native-network.d.ts +43 -7
- package/dist/runtime/native-network.js +567 -110
- package/dist/runtime/proxy-nodemaven.d.ts +7 -0
- package/dist/runtime/proxy-nodemaven.js +5 -5
- package/dist/server/serve.js +76 -100
- package/dist/types.d.ts +9 -2
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/config/loader.ts +110 -18
- package/src/define.ts +33 -0
- package/src/error-resolution.ts +91 -0
- package/src/index.ts +6 -0
- package/src/native-egress-policy.ts +39 -33
- package/src/native-ipv4.ts +118 -0
- package/src/provider.ts +6 -0
- package/src/runtime/native-network.ts +734 -131
- package/src/runtime/proxy-nodemaven.ts +13 -5
- package/src/server/serve.ts +118 -98
- package/src/types.ts +11 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { domainToASCII } from "node:url";
|
|
2
|
+
|
|
3
|
+
const STRICT_IPV4_PATTERN =
|
|
4
|
+
/^(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})$/;
|
|
5
|
+
const DECIMAL_COMPONENT_PATTERN = /^\d+$/;
|
|
6
|
+
const HEX_COMPONENT_PATTERN = /^0[xX][\da-fA-F]+$/;
|
|
7
|
+
const FORMAT_CONTROL_PATTERN = /\p{Cf}/u;
|
|
8
|
+
const RESERVED_EGRESS_HOST_DELIMITERS = ["/", "\\", "?", "#", "@", "[", "]", " ", "%"];
|
|
9
|
+
|
|
10
|
+
export type EgressHostCanonicalizationFailure =
|
|
11
|
+
| "not-string"
|
|
12
|
+
| "reserved-delimiter"
|
|
13
|
+
| "control-character"
|
|
14
|
+
| "whitespace"
|
|
15
|
+
| "canonicalization-empty";
|
|
16
|
+
|
|
17
|
+
export type EgressHostCanonicalizationResult =
|
|
18
|
+
| { readonly ok: true; readonly host: string }
|
|
19
|
+
| { readonly ok: false; readonly reason: EgressHostCanonicalizationFailure };
|
|
20
|
+
|
|
21
|
+
export function parseStrictIpv4(value: string): number | undefined {
|
|
22
|
+
const match = STRICT_IPV4_PATTERN.exec(value);
|
|
23
|
+
if (!match || match[0] !== value) return undefined;
|
|
24
|
+
const [, first, second, third, fourth] = match;
|
|
25
|
+
if (first === undefined || second === undefined || third === undefined || fourth === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
const octets = [Number(first), Number(second), Number(third), Number(fourth)];
|
|
28
|
+
if (octets.some((octet) => octet > 255)) return undefined;
|
|
29
|
+
const [a, b, c, d] = octets;
|
|
30
|
+
if (a === undefined || b === undefined || c === undefined || d === undefined) return undefined;
|
|
31
|
+
return (a * 0x1000000 + b * 0x10000 + c * 0x100 + d) >>> 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function classifyEgressTargetHost(host: string): "ipv4" | "numeric-ambiguous" | "dns" {
|
|
35
|
+
if (parseStrictIpv4(host) !== undefined) return "ipv4";
|
|
36
|
+
if (host.includes(":")) return "numeric-ambiguous";
|
|
37
|
+
const labels = host.split(".");
|
|
38
|
+
if (
|
|
39
|
+
labels.every(
|
|
40
|
+
(label) =>
|
|
41
|
+
DECIMAL_COMPONENT_PATTERN.exec(label)?.[0] === label ||
|
|
42
|
+
HEX_COMPONENT_PATTERN.exec(label)?.[0] === label,
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
return "numeric-ambiguous";
|
|
46
|
+
return "dns";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function hasReservedEgressHostDelimiter(value: string): boolean {
|
|
50
|
+
return RESERVED_EGRESS_HOST_DELIMITERS.some((delimiter) => value.includes(delimiter));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function hasEgressHostControlCharacter(value: string): boolean {
|
|
54
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
55
|
+
const code = value.charCodeAt(index);
|
|
56
|
+
if (code <= 31 || code === 127) return true;
|
|
57
|
+
}
|
|
58
|
+
return FORMAT_CONTROL_PATTERN.test(value);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function canonicalizeEgressHost(value: unknown): EgressHostCanonicalizationResult {
|
|
62
|
+
if (typeof value !== "string") return { ok: false, reason: "not-string" };
|
|
63
|
+
if (hasReservedEgressHostDelimiter(value)) return { ok: false, reason: "reserved-delimiter" };
|
|
64
|
+
if (hasEgressHostControlCharacter(value)) return { ok: false, reason: "control-character" };
|
|
65
|
+
if (/\s/u.test(value)) return { ok: false, reason: "whitespace" };
|
|
66
|
+
const raw = value.trim();
|
|
67
|
+
if (!raw) return { ok: false, reason: "canonicalization-empty" };
|
|
68
|
+
|
|
69
|
+
// Classify the spelling with one optional root-label dot removed before IDNA.
|
|
70
|
+
// This keeps resolver-numeric ASCII forms from being widened into canonical IPv4.
|
|
71
|
+
const numericCandidate = raw.endsWith(".") ? raw.slice(0, -1) : raw;
|
|
72
|
+
const normalizedNumericCandidate = numericCandidate.toLowerCase();
|
|
73
|
+
if (classifyEgressTargetHost(normalizedNumericCandidate) === "numeric-ambiguous")
|
|
74
|
+
return { ok: true, host: normalizedNumericCandidate };
|
|
75
|
+
|
|
76
|
+
let ascii: string;
|
|
77
|
+
try {
|
|
78
|
+
ascii = domainToASCII(raw).toLowerCase().replace(/\.$/, "");
|
|
79
|
+
} catch {
|
|
80
|
+
return { ok: false, reason: "canonicalization-empty" };
|
|
81
|
+
}
|
|
82
|
+
if (!ascii || /^\.+$/.test(ascii)) return { ok: false, reason: "canonicalization-empty" };
|
|
83
|
+
return { ok: true, host: ascii };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function parseIpv4Cidr(
|
|
87
|
+
value: string,
|
|
88
|
+
):
|
|
89
|
+
| { readonly ok: true; readonly network: number; readonly prefix: number }
|
|
90
|
+
| { readonly ok: false; readonly reason: "malformed" | "non-canonical-network" } {
|
|
91
|
+
const separator = value.indexOf("/");
|
|
92
|
+
if (separator <= 0 || separator !== value.lastIndexOf("/"))
|
|
93
|
+
return { ok: false, reason: "malformed" };
|
|
94
|
+
const address = parseStrictIpv4(value.slice(0, separator));
|
|
95
|
+
const prefixText = value.slice(separator + 1);
|
|
96
|
+
const prefix = Number(prefixText);
|
|
97
|
+
if (
|
|
98
|
+
address === undefined ||
|
|
99
|
+
!Number.isInteger(prefix) ||
|
|
100
|
+
prefix < 0 ||
|
|
101
|
+
prefix > 32 ||
|
|
102
|
+
String(prefix) !== prefixText
|
|
103
|
+
)
|
|
104
|
+
return { ok: false, reason: "malformed" };
|
|
105
|
+
const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
|
|
106
|
+
const network = (address & mask) >>> 0;
|
|
107
|
+
if (address !== network) return { ok: false, reason: "non-canonical-network" };
|
|
108
|
+
return { ok: true, network, prefix };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function ipv4InCidr(address: number, cidr: string): boolean {
|
|
112
|
+
const parsed = parseIpv4Cidr(cidr);
|
|
113
|
+
if (!parsed.ok) return false;
|
|
114
|
+
return (
|
|
115
|
+
parsed.prefix === 0 ||
|
|
116
|
+
address >>> (32 - parsed.prefix) === parsed.network >>> (32 - parsed.prefix)
|
|
117
|
+
);
|
|
118
|
+
}
|
package/src/provider.ts
CHANGED
|
@@ -123,6 +123,7 @@ export type {
|
|
|
123
123
|
OperationDefinition,
|
|
124
124
|
OperationDocMeta,
|
|
125
125
|
OperationErrorCode,
|
|
126
|
+
ProviderErrorStatus,
|
|
126
127
|
OperationInputExample,
|
|
127
128
|
OperationLifecycle,
|
|
128
129
|
OperationObservabilityConfig,
|
|
@@ -165,6 +166,7 @@ export type {
|
|
|
165
166
|
} from "./types.js";
|
|
166
167
|
export {
|
|
167
168
|
createNativeNetworkClient,
|
|
169
|
+
createEnvVendorCredentialResolver,
|
|
168
170
|
deriveNativeCredentialAffinityKey,
|
|
169
171
|
NativeEgressGrantExpiredError,
|
|
170
172
|
NativeEgressNotDeclaredError,
|
|
@@ -174,10 +176,14 @@ export {
|
|
|
174
176
|
resolveNativeGatewayProxy,
|
|
175
177
|
type NativeGatewayProxy,
|
|
176
178
|
type NativeGatewayProxyResolutionInput,
|
|
179
|
+
type NativeGatewayProxySkipReason,
|
|
177
180
|
type NativeGatewayProxySynthesizer,
|
|
181
|
+
type NativeGatewayProxySynthesisResult,
|
|
178
182
|
type NativeGatewayProxySynthesisInput,
|
|
179
183
|
type NativeNetworkClientOptions,
|
|
180
184
|
type NativeNetworkErrorCode,
|
|
185
|
+
type VendorCredentialLookup,
|
|
186
|
+
type VendorCredentialResolver,
|
|
181
187
|
} from "./runtime/native-network.js";
|
|
182
188
|
export {
|
|
183
189
|
HttpRetryAfterPolicy,
|