@fluid-app/exigo-connection-sdk 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -13,6 +13,8 @@ pnpm add @fluid-app/exigo-connection-sdk
13
13
  # Only for apps that query the SQL replica:
14
14
  pnpm add mssql
15
15
  pnpm add -D @types/mssql
16
+ # Only for apps that reach Exigo through Fluid's egress proxy:
17
+ pnpm add undici
16
18
  ```
17
19
 
18
20
  | Import | Provides | Needs `mssql` |
@@ -114,6 +116,47 @@ The client:
114
116
  `get`, `delete` take `params`, `query`, `headers`, `timeoutMs` and `signal`;
115
117
  `post`, `put`, `patch` also take a `body`, sent as JSON.
116
118
 
119
+ ### Through Fluid's egress proxy (Mist apps)
120
+
121
+ Exigo allowlists callers by source IP, and a Mist app on Vercel has no fixed
122
+ outbound IP. Fluid's egress proxy (`services/egress-proxy`) lends it one: a
123
+ CONNECT-only forward proxy whose static IP Exigo tenants allowlist. TLS stays
124
+ end to end between the app and Exigo, so the proxy never sees the Exigo
125
+ credentials.
126
+
127
+ ```bash
128
+ pnpm add undici
129
+ ```
130
+
131
+ ```ts
132
+ const exigo = createExigoRestClient(rest, {
133
+ egressProxy: process.env.FLUID_EGRESS_PROXY_URL
134
+ ? {
135
+ url: process.env.FLUID_EGRESS_PROXY_URL,
136
+ // The install webhook's authentication_token (dit_…).
137
+ token: installation.authenticationToken,
138
+ }
139
+ : undefined,
140
+ });
141
+ ```
142
+
143
+ - Fluid sets `FLUID_EGRESS_PROXY_URL` on a droplet-linked Mist app when its
144
+ environment has a proxy. `fluid mist env pull` leaves it out on purpose: the
145
+ proxy refuses callers off Fluid's platform, so local runs call Exigo
146
+ directly, and the code above does that when the variable is unset.
147
+ - The proxy authenticates the droplet installation token, and lets through
148
+ only droplets and Exigo hosts on its own allowlists.
149
+ - The URL must be `https` (`http` only for a loopback proxy run locally),
150
+ since the CONNECT request carries the token outside the tunnel.
151
+ - A refusal throws `ExigoProxyError`, a subclass of `ExigoConnectionError`
152
+ whose `status` is the proxy's answer: 407 for a token it does not accept, 403
153
+ for a droplet or host it does not let through, 502 or 504 when it could not
154
+ reach Exigo, 503 when it could not verify the token or is at capacity.
155
+ - Clients built with the same proxy URL and token share one agent, so a
156
+ client per request still reuses open tunnels.
157
+ - REST only. The proxy does not carry the SQL replica's port, and `mssql`
158
+ cannot use a proxy.
159
+
117
160
  ## 3. SQL
118
161
 
119
162
  ```ts
@@ -179,6 +222,7 @@ Authorization header.
179
222
  | `ExigoAuthError` | REST 401/403, or a SQL login failure |
180
223
  | `ExigoTimeoutError` | a REST call, SQL connect or SQL query ran too long |
181
224
  | `ExigoConnectionError` | DNS, refused connection, TLS, network |
225
+ | `ExigoProxyError` | the egress proxy refused the tunnel (`status`) |
182
226
  | `ExigoApiError` | REST answered with an error or a body that isn't JSON |
183
227
 
184
228
  `source` is `"rest"` or `"sql"` on the auth, timeout and connection errors.
package/dist/errors.d.mts CHANGED
@@ -52,6 +52,20 @@ declare class ExigoConnectionError extends ExigoError {
52
52
  readonly source: ExigoSource;
53
53
  constructor(message: string, source: ExigoSource, options?: ExigoErrorOptions);
54
54
  }
55
+ /**
56
+ * Fluid's egress proxy refused to open a tunnel to Exigo. `status` is the
57
+ * proxy's answer to CONNECT: 407 for a token it does not accept, 403 for a
58
+ * droplet or host it does not let through, 502/504 when it could not reach
59
+ * Exigo, 503 when it could not verify the token or is at capacity.
60
+ */
61
+ declare class ExigoProxyError extends ExigoConnectionError {
62
+ name: string;
63
+ /** The proxy's HTTP status for the CONNECT request. */
64
+ readonly status: number;
65
+ constructor(message: string, source: ExigoSource, options: ExigoErrorOptions & {
66
+ readonly status: number;
67
+ });
68
+ }
55
69
  interface ExigoApiErrorDetails {
56
70
  readonly status: number;
57
71
  readonly method: string;
@@ -76,4 +90,4 @@ declare class ExigoApiError extends ExigoError {
76
90
  constructor(message: string, details: ExigoApiErrorDetails);
77
91
  }
78
92
  //#endregion
79
- export { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoSource, ExigoTimeoutError };
93
+ export { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoProxyError, ExigoSource, ExigoTimeoutError };
package/dist/errors.mjs CHANGED
@@ -49,6 +49,21 @@ var ExigoConnectionError = class extends ExigoError {
49
49
  }
50
50
  };
