@compforge/harness-toolbox 0.5.0 → 0.5.1

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
@@ -5,7 +5,7 @@ Client, ClientProvider, DataSource, EnvironmentContext and ClientManager are own
5
5
  its lifecycle entrypoints re-export the same common symbols.
6
6
 
7
7
  Shared infrastructure for diagnostic tools, test runners and business adapters. Use the same
8
- clients to access Kubernetes, MySQL, Redis, OpenSearch and S3-compatible object storage without depending on a particular
8
+ clients to access HTTP(S), Kubernetes, MySQL, Redis, OpenSearch and S3-compatible object storage without depending on a particular
9
9
  command, plugin protocol, test model or verdict.
10
10
 
11
11
  The package supports Node.js 22+ and Bun. Install with `npm install @compforge/harness-toolbox`.
@@ -16,6 +16,31 @@ claiming snapshot consistency; callers supply cancellation and decide how to per
16
16
  Protocol adapters have separate entry points; importing lifecycle or transport contracts does
17
17
  not load database or Kubernetes drivers.
18
18
 
19
+ ## HTTP requests
20
+
21
+ `HttpClient` borrows the same `Transport` as other protocol clients, keeping the logical Host and
22
+ TLS identity even when the socket goes through a port-forward. Limits include the response body;
23
+ statuses and redirects are returned without retries or redirect following.
24
+
25
+ ```ts
26
+ import { ClientManager } from "@compforge/harness-common";
27
+ import { HttpClient } from "@compforge/harness-toolbox/http";
28
+ import { DirectTransport } from "@compforge/harness-toolbox/transport";
29
+
30
+ const clients = new ClientManager();
31
+ try {
32
+ const route = await clients.get({ clientKey: "direct", createClient: () => new DirectTransport() });
33
+ const http = await clients.create({ createClient: (_clients, signal) => new HttpClient(
34
+ { endpoint: "https://service.example" }, route,
35
+ { concurrency: 4, connectTimeoutMs: 5000, requestTimeoutMs: 10000, maxResponseBytes: 1024 * 1024 },
36
+ { signal },
37
+ ) });
38
+ const response = await http.request("/health");
39
+ console.log(response.status, new TextDecoder().decode(response.body));
40
+ await http.dispose(); // The shared route remains available until root disposal.
41
+ } finally { await clients.dispose(); }
42
+ ```
43
+
19
44
  ## File sources
20
45
 
21
46
  A FileDataSource is a caller-declared acquisition group. Use `LocalFileDataSource` for local paths
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-z5pm2emz.js";
4
4
  import {
5
5
  S3Client
6
- } from "./chunk-7hbvjzb9.js";
6
+ } from "./chunk-7m95c7pn.js";
7
7
  import {
8
8
  DirectTransport
9
9
  } from "./chunk-18gcp0ck.js";
