@juspay/neurolink 12.49.2 → 12.49.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.
@@ -4,14 +4,19 @@
4
4
  * Supports comprehensive NO_PROXY pattern matching including wildcards, domains, ports, and CIDR
5
5
  */
6
6
  /**
7
- * Comprehensive NO_PROXY bypass check supporting multiple pattern types
7
+ * NO_PROXY bypass check. The value is a comma- or space-separated list; each
8
+ * entry is matched case-insensitively.
8
9
  *
9
- * Supported patterns:
10
+ * Supported entries:
10
11
  * - "*" - bypass all requests
11
- * - "example.com" - exact hostname match
12
- * - ".example.com" - domain suffix match (matches example.com and subdomains)
13
- * - "localhost:8080" - hostname with specific port
14
- * - "192.168.1.0/24" - CIDR notation for IP ranges
12
+ * - "example.com", ".example.com", "*.example.com" - the host and any subdomain
13
+ * - "example.com:8443" - the same, on that port only; a URL without a port is
14
+ * on the scheme's default (80 for http, 443 for https)
15
+ * - "example.com." - the same as "example.com": one trailing dot is ignored on
16
+ * an entry and on the URL's host name, so "https://api.example.com./" matches
17
+ * - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
18
+ * - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
19
+ * ranges are not supported)
15
20
  *
16
21
  * @param targetUrl - The URL to check for proxy bypass
17
22
  * @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
@@ -27,15 +27,124 @@ function isIpInCIDR(ip, cidr) {
27
27
  return false;
28
28
  }
29
29
  }
30
+ const IPV4_LITERAL = /^\d{1,3}(\.\d{1,3}){3}$/;
30
31
  /**
31
- * Comprehensive NO_PROXY bypass check supporting multiple pattern types
32
+ * The form a URL gives an IPv6 literal (`[::1]`, lower-case, compressed), so
33
+ * `[0:0:0:0:0:0:0:1]` and `[::1]` compare equal. `null` when it is not one.
34
+ */
35
+ function canonicalIpv6Host(address) {
36
+ try {
37
+ return new URL(`http://[${address}]`).hostname;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /** A fully qualified name's trailing dot, which a URL keeps and curl ignores. */
44
+ function withoutTrailingDot(name) {
45
+ return name.endsWith(".") ? name.slice(0, -1) : name;
46
+ }
47
+ /**
48
+ * curl's rules for one list entry: an optional leading `.` or `*.` is ignored;
49
+ * the entry names that host and every subdomain of it, an IP literal only
50
+ * itself; and a `:port` restricts it to that port. IPv6 is written bare (`::1`)
51
+ * or bracketed (`[::1]:8080`), and only the bracketed form can carry a port.
52
+ * One trailing dot is ignored on the entry's domain and on the URL's host name,
53
+ * so `example.com.` and `example.com` name the same host; an entry made only of
54
+ * dots names none.
55
+ */
56
+ function matchesNoProxyEntry(entry, hostname, port) {
57
+ let host = entry;
58
+ let entryPort;
59
+ if (entry.startsWith("[")) {
60
+ const close = entry.indexOf("]");
61
+ if (close === -1) {
62
+ return false;
63
+ }
64
+ host = entry.slice(0, close + 1);
65
+ const rest = entry.slice(close + 1);
66
+ if (rest !== "") {
67
+ if (!/^:\d+$/.test(rest)) {
68
+ return false;
69
+ }
70
+ entryPort = rest.slice(1);
71
+ }
72
+ }
73
+ else {
74
+ const colons = entry.split(":").length - 1;
75
+ if (colons === 1) {
76
+ const separator = entry.indexOf(":");
77
+ host = entry.slice(0, separator);
78
+ entryPort = entry.slice(separator + 1);
79
+ if (!/^\d+$/.test(entryPort)) {
80
+ return false;
81
+ }
82
+ }
83
+ else if (colons > 1) {
84
+ host = `[${entry}]`;
85
+ }
86
+ }
87
+ if (entryPort !== undefined && entryPort !== port) {
88
+ return false;
89
+ }
90
+ if (host.startsWith("[")) {
91
+ return canonicalIpv6Host(host.slice(1, -1)) === hostname;
92
+ }
93
+ host = host.replace(/^(\*\.|\.)/, "");
94
+ if (/^\.*$/.test(host) || /[\s*/]/.test(host)) {
95
+ return false;
96
+ }
97
+ if (IPV4_LITERAL.test(host)) {
98
+ return hostname === host;
99
+ }
100
+ const domain = withoutTrailingDot(host);
101
+ // curl does not take "127.0.0.1." for an address, so it names nothing.
102
+ if (IPV4_LITERAL.test(domain)) {
103
+ return false;
104
+ }
105
+ const name = withoutTrailingDot(hostname);
106
+ return name === domain || name.endsWith(`.${domain}`);
107
+ }
108
+ /**
109
+ * The rules this function applied before it followed curl, unchanged and still
110
+ * consulted, so that a configuration that bypassed the proxy through them keeps
111
+ * doing so. That includes where they are looser than curl (`.example.com` also
112
+ * matches `notexample.com`) and an IPv4 CIDR range such as `192.168.1.0/24`,
113
+ * which curl-style entries do not express.
114
+ */
115
+ function matchesLegacyNoProxyEntry(lowerPattern, hostname, port) {
116
+ // Domain suffix match (.example.com)
117
+ if (lowerPattern.startsWith(".")) {
118
+ const suffix = lowerPattern.slice(1);
119
+ return hostname.endsWith(suffix) || hostname === suffix;
120
+ }
121
+ // Port-specific match (hostname:port)
122
+ if (lowerPattern.includes(":")) {
123
+ const [patternHost, patternPort] = lowerPattern.split(":");
124
+ return hostname === patternHost && port === patternPort;
125
+ }
126
+ // CIDR notation (192.168.1.0/24) - only for IP addresses
127
+ if (lowerPattern.includes("/")) {
128
+ // Only apply CIDR when target is an IP literal
129
+ return IPV4_LITERAL.test(hostname) && isIpInCIDR(hostname, lowerPattern);
130
+ }
131
+ // Exact hostname match
132
+ return hostname === lowerPattern;
133
+ }
134
+ /**
135
+ * NO_PROXY bypass check. The value is a comma- or space-separated list; each
136
+ * entry is matched case-insensitively.
32
137
  *
33
- * Supported patterns:
138
+ * Supported entries:
34
139
  * - "*" - bypass all requests
35
- * - "example.com" - exact hostname match
36
- * - ".example.com" - domain suffix match (matches example.com and subdomains)
37
- * - "localhost:8080" - hostname with specific port
38
- * - "192.168.1.0/24" - CIDR notation for IP ranges
140
+ * - "example.com", ".example.com", "*.example.com" - the host and any subdomain
141
+ * - "example.com:8443" - the same, on that port only; a URL without a port is
142
+ * on the scheme's default (80 for http, 443 for https)
143
+ * - "example.com." - the same as "example.com": one trailing dot is ignored on
144
+ * an entry and on the URL's host name, so "https://api.example.com./" matches
145
+ * - "192.168.1.10", "::1", "[::1]:8080" - an IP literal, exactly
146
+ * - "192.168.1.0/24" - an IPv4 CIDR range, for IPv4 literal targets (IPv6 CIDR
147
+ * ranges are not supported)
39
148
  *
40
149
  * @param targetUrl - The URL to check for proxy bypass
41
150
  * @param noProxyEnv - Optional NO_PROXY environment variable value (if not provided, reads from process.env)
@@ -51,7 +160,7 @@ export function shouldBypassProxy(targetUrl, noProxyEnv) {
51
160
  const hostname = url.hostname.toLowerCase();
52
161
  const port = url.port || (url.protocol === "https:" ? "443" : "80");
53
162
  const patterns = noProxy
54
- .split(",")
163
+ .split(/[,\s]+/)
55
164
  .map((p) => p.trim())
56
165
  .filter(Boolean);
57
166
  for (const pattern of patterns) {
@@ -60,30 +169,8 @@ export function shouldBypassProxy(targetUrl, noProxyEnv) {
60
169
  if (lowerPattern === "*") {
61
170
  return true;
62
171
  }
63
- // Domain suffix match (.example.com)
64
- if (lowerPattern.startsWith(".")) {
65
- const suffix = lowerPattern.slice(1);
66
- if (hostname.endsWith(suffix) || hostname === suffix) {
67
- return true;
68
- }
69
- }
70
- // Port-specific match (hostname:port)
71
- else if (lowerPattern.includes(":")) {
72
- const [patternHost, patternPort] = lowerPattern.split(":");
73
- if (hostname === patternHost && port === patternPort) {
74
- return true;
75
- }
76
- }
77
- // CIDR notation (192.168.1.0/24) - only for IP addresses
78
- else if (lowerPattern.includes("/")) {
79
- // Only apply CIDR when target is an IP literal
80
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname) &&
81
- isIpInCIDR(hostname, lowerPattern)) {
82
- return true;
83
- }
84
- }
85
- // Exact hostname match
86
- else if (hostname === lowerPattern) {
172
+ if (matchesNoProxyEntry(lowerPattern, hostname, port) ||
173
+ matchesLegacyNoProxyEntry(lowerPattern, hostname, port)) {
87
174
  return true;
88
175
  }
89
176
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.49.2",
3
+ "version": "12.49.3",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
6
6
  "author": {