51
51
  /**
52
+ * Fluid's egress proxy refused to open a tunnel to Exigo. `status` is the
53
+ * proxy's answer to CONNECT: 407 for a token it does not accept, 403 for a
54
+ * droplet or host it does not let through, 502/504 when it could not reach
55
+ * Exigo, 503 when it could not verify the token or is at capacity.
56
+ */
57
+ var ExigoProxyError = class extends ExigoConnectionError {
58
+ name = "ExigoProxyError";
59
+ /** The proxy's HTTP status for the CONNECT request. */
60
+ status;
61
+ constructor(message, source, options) {
62
+ super(message, source, options);
63
+ this.status = options.status;
64
+ }
65
+ };
66
+ /**
52
67
  * The REST API answered, but not with a usable result: a non-2xx status other
53
68
  * than an auth refusal, or a success whose body is not JSON (Exigo serves an
54
69
  * HTML page for a wrong URL with a 200).
@@ -70,4 +85,4 @@ var ExigoApiError = class extends ExigoError {
70
85
  }
71
86
  };
72
87
  //#endregion
73
- export { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError };
88
+ export { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { ExigoCredentialResolver, ExigoCredentials, ExigoRestCredentials, ExigoSqlCredentials, assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials } from "./credentials.mjs";
2
- import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
3
- export { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, type ExigoCredentialResolver, type ExigoCredentials, ExigoCredentialsError, ExigoError, ExigoErrorOptions, type ExigoRestCredentials, ExigoSource, type ExigoSqlCredentials, ExigoTimeoutError, assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials };
2
+ import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoProxyError, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
3
+ export { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, type ExigoCredentialResolver, type ExigoCredentials, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoProxyError, type ExigoRestCredentials, ExigoSource, type ExigoSqlCredentials, ExigoTimeoutError, assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError } from "./errors.mjs";
1
+ import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError } from "./errors.mjs";
2
2
  import { assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials } from "./credentials.mjs";
3
- export { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError, assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials };
3
+ export { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError, assertExigoRestCredentials, assertExigoSqlCredentials, defineExigoCredentials };
package/dist/rest.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ExigoRestCredentials } from "./credentials.mjs";
2
- import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
2
+ import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoProxyError, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
3
3
 
4
4
  //#region src/rest.d.ts
5
5
  declare const EXIGO_API_VERSION = "3.0";
@@ -21,11 +21,43 @@ interface ExigoRequestOptions {
21
21
  }
22
22
  type ExigoMethodOptions = Omit<ExigoRequestOptions, "body">;
23
23
  type ExigoBodyMethodOptions = ExigoRequestOptions;
24
+ /**
25
+ * Fluid's egress proxy: a CONNECT-only forward proxy with a static outbound IP
26
+ * that Exigo tenants allowlist, for apps on hosts whose egress IPs are not
27
+ * Fluid's (Mist apps on Vercel). TLS stays end to end between the app and
28
+ * Exigo; the proxy never sees the Exigo credentials.
29
+ */
30
+ interface ExigoEgressProxy {
31
+ /**
32
+ * The proxy URL, which Fluid provides to a droplet-linked Mist app as
33
+ * `FLUID_EGRESS_PROXY_URL`. Must be https: the CONNECT request carries the
34
+ * token outside the tunnel. Plain http is accepted only for a loopback host,
35
+ * such as a proxy run locally.
36
+ */
37
+ readonly url: string;
38
+ /**
39
+ * The droplet installation token (`dit_…`, the `authentication_token` of the
40
+ * install webhook) the proxy authenticates the app with. A `Bearer ` prefix
41
+ * is optional.
42
+ */
43
+ readonly token: string;
44
+ }
24
45
  interface ExigoRestClientOptions {
25
46
  /** Per-request timeout. Defaults to {@link DEFAULT_EXIGO_TIMEOUT_MS}. */
26
47
  readonly timeoutMs?: number;
27
- /** For tests and instrumentation. Defaults to the global `fetch`. */
48
+ /**
49
+ * For tests and instrumentation. Defaults to the global `fetch`, or to
50
+ * undici's when `egressProxy` is set; a custom one then receives the proxy
51
+ * as the `dispatcher` init option.
52
+ */
28
53
  readonly fetch?: typeof fetch;
54
+ /**
55
+ * Sends every request through Fluid's egress proxy. Needs the `undici`
56
+ * package. Leave it unset to call Exigo directly, as in local development,
57
+ * where Fluid withholds the proxy URL because the proxy refuses callers off
58
+ * its own platform.
59
+ */
60
+ readonly egressProxy?: ExigoEgressProxy;
29
61
  }