@@ -0,0 +1,142 @@
1
+ import {
2
+ isConnectionNetworkError
3
+ } from "./chunk-18gcp0ck.js";
4
+ import {
5
+ ConcurrencyPool
6
+ } from "./chunk-v3hxvnrc.js";
7
+ import {
8
+ httpHandler
9
+ } from "./chunk-c2b2jwm4.js";
10
+ import {
11
+ TimeoutError,
12
+ ToolboxError
13
+ } from "./chunk-rkt41za2.js";
14
+
15
+ // src/http/client.ts
16
+ import { HttpRequest } from "@smithy/core/protocols";
17
+ import { Readable } from "node:stream";
18
+ import { raceSignal } from "race-signal";
19
+ class HttpClient {
20
+ transport;
21
+ lifecycle;
22
+ #controller = new AbortController;
23
+ signal;
24
+ #endpoint;
25
+ #target;
26
+ #limits;
27
+ #pool;
28
+ #operations = new Set;
29
+ #initialization;
30
+ #disposal;
31
+ #handler;
32
+ constructor(target, transport, limits, lifecycle = {}) {
33
+ this.transport = transport;
34
+ this.lifecycle = lifecycle;
35
+ for (const name of ["concurrency", "connectTimeoutMs", "requestTimeoutMs", "maxResponseBytes"]) {
36
+ const value = limits[name];
37
+ if (!Number.isSafeInteger(value) || value < 1 || name.endsWith("Ms") && value > 2147483647) {
38
+ throw new Error(`${name} must be a positive integer within its supported range`);
39
+ }
40
+ }
41
+ this.#endpoint = new URL(target.endpoint);
42
+ if (!["http:", "https:"].includes(this.#endpoint.protocol) || this.#endpoint.username || this.#endpoint.password || this.#endpoint.search || this.#endpoint.hash)
43
+ throw new Error("HTTP endpoint requires HTTP(S), without credentials, query or fragment");
44
+ this.#target = { ...target };
45
+ this.#limits = { ...limits };
46
+ this.#pool = new ConcurrencyPool(limits.concurrency);
47
+ this.signal = AbortSignal.any([this.#controller.signal, transport.signal, ...lifecycle.signal ? [lifecycle.signal] : []]);
48
+ }
49
+ initialize() {
50
+ this.signal.throwIfAborted();
51
+ return this.#initialization ??= (async () => {
52
+ const endpoint = this.#endpoint;
53
+ const route = await this.transport.acquire({
54
+ name: "HTTP route",
55
+ signal: this.signal,
56
+ connectTimeoutMs: this.#limits.connectTimeoutMs,
57
+ onRoute: this.lifecycle.onRoute,
58
+ open: async (path, attempt) => {
59
+ if (path.kind !== "tcp")
60
+ throw new Error("HTTP requires a TCP transport");
61
+ return { connection: await path.connect({
62
+ host: endpoint.hostname.replace(/^\[|\]$/g, ""),
63
+ port: Number(endpoint.port || (endpoint.protocol === "https:" ? 443 : 80))
64
+ }, attempt), transport: path.name };
65
+ },
66
+ close: () => {},
67
+ retryReason: (error) => isConnectionNetworkError(error) ? String(error.code) : undefined
68
+ });
69
+ this.signal.throwIfAborted();
70
+ this.#handler = httpHandler(this.#target, route, this.#limits);
71
+ })();
72
+ }
73
+ request(path, options = {}) {
74
+ this.signal.throwIfAborted();
75
+ const url = new URL(path, this.#endpoint);
76
+ if (url.origin !== this.#endpoint.origin || url.username || url.password || url.hash) {
77
+ throw new Error("HTTP request must retain the configured origin and contain no credentials or fragment");
78
+ }
79
+ const headers = {};
80
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
81
+ if (name.toLowerCase() === "host")
82
+ throw new Error("HTTP Host is owned by the configured endpoint");
83
+ headers[name.toLowerCase()] = value;
84
+ }
85
+ headers.host = url.host;
86
+ const timeout = new AbortController;
87
+ const timer = setTimeout(() => timeout.abort(new TimeoutError(`HTTP request timed out after ${this.#limits.requestTimeoutMs}ms`)), this.#limits.requestTimeoutMs);
88
+ timer.unref();
89
+ const signal = AbortSignal.any([this.signal, timeout.signal, ...options.signal ? [options.signal] : []]);
90
+ const pending = this.#pool.run(async () => {
91
+ await raceSignal(this.initialize(), signal);
92
+ signal.throwIfAborted();
93
+ const { response } = await this.#handler.handle(new HttpRequest({
94
+ protocol: url.protocol,
95
+ hostname: url.hostname,
96
+ port: Number(url.port || (url.protocol === "https:" ? 443 : 80)),
97
+ method: options.method ?? "GET",
98
+ path: url.pathname + url.search,
99
+ headers,
100
+ body: options.body
101
+ }), { abortSignal: signal });
102
+ const body = response.body;
103
+ if (!(body instanceof Readable))
104
+ throw new ToolboxError("HTTP response has no readable body", { kind: "invalid_response" });
105
+ const abort = () => body.destroy(new Error("HTTP body read cancelled", { cause: signal.reason }));
106
+ signal.addEventListener("abort", abort, { once: true });
107
+ try {
108
+ signal.throwIfAborted();
109
+ const chunks = [];
110
+ let size = 0;
111
+ for await (const chunk of body) {
112
+ signal.throwIfAborted();
113
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
114
+ size += bytes.length;
115
+ if (size > this.#limits.maxResponseBytes)
116
+ throw new ToolboxError(`HTTP response exceeded ${this.#limits.maxResponseBytes} bytes`, { kind: "limit_exceeded" });
117
+ chunks.push(bytes);
118
+ }
119
+ return { status: response.statusCode, headers: response.headers, body: Buffer.concat(chunks, size) };
120
+ } finally {
121
+ signal.removeEventListener("abort", abort);
122
+ body.destroy();
123
+ }
124
+ }, signal).catch((error) => {
125
+ signal.throwIfAborted();
126
+ throw error;
127
+ }).finally(() => clearTimeout(timer));
128
+ this.#operations.add(pending);
129
+ pending.then(() => this.#operations.delete(pending), () => this.#operations.delete(pending));
130
+ return pending;
131
+ }
132
+ dispose() {
133
+ return this.#disposal ??= (async () => {
134
+ this.#controller.abort(new Error("HTTP client disposed"));
135
+ await this.#initialization?.catch(() => {});
136
+ await Promise.allSettled(this.#operations);
137
+ this.#handler?.destroy();
138
+ })();
139
+ }
140
+ }
141
+
142
+ export { HttpClient };
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-v3hxvnrc.js";
7
7
  import {
8
8
  s3Handler
9
- } from "./chunk-x4ntb898.js";
9
+ } from "./chunk-z8e1ckkq.js";
10
10
 
11
11
  // src/s3/client.ts
12
12
  import {
@@ -1,46 +1,46 @@
1
- // src/s3/handler.ts
1
+ // src/http/handler.ts
2
2
  import { Agent as HttpAgent } from "node:http";
3
3
  import { Agent as HttpsAgent } from "node:https";
4
+ import { isIP } from "node:net";
5
+ import { checkServerIdentity } from "node:tls";
4
6
  import { NodeHttpHandler } from "@smithy/node-http-handler";
5
- function s3Handler(target, route, limits) {
7
+ function httpHandler(target, route, limits) {
6
8
  const endpoint = new URL(target.endpoint);
7
- const mapped = route.host !== endpoint.hostname || route.port !== Number(endpoint.port || (endpoint.protocol === "https:" ? 443 : 80));
8
- if (mapped && target.forcePathStyle === false) {
9
- throw new Error("S3 mapped transports require path-style addressing to preserve bucket and TLS identity");
10
- }
9
+ const hostname = endpoint.hostname.replace(/^\[|\]$/g, "");
10
+ const mapped = route.host !== hostname || route.port !== Number(endpoint.port || (endpoint.protocol === "https:" ? 443 : 80));
11
11
  const pool = { keepAlive: true, maxSockets: limits.concurrency, maxTotalSockets: limits.concurrency };
12
12
  const httpAgent = new HttpAgent(pool);
13
13
  const httpsAgent = new HttpsAgent({
14
14
  ...pool,
15
15
  ca: target.ca,
16
16
  rejectUnauthorized: true,
17
- ...mapped ? { servername: endpoint.hostname } : {}
17
+ ...mapped ? {
18
+ servername: isIP(hostname) ? "" : hostname,
19
+ checkServerIdentity: (_host, certificate) => checkServerIdentity(hostname, certificate)
20
+ } : {}
18
21
  });
19
- const transport = new NodeHttpHandler({
22
+ const engine = new NodeHttpHandler({
20
23
  httpAgent,
21
24
  httpsAgent,
22
25
  connectionTimeout: limits.connectTimeoutMs,
23
26
  requestTimeout: limits.requestTimeoutMs,
24
27
  throwOnRequestTimeout: true
25
28
  });
26
- const handler = {
29
+ return {
27
30
  handle(request, options) {
28
31
  if (!mapped)
29
- return transport.handle(request, options);
32
+ return engine.handle(request, options);
30
33
  const routed = request.clone();
31
34
  routed.hostname = route.host;
32
35
  routed.port = route.port;
33
- return transport.handle(routed, options);
36
+ return engine.handle(routed, options);
34
37
  },
35
38
  destroy() {
36
- transport.destroy();
39
+ engine.destroy();
40
+ httpAgent.destroy();
41
+ httpsAgent.destroy();
37
42
  }
38
43
  };
39
- return { handler, destroy: () => {
40
- handler.destroy();
41
- httpAgent.destroy();
42
- httpsAgent.destroy();
43
- } };
44
44
  }
45
45
 
46
- export { s3Handler };
46
+ export { httpHandler };
@@ -0,0 +1,16 @@
1
+ import {
2
+ httpHandler
3
+ } from "./chunk-c2b2jwm4.js";
4
+
5
+ // src/s3/handler.ts
6
+ function s3Handler(target, route, limits) {
7
+ const endpoint = new URL(target.endpoint);
8
+ const mapped = route.host !== endpoint.hostname || route.port !== Number(endpoint.port || (endpoint.protocol === "https:" ? 443 : 80));
9
+ if (mapped && target.forcePathStyle === false) {
10
+ throw new Error("S3 mapped transports require path-style addressing to preserve bucket and TLS identity");
11
+ }
12
+ const handler = httpHandler(target, route, limits);
13
+ return { handler, destroy: () => handler.destroy() };
14
+ }
15
+
16
+ export { s3Handler };
@@ -0,0 +1,15 @@
1
+ import type { Client } from "../client";
2
+ import type { ClientLifecycle } from "../datasource";
3
+ import { Transport } from "../transport";
4
+ import type { HttpTarget, HttpLimits, HttpRequestOptions, HttpResponse, HttpApi } from "./types";
5
+ /** HTTP clients borrow a Transport; their pools and response bodies belong to the client. */
6
+ export declare class HttpClient implements Client, HttpApi {
7
+ #private;
8
+ private readonly transport;
9
+ private readonly lifecycle;
10
+ readonly signal: AbortSignal;
11
+ constructor(target: HttpTarget, transport: Transport, limits: HttpLimits, lifecycle?: ClientLifecycle);
12
+ initialize(): Promise<void>;
13
+ request(path: string, options?: HttpRequestOptions): Promise<HttpResponse>;
14
+ dispose(): Promise<void>;
15
+ }
@@ -0,0 +1,21 @@
1
+ import {
2
+ HttpClient
3
+ } from "../chunk-56fev9np.js";
4
+ import"../chunk-18gcp0ck.js";
5
+ import"../chunk-kap6ka3n.js";
6
+ import"../chunk-v3hxvnrc.js";
7
+ import"../chunk-c2b2jwm4.js";
8
+ import"../chunk-ssj93brx.js";
9
+ import"../chunk-ehmx0yhp.js";
10
+ import"../chunk-0d8vs5q8.js";
11
+ import"../chunk-xgnz10sr.js";
12
+ import"../chunk-6fnhzhdb.js";
13
+ import"../chunk-mvkxs8d0.js";
14
+ import"../chunk-rq5fc007.js";
15
+ import"../chunk-9shz0bw1.js";
16
+ import"../chunk-sb5qzv37.js";
17
+ import"../chunk-43mcyrh4.js";
18
+ import"../chunk-rkt41za2.js";
19
+ export {
20
+ HttpClient
21
+ };
@@ -0,0 +1,10 @@
1
+ import { NodeHttpHandler } from "@smithy/node-http-handler";
2
+ import type { Endpoint } from "../transport";
3
+ import type { HttpTarget, HttpLimits } from "./types";
4
+ /** @rule Routing changes the dial address, never the HTTP Host or certificate identity. */
5
+ export declare function httpHandler(target: HttpTarget, route: Endpoint, limits: Omit<HttpLimits, "maxResponseBytes">): {
6
+ handle(request: Parameters<NodeHttpHandler["handle"]>[0], options: Parameters<NodeHttpHandler["handle"]>[1]): Promise<{
7
+ response: import("@smithy/core/transport").HttpResponse;
8
+ }>;
9
+ destroy(): void;
10
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ httpHandler
3
+ } from "../chunk-c2b2jwm4.js";
4
+ export {
5
+ httpHandler
6
+ };
@@ -0,0 +1,2 @@
1
+ export { HttpClient } from "./client";
2
+ export type { HttpTarget, HttpLimits, HttpRequestOptions, HttpResponse, HttpApi } from "./types";
@@ -0,0 +1,21 @@
1
+ import {
2
+ HttpClient
3
+ } from "../chunk-56fev9np.js";
4
+ import"../chunk-18gcp0ck.js";
5
+ import"../chunk-kap6ka3n.js";
6
+ import"../chunk-v3hxvnrc.js";
7
+ import"../chunk-c2b2jwm4.js";
8
+ import"../chunk-ssj93brx.js";
9
+ import"../chunk-ehmx0yhp.js";
10
+ import"../chunk-0d8vs5q8.js";
11
+ import"../chunk-xgnz10sr.js";
12
+ import"../chunk-6fnhzhdb.js";
13
+ import"../chunk-mvkxs8d0.js";
14
+ import"../chunk-rq5fc007.js";
15
+ import"../chunk-9shz0bw1.js";
16
+ import"../chunk-sb5qzv37.js";
17
+ import"../chunk-43mcyrh4.js";
18
+ import"../chunk-rkt41za2.js";
19
+ export {
20
+ HttpClient
21
+ };
@@ -0,0 +1,34 @@
1
+ export interface HttpTarget {
2
+ /** Logical endpoint; forwarding never changes HTTP Host or TLS identity. */
3
+ endpoint: string;
4
+ ca?: string;
5
+ }
6
+ /** Request time includes queueing, route preparation and response consumption. */
7
+ export interface HttpLimits {
8
+ concurrency: number;
9
+ connectTimeoutMs: number;
10
+ requestTimeoutMs: number;
11
+ maxResponseBytes: number;
12
+ }
13
+ export interface HttpRequestOptions {
14
+ method?: string;
15
+ headers?: Record<string, string>;
16
+ body?: string | Uint8Array;
17
+ signal?: AbortSignal;
18
+ }
19
+ /** The wire body is consumed or destroyed before return; callers own no socket. */
20
+ export interface HttpResponse {
21
+ status: number;
22
+ headers: Readonly<Record<string, string>>;
23
+ body: Uint8Array;
24
+ }
25
+ /**
26
+ * @spec Responses are bounded and consumed before returning; cancellation releases the request's resources.
27
+ * @rule HTTP statuses and redirects are returned without automatic replay or redirect following.
28
+ * @case id=http_forwarded_identity,desc=`HTTP through a mapped route`,expect=`original Host and TLS identity`
29
+ * @case id=http_cancel_body,desc=`cancel an active body read`,expect=`original cancellation reason and released pool slot`
30
+ * @see {@link component://docs/toolbox.md}
31
+ */
32
+ export interface HttpApi {
33
+ request(path: string, options?: HttpRequestOptions): Promise<HttpResponse>;
34
+ }
File without changes
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-ze1hng62.js";
3
+ } from "../chunk-hbhbragw.js";
4
4
  import"../chunk-5w85c7cs.js";
5
- import"../chunk-ae84rzq5.js";
6
5
  import"../chunk-dpcge1xt.js";
7
6
  import"../chunk-xeft7af0.js";
7
+ import"../chunk-ae84rzq5.js";
8
8
  import"../chunk-a9htb6cr.js";
9
9
  import"../chunk-v3hxvnrc.js";
10
10
  import"../chunk-0d8vs5q8.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-ze1hng62.js";
3
+ } from "../chunk-hbhbragw.js";
4
4
  import"../chunk-5w85c7cs.js";
5
- import"../chunk-ae84rzq5.js";
6
5
  import"../chunk-dpcge1xt.js";
7
6
  import"../chunk-xeft7af0.js";
7
+ import"../chunk-ae84rzq5.js";
8
8
  import {
9
9
  clientKey
10
10
  } from "../chunk-a9htb6cr.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodLogClient
3
- } from "../chunk-010339ga.js";
3
+ } from "../chunk-mnad4zkp.js";
4
4
  import"../chunk-8nm9f0hh.js";
5
- import"../chunk-1vfwvgkj.js";
6
5
  import"../chunk-mp88s7r7.js";
6
+ import"../chunk-1vfwvgkj.js";
7
7
  import"../chunk-a9htb6cr.js";
8
8
  import"../chunk-v3hxvnrc.js";
9
9
  export {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodLogClient
3
- } from "../chunk-010339ga.js";
3
+ } from "../chunk-mnad4zkp.js";
4
4
  import"../chunk-8nm9f0hh.js";