30
62
  interface ExigoRestClient {
31
63
  /** The normalized base URL, including the API version. */
@@ -62,4 +94,4 @@ declare function normalizeExigoBaseUrl(baseUrl: string): string;
62
94
  */
63
95
  declare function createExigoRestClient(credentials: ExigoRestCredentials | null | undefined, options?: ExigoRestClientOptions): ExigoRestClient;
64
96
  //#endregion
65
- export { DEFAULT_EXIGO_TIMEOUT_MS, EXIGO_API_VERSION, ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoBodyMethodOptions, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoHttpMethod, ExigoMethodOptions, ExigoQueryValue, ExigoRequestOptions, ExigoRestClient, ExigoRestClientOptions, type ExigoRestCredentials, ExigoSource, ExigoTimeoutError, createExigoRestClient, normalizeExigoBaseUrl };
97
+ export { DEFAULT_EXIGO_TIMEOUT_MS, EXIGO_API_VERSION, ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoBodyMethodOptions, ExigoConnectionError, ExigoCredentialsError, ExigoEgressProxy, ExigoError, ExigoErrorOptions, ExigoHttpMethod, ExigoMethodOptions, ExigoProxyError, ExigoQueryValue, ExigoRequestOptions, ExigoRestClient, ExigoRestClientOptions, type ExigoRestCredentials, ExigoSource, ExigoTimeoutError, createExigoRestClient, normalizeExigoBaseUrl };
package/dist/rest.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError } from "./errors.mjs";
1
+ import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError } from "./errors.mjs";
2
2
  import { assertExigoRestCredentials } from "./credentials.mjs";
3
3
  //#region src/rest.ts
4
4
  /**
@@ -11,7 +11,8 @@ import { assertExigoRestCredentials } from "./credentials.mjs";
11
11
  * in each app.
12
12
  *
13
13
  * Uses the global `fetch`, so it runs on Node 20+ (Cloud Run, Vercel's Node
14
- * runtime) without Node-only APIs.
14
+ * runtime) without Node-only APIs. Routing through Fluid's egress proxy is the
15
+ * exception: it needs `undici`, loaded only when `egressProxy` is set.
15
16
  */
16
17
  const EXIGO_API_VERSION = "3.0";
17
18
  const DEFAULT_EXIGO_TIMEOUT_MS = 15e3;
@@ -136,6 +137,75 @@ function validTimeout(timeoutMs) {
136
137
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_TIMEOUT_MS) throw new TypeError(`Exigo timeoutMs must be a positive number up to ${MAX_TIMEOUT_MS}, got ${timeoutMs}.`);
137
138
  return timeoutMs;
138
139
  }