5
- import"../chunk-1vfwvgkj.js";
6
5
  import"../chunk-mp88s7r7.js";
6
+ import"../chunk-1vfwvgkj.js";
7
7
  import"../chunk-a9htb6cr.js";
8
8
  import {
9
9
  clientKey
@@ -1,12 +1,3 @@
1
- import {
2
- limitedRows,
3
- limitedStatement,
4
- queryLimited
5
- } from "../chunk-1gyshqd9.js";
6
- import"../chunk-pfar9cm3.js";
7
- import {
8
- withReadScope
9
- } from "../chunk-4sqvppz7.js";
10
1
  import {
11
2
  MysqlClient,
12
3
  MysqlDatabase,
@@ -14,10 +5,19 @@ import {
14
5
  } from "../chunk-ex429qjt.js";
15
6
  import"../chunk-m91t44jh.js";
16
7
  import"../chunk-db4an9td.js";
17
- import"../chunk-835fssgz.js";
18
8
  import {
19
9
  parseMysqlEnvTarget
20
10
  } from "../chunk-qq77x9ek.js";
11
+ import {
12
+ limitedRows,
13
+ limitedStatement,
14
+ queryLimited
15
+ } from "../chunk-1gyshqd9.js";
16
+ import"../chunk-835fssgz.js";
17
+ import"../chunk-pfar9cm3.js";
18
+ import {
19
+ withReadScope
20
+ } from "../chunk-4sqvppz7.js";
21
21
  import"../chunk-18gcp0ck.js";
22
22
  import"../chunk-kap6ka3n.js";
23
23
  import"../chunk-v3hxvnrc.js";
package/dist/s3/client.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  S3Client
3
- } from "../chunk-7hbvjzb9.js";
3
+ } from "../chunk-7m95c7pn.js";
4
4
  import"../chunk-18gcp0ck.js";
5
5
  import"../chunk-kap6ka3n.js";
6
6
  import"../chunk-v3hxvnrc.js";
7
- import"../chunk-x4ntb898.js";
7
+ import"../chunk-z8e1ckkq.js";
8
+ import"../chunk-c2b2jwm4.js";
8
9
  import"../chunk-ssj93brx.js";
9
10
  import"../chunk-ehmx0yhp.js";
10
11
  import"../chunk-0d8vs5q8.js";
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  S3DataSource
3
- } from "../chunk-ccre3nh1.js";
3
+ } from "../chunk-3b877a0y.js";
4
4
  import"../chunk-z5pm2emz.js";
5
- import"../chunk-7hbvjzb9.js";
5
+ import"../chunk-7m95c7pn.js";
6
6
  import"../chunk-18gcp0ck.js";
7
7
  import"../chunk-kap6ka3n.js";
8
8
  import"../chunk-v3hxvnrc.js";
9
- import"../chunk-x4ntb898.js";
9
+ import"../chunk-z8e1ckkq.js";
10
+ import"../chunk-c2b2jwm4.js";
10
11
  import"../chunk-ssj93brx.js";
11
12
  import"../chunk-ehmx0yhp.js";
12
13
  import"../chunk-0d8vs5q8.js";
@@ -1,10 +1,9 @@
1
- import { NodeHttpHandler } from "@smithy/node-http-handler";
2
1
  import type { Endpoint } from "../transport";