140
+ /** Same rule as the base URL: the CONNECT request carries the token in clear. */
141
+ function normalizeEgressProxyUrl(proxyUrl) {
142
+ let url;
143
+ try {
144
+ url = new URL(proxyUrl.trim());
145
+ } catch {
146
+ throw new ExigoCredentialsError("Exigo egressProxy.url is not a valid URL.", ["egressProxy.url"]);
147
+ }
148
+ const loopbackHttp = url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname);
149
+ if (url.protocol !== "https:" && !loopbackHttp) throw new ExigoCredentialsError("Exigo egressProxy.url must be an https URL; the CONNECT request carries the token.", ["egressProxy.url"]);
150
+ if (url.username || url.password) throw new ExigoCredentialsError("Exigo egressProxy.url must not carry credentials; pass the token instead.", ["egressProxy.url"]);
151
+ return url.origin;
152
+ }
153
+ function normalizeEgressProxyToken(token) {
154
+ const bare = token.replace(/^\s*Bearer(?:\s+|$)/i, "").trim();
155
+ if (bare === "" || /\s/.test(bare)) throw new ExigoCredentialsError("Exigo egressProxy.token must be the droplet installation token (dit_…).", ["egressProxy.token"]);
156
+ return bare;
157
+ }
158
+ /**
159
+ * One proxy agent per proxy URL and token, shared by every client that uses
160
+ * them, so a droplet building a client per request still reuses its tunnels.
161
+ */
162
+ const proxyTransports = /* @__PURE__ */ new Map();
163
+ async function loadUndici() {
164
+ try {
165
+ return await import("undici");
166
+ } catch (error) {
167
+ throw new ExigoError("Routing Exigo calls through egressProxy needs the undici package. Install it next to @fluid-app/exigo-connection-sdk.", { cause: error });
168
+ }
169
+ }
170
+ function proxyTransport(proxyUrl, token) {
171
+ const key = `${proxyUrl}\n${token}`;
172
+ let transport = proxyTransports.get(key);
173
+ if (!transport) {
174
+ transport = loadUndici().then((undici) => ({
175
+ fetch: undici.fetch,
176
+ dispatcher: new undici.ProxyAgent({
177
+ uri: proxyUrl,
178
+ token: `Bearer ${token}`
179
+ })
180
+ }));
181
+ transport.catch(() => proxyTransports.delete(key));
182
+ proxyTransports.set(key, transport);
183
+ }
184
+ return transport;
185
+ }
186
+ /** undici reports a refused CONNECT as `Proxy response (407) !== 200 ...`. */
187
+ function proxyRefusalStatus(error) {
188
+ const seen = /* @__PURE__ */ new Set();
189
+ let current = error;
190
+ while (current instanceof Error && !seen.has(current)) {
191
+ seen.add(current);
192
+ const match = /Proxy response \((\d{3})\)/.exec(current.message);
193
+ if (match) return Number(match[1]);
194
+ current = current.cause;
195
+ }
196
+ return null;
197
+ }
198
+ function describeProxyRefusal(status, host, proxyHost) {
199
+ const prefix = `Fluid's egress proxy at ${proxyHost} refused the tunnel to ${host} (HTTP ${status})`;
200
+ switch (status) {
201
+ case 407: return `${prefix}: it did not accept the token. Pass the droplet installation token (dit_…) as egressProxy.token.`;
202
+ case 403: return `${prefix}: this droplet may not egress through it, or ${host} is not on its allowlist.`;
203
+ case 502: return `${prefix}: it could not reach Exigo.`;
204
+ case 503: return `${prefix}: it could not verify the token with Fluid or is at capacity. Retry.`;
205
+ case 504: return `${prefix}: its connection to Exigo timed out. Retry.`;
206
+ default: return `${prefix}.`;
207
+ }
208
+ }
139
209
  /**
140
210
  * Creates a client for one set of REST credentials.
141
211
  *
@@ -149,9 +219,26 @@ function createExigoRestClient(credentials, options = {}) {
149
219
  const baseUrl = normalizeExigoBaseUrl(credentials.baseUrl);
150
220
  const host = new URL(baseUrl).host;
151
221
  const authorization = authorizationHeader(credentials);
152
- const secrets = [credentials.password, authorization.replace(/^Basic /, "")];
222
+ const egressProxy = options.egressProxy ? {
223
+ url: normalizeEgressProxyUrl(options.egressProxy.url),
224
+ token: normalizeEgressProxyToken(options.egressProxy.token)
225
+ } : null;
226
+ const proxyHost = egressProxy ? new URL(egressProxy.url).host : null;
227
+ const secrets = [
228
+ credentials.password,
229
+ authorization.replace(/^Basic /, ""),
230
+ ...egressProxy ? [egressProxy.token] : []
231
+ ];
153
232
  const defaultTimeout = validTimeout(options.timeoutMs ?? 15e3);
154
- const fetchImpl = options.fetch ?? globalThis.fetch;
233
+ async function send(url, init) {
234
+ if (!egressProxy) return (options.fetch ?? globalThis.fetch)(url, init);
235
+ const transport = await proxyTransport(egressProxy.url, egressProxy.token);
236
+ const proxiedInit = {
237
+ ...init,
238
+ dispatcher: transport.dispatcher
239
+ };
240
+ return (options.fetch ?? transport.fetch)(url, proxiedInit);
241
+ }
155
242
  async function request(method, path, requestOptions = {}) {
156
243
  const relative = expandPath(path, requestOptions.params);
157
244
  const url = new URL(`${baseUrl}${relative}`);
@@ -178,7 +265,7 @@ function createExigoRestClient(credentials, options = {}) {
178
265
  let response;
179
266
  let text;
180
267
  try {
181
- response = await fetchImpl(url, {
268
+ response = await send(url, {
182
269
  method,
183
270
  headers,
184
271
  body,
@@ -191,7 +278,15 @@ function createExigoRestClient(credentials, options = {}) {
191
278
  timeoutMs
192
279
  });
193
280
  if (callerSignal?.aborted) throw callerSignal.reason;
194
- throw new ExigoConnectionError(`Could not reach Exigo at ${host}: ${describeNetworkFailure(error)}`, "rest", { cause: error });
281
+ if (error instanceof ExigoError) throw error;
282
+ if (proxyHost) {
283
+ const status = proxyRefusalStatus(error);
284
+ if (status !== null) throw new ExigoProxyError(describeProxyRefusal(status, host, proxyHost), "rest", {
285
+ cause: error,
286
+ status
287
+ });
288
+ }
289
+ throw new ExigoConnectionError(`Could not reach Exigo at ${host}${proxyHost ? ` through the egress proxy at ${proxyHost}` : ""}: ${redact(describeNetworkFailure(error), secrets)}`, "rest", { cause: error });
195
290
  } finally {
196
291
  clearTimeout(timer);
197
292
  callerSignal?.removeEventListener("abort", onCallerAbort);
@@ -228,4 +323,4 @@ function createExigoRestClient(credentials, options = {}) {
228
323
  };
229
324
  }
230
325
  //#endregion
231
- export { DEFAULT_EXIGO_TIMEOUT_MS, EXIGO_API_VERSION, ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError, createExigoRestClient, normalizeExigoBaseUrl };
326
+ export { DEFAULT_EXIGO_TIMEOUT_MS, EXIGO_API_VERSION, ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError, createExigoRestClient, normalizeExigoBaseUrl };
package/dist/sql.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ExigoSqlCredentials } from "./credentials.mjs";
2
- import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
2
+ import { ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoProxyError, ExigoSource, ExigoTimeoutError } from "./errors.mjs";
3
3
  import { ConnectionPool, ConnectionPool as ConnectionPool$1 } from "mssql";
4
4
 
5
5
  //#region src/sql.d.ts
@@ -50,4 +50,4 @@ declare function closeExigoPool(credentials: Pick<ExigoSqlCredentials, "host" |
50
50
  /** Closes every pool this package opened; for shutdown hooks and tests. */