3
2
  import type { S3Limits, S3Target } from "./types";
4
- /** Routing changes only the socket destination, never the signed HTTP Host or TLS identity. */
3
+ /** Signing precedes the HTTP handler; routing must preserve the signed Host and TLS identity. */
5
4
  export declare function s3Handler(target: S3Target, route: Endpoint, limits: S3Limits): {
6
5
  handler: {
7
- handle(request: Parameters<NodeHttpHandler["handle"]>[0], options: Parameters<NodeHttpHandler["handle"]>[1]): Promise<{
6
+ handle(request: Parameters<import("@smithy/node-http-handler").NodeHttpHandler["handle"]>[0], options: Parameters<import("@smithy/node-http-handler").NodeHttpHandler["handle"]>[1]): Promise<{
8
7
  response: import("@smithy/core/transport").HttpResponse;
9
8
  }>;
10
9
  destroy(): void;
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  s3Handler
3
- } from "../chunk-x4ntb898.js";
3
+ } from "../chunk-z8e1ckkq.js";
4
+ import"../chunk-c2b2jwm4.js";
4
5
  export {
5
6
  s3Handler
6
7
  };
package/dist/s3/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  S3DataSource
3
- } from "../chunk-ccre3nh1.js";
3
+ } from "../chunk-3b877a0y.js";
4
4
  import"../chunk-z5pm2emz.js";
5
5
  import {
6
6
  S3Client
7
- } from "../chunk-7hbvjzb9.js";
7
+ } from "../chunk-7m95c7pn.js";
8
8
  import"../chunk-18gcp0ck.js";
9
9
  import"../chunk-kap6ka3n.js";
10
10
  import"../chunk-v3hxvnrc.js";
11
- import"../chunk-x4ntb898.js";
11
+ import"../chunk-z8e1ckkq.js";
12
+ import"../chunk-c2b2jwm4.js";
12
13
  import"../chunk-ssj93brx.js";
13
14
  import"../chunk-ehmx0yhp.js";
14
15
  import"../chunk-0d8vs5q8.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compforge/harness-toolbox",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Shared infrastructure clients, transports and bounded data capture",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -92,6 +92,10 @@
92
92
  "./file": {
93
93
  "types": "./dist/file/index.d.ts",
94
94
  "import": "./dist/file/index.js"
95
+ },
96
+ "./http": {
97
+ "types": "./dist/http/index.d.ts",
98
+ "import": "./dist/http/index.js"
95
99
  }
96
100
  },
97
101
  "files": [
@@ -108,7 +112,8 @@
108
112
  "mysql2": "3.23.1",
109
113
  "node-fetch": "2.7.0",
110
114
  "race-signal": "2.0.2",
111
- "ws": "8.21.3"
115
+ "ws": "8.21.3",
116
+ "@smithy/core": "3.34.1"
112
117
  },
113
118
  "devDependencies": {
114
119
  "@types/bun": "latest",
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  KubernetesResourceTransport
3
3
  } from "./chunk-5w85c7cs.js";
4
- import {
5
- resolveWorkload
6
- } from "./chunk-ae84rzq5.js";
7
4
  import {
8
5
  KubernetesExecTransport
9
6
  } from "./chunk-xeft7af0.js";
7
+ import {
8
+ resolveWorkload
9
+ } from "./chunk-ae84rzq5.js";
10
10
  import {
11
11
  ServicePortForwarder
12
12
  } from "./chunk-0d8vs5q8.js";
@@ -2,12 +2,12 @@ import {
2
2
  PodLogByteBudget,
3
3
  runPodLogCapturePlan
4
4
  } from "./chunk-8nm9f0hh.js";
5
- import {
6
- LogCaptureFile
7
- } from "./chunk-1vfwvgkj.js";
8
5
  import {
9
6
  logTimestampNanos
10
7
  } from "./chunk-mp88s7r7.js";
8
+ import {
9
+ LogCaptureFile
10
+ } from "./chunk-1vfwvgkj.js";
11
11
  import {
12
12
  clientKey
13
13
  } from "./chunk-a9htb6cr.js";