51
51
  declare function closeAllExigoPools(): Promise<void>;
52
52
  //#endregion
53
- export { type ConnectionPool, EXIGO_SQL_DEFAULTS, ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoPoolOptions, ExigoSource, type ExigoSqlCredentials, ExigoTimeoutError, closeAllExigoPools, closeExigoPool, getExigoPool, translateExigoSqlError };
53
+ export { type ConnectionPool, EXIGO_SQL_DEFAULTS, ExigoApiError, ExigoApiErrorDetails, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoErrorOptions, ExigoPoolOptions, ExigoProxyError, ExigoSource, type ExigoSqlCredentials, ExigoTimeoutError, closeAllExigoPools, closeExigoPool, getExigoPool, translateExigoSqlError };
package/dist/sql.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError } from "./errors.mjs";
1
+ import { ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError } from "./errors.mjs";
2
2
  import { assertExigoSqlCredentials } from "./credentials.mjs";
3
3
  import { createHash } from "node:crypto";
4
4
  //#region src/sql.ts
@@ -292,4 +292,4 @@ async function closeEntry(entry) {
292
292
  await pool.close();
293
293
  }
294
294
  //#endregion
295
- export { EXIGO_SQL_DEFAULTS, ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoTimeoutError, closeAllExigoPools, closeExigoPool, getExigoPool, translateExigoSqlError };
295
+ export { EXIGO_SQL_DEFAULTS, ExigoApiError, ExigoAuthError, ExigoConnectionError, ExigoCredentialsError, ExigoError, ExigoProxyError, ExigoTimeoutError, closeAllExigoPools, closeExigoPool, getExigoPool, translateExigoSqlError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/exigo-connection-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Exigo REST client, SQL pool and credential interface for Fluid droplets and Mist apps",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -41,11 +41,13 @@
41
41
  "mssql": "^12.7.2",
42
42
  "tsdown": "^0.21.0",
43
43
  "typescript": "^5",
44
+ "undici": "^7.28.0",
44
45
  "vitest": "^4.0.18"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "@types/mssql": ">=9",
48
- "mssql": ">=11 <13"
49
+ "mssql": ">=11 <13",
50
+ "undici": ">=6 <8"
49
51
  },
50
52
  "peerDependenciesMeta": {
51
53
  "@types/mssql": {
@@ -53,6 +55,9 @@
53
55
  },
54
56
  "mssql": {
55
57
  "optional": true
58
+ },
59
+ "undici": {
60
+ "optional": true
56
61
  }
57
62
  },
58
63
  "scripts": {