@agentuity/storage 3.0.0-alpha.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/AGENTS.md ADDED
@@ -0,0 +1,62 @@
1
+ # Agent Guidelines for @agentuity/storage
2
+
3
+ ## Package Overview
4
+
5
+ Dual-runtime S3 client for Agentuity storage buckets. Provides a unified
6
+ `S3ClientLike` interface backed by either Bun's native `S3Client` (faster,
7
+ preferred when available) or `@aws-sdk/client-s3` (works under Node).
8
+
9
+ ## Commands
10
+
11
+ - **Build**: `bun run build`
12
+ - **Typecheck**: `bun run typecheck`
13
+ - **Clean**: `rm -rf dist`
14
+
15
+ ## Architecture
16
+
17
+ - **Runtime**: Node.js and Bun compatible
18
+ - **Backend selection**: `package.json` `exports` conditions select
19
+ `./dist/bun.js` under Bun and `./dist/node.js` under Node automatically.
20
+ Subpath imports `@agentuity/storage/bun` and `@agentuity/storage/node`
21
+ are also available for explicit pinning.
22
+ - **Dependencies**: `@aws-sdk/client-s3` (loaded lazily by the Node backend
23
+ on first use, so non-storage callers don't pay the cold-start cost).
24
+
25
+ ## Usage
26
+
27
+ ```typescript
28
+ import { createS3Client } from '@agentuity/storage';
29
+
30
+ const s3 = createS3Client({
31
+ endpoint: 'my-bucket.agentuity.run',
32
+ access_key: '...',
33
+ secret_key: '...',
34
+ });
35
+
36
+ const list = await s3.list({ prefix: 'logs/' });
37
+ for (const obj of list.contents) {
38
+ console.log(obj.key, obj.size, obj.lastModified);
39
+ }
40
+
41
+ const bytes = await s3.write('hello.txt', 'Hello, World!', {
42
+ type: 'text/plain',
43
+ });
44
+ console.log(`Uploaded ${bytes} bytes`);
45
+ ```
46
+
47
+ ### Pinning a backend explicitly
48
+
49
+ ```typescript
50
+ // Bun-only (only resolvable when running under Bun):
51
+ import { createS3Client } from '@agentuity/storage/bun';
52
+
53
+ // Node-compatible (works under both Bun and Node):
54
+ import { createS3Client } from '@agentuity/storage/node';
55
+ ```
56
+
57
+ ## Publishing
58
+
59
+ 1. Run `bun run build`
60
+ 2. Must publish **after** any new direct deps are released
61
+ 3. Must publish **before** `@agentuity/cli` (the CLI's storage subcommands
62
+ depend on this package)
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @agentuity/storage
2
+
3
+ Dual-runtime S3 client for Agentuity storage buckets.
4
+
5
+ ## Why this exists
6
+
7
+ Agentuity storage buckets are S3-compatible. The CLI and other tooling
8
+ need to upload, download, list, and delete objects. Bun ships a native
9
+ `S3Client` that's significantly faster than `@aws-sdk/client-s3` for
10
+ large transfers, but it doesn't work under Node.
11
+
12
+ This package exposes a single `S3ClientLike` interface implemented by
13
+ both backends. Bun consumers automatically get the fast native client;
14
+ Node consumers automatically get the AWS SDK. Subpath imports
15
+ (`@agentuity/storage/bun`, `@agentuity/storage/node`) are available for
16
+ explicit pinning.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @agentuity/storage
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { createS3Client } from '@agentuity/storage';
28
+
29
+ const s3 = createS3Client({
30
+ endpoint: 'my-bucket.agentuity.run',
31
+ access_key: 'AKIA...',
32
+ secret_key: '...',
33
+ region: 'us-east-1', // optional, defaults to 'auto'
34
+ });
35
+
36
+ // List objects
37
+ const result = await s3.list({ prefix: 'logs/', maxKeys: 100 });
38
+ for (const obj of result.contents) {
39
+ console.log(obj.key, obj.size, obj.lastModified);
40
+ }
41
+
42
+ // Upload (string, Buffer, Uint8Array, or ReadableStream)
43
+ const bytes = await s3.write('hello.txt', 'Hello, World!', {
44
+ type: 'text/plain',
45
+ });
46
+
47
+ // Stat (HEAD)
48
+ const meta = await s3.stat('hello.txt');
49
+ console.log(meta.size, meta.type);
50
+
51
+ // Download
52
+ const file = s3.file('hello.txt');
53
+ const text = await file.text();
54
+
55
+ // Delete
56
+ await s3.delete('hello.txt');
57
+ ```
58
+
59
+ ## Backends
60
+
61
+ | Subpath | Resolver | Implementation | Notes |
62
+ | --- | --- | --- | --- |
63
+ | `@agentuity/storage` (bare) | `package.json` conditions | Bun → `bun.ts`, Node → `node.ts` | Recommended for most callers |
64
+ | `@agentuity/storage/bun` | explicit | `Bun.S3Client` wrapper | Bun runtime only |
65
+ | `@agentuity/storage/node` | explicit | `@aws-sdk/client-s3` wrapper | Works under both runtimes |
66
+
67
+ The Node backend lazy-loads `@aws-sdk/client-s3` on first method call,
68
+ so importing the package does not incur the SDK's cold-start cost
69
+ unless storage operations are actually performed.
70
+
71
+ ## License
72
+
73
+ Apache-2.0
package/dist/bun.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Bun-backed implementation of `S3ClientLike`.
3
+ *
4
+ * Thin wrapper around `Bun.S3Client`. Only resolvable when the consumer
5
+ * is running under Bun — `package.json`'s `"bun"` exports condition
6
+ * routes here automatically; explicit `@agentuity/storage/bun` imports
7
+ * also land here.
8
+ *
9
+ * Falling through to this module under Node will fail at import time
10
+ * because `import { S3Client } from 'bun'` is not satisfiable there.
11
+ * That is intentional and matches the contract of the `bun` exports
12
+ * condition.
13
+ */
14
+ import type { BucketConfig, S3ClientLike } from './types.ts';
15
+ export type { BucketConfig, S3ClientLike } from './types.ts';
16
+ /**
17
+ * Create an S3 client backed by `Bun.S3Client`.
18
+ *
19
+ * Endpoints are bucket-scoped (virtual-hosted-style), so we do not pass
20
+ * a bucket parameter on the client itself; the hostname routes to the
21
+ * correct bucket.
22
+ */
23
+ export declare function createS3Client(bucket: BucketConfig): S3ClientLike;
24
+ //# sourceMappingURL=bun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../src/bun.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EACX,YAAY,EAEZ,YAAY,EAMZ,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAmEjE"}
package/dist/bun.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Bun-backed implementation of `S3ClientLike`.
3
+ *
4
+ * Thin wrapper around `Bun.S3Client`. Only resolvable when the consumer
5
+ * is running under Bun — `package.json`'s `"bun"` exports condition
6
+ * routes here automatically; explicit `@agentuity/storage/bun` imports
7
+ * also land here.
8
+ *
9
+ * Falling through to this module under Node will fail at import time
10
+ * because `import { S3Client } from 'bun'` is not satisfiable there.
11
+ * That is intentional and matches the contract of the `bun` exports
12
+ * condition.
13
+ */
14
+ import { S3Client } from 'bun';
15
+ /**
16
+ * Create an S3 client backed by `Bun.S3Client`.
17
+ *
18
+ * Endpoints are bucket-scoped (virtual-hosted-style), so we do not pass
19
+ * a bucket parameter on the client itself; the hostname routes to the
20
+ * correct bucket.
21
+ */
22
+ export function createS3Client(bucket) {
23
+ const endpoint = bucket.endpoint.startsWith('http')
24
+ ? bucket.endpoint
25
+ : `https://${bucket.endpoint}`;
26
+ const client = new S3Client({
27
+ endpoint,
28
+ accessKeyId: bucket.access_key,
29
+ secretAccessKey: bucket.secret_key,
30
+ region: bucket.region || 'auto',
31
+ virtualHostedStyle: true,
32
+ });
33
+ return {
34
+ async list(opts) {
35
+ // `Bun.S3Client.list` accepts `null` for "no filter".
36
+ const out = (await client.list(opts ?? null));
37
+ return {
38
+ contents: (out.contents ?? []).map((o) => ({
39
+ key: o.key,
40
+ size: o.size ?? 0,
41
+ lastModified: normalizeTimestamp(o.lastModified),
42
+ etag: o.etag,
43
+ })),
44
+ isTruncated: out.isTruncated ?? false,
45
+ };
46
+ },
47
+ async stat(key) {
48
+ const out = await client.stat(key);
49
+ return {
50
+ size: out.size ?? 0,
51
+ type: out.type,
52
+ lastModified: out.lastModified,
53
+ // Bun's stat returns the etag with mixed casing across versions.
54
+ etag: out.etag ?? out.ETag,
55
+ };
56
+ },
57
+ file(key) {
58
+ const f = client.file(key);
59
+ return {
60
+ arrayBuffer: () => f.arrayBuffer(),
61
+ text: () => f.text(),
62
+ stream: () => f.stream(),
63
+ };
64
+ },
65
+ async write(key, body, opts) {
66
+ // `Bun.S3Client.write` accepts string, Uint8Array, ArrayBuffer,
67
+ // Blob, ReadableStream, or Response. We accept the same shapes
68
+ // minus Response (callers should pass the underlying stream).
69
+ return client.write(key, body, opts);
70
+ },
71
+ async delete(key) {
72
+ await client.delete(key);
73
+ },
74
+ };
75
+ }
76
+ function normalizeTimestamp(value) {
77
+ if (!value)
78
+ return '';
79
+ if (typeof value === 'string')
80
+ return value;
81
+ return value.toISOString();
82
+ }
83
+ //# sourceMappingURL=bun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bun.js","sourceRoot":"","sources":["../src/bun.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAc/B;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QAClD,CAAC,CAAC,MAAM,CAAC,QAAQ;QACjB,CAAC,CAAC,WAAW,MAAM,CAAC,QAAQ,EAAE,CAAC;IAEhC,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC;QAC3B,QAAQ;QACR,WAAW,EAAE,MAAM,CAAC,UAAU;QAC9B,eAAe,EAAE,MAAM,CAAC,UAAU;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;QAC/B,kBAAkB,EAAE,IAAI;KACxB,CAAC,CAAC;IAEH,OAAO;QACN,KAAK,CAAC,IAAI,CAAC,IAA2B;YACrC,sDAAsD;YACtD,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,IAAK,IAAY,CAAC,CAQpD,CAAC;YACF,OAAO;gBACN,QAAQ,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC1C,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC;oBACjB,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC;oBAChD,IAAI,EAAE,CAAC,CAAC,IAAI;iBACZ,CAAC,CAAC;gBACH,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,KAAK;aACrC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAW;YACrB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnC,OAAO;gBACN,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;gBACnB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,iEAAiE;gBACjE,IAAI,EAAG,GAAW,CAAC,IAAI,IAAK,GAAW,CAAC,IAAI;aAC5C,CAAC;QACH,CAAC;QAED,IAAI,CAAC,GAAW;YACf,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC3B,OAAO;gBACN,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE;gBAClC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;gBACpB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,EAAgC;aACtD,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,IAAY,EAAE,IAAqB;YAC3D,gEAAgE;YAChE,+DAA+D;YAC/D,8DAA8D;YAC9D,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAW,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAW;YACvB,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;KACD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAgC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Default entry for `@agentuity/storage`.
3
+ *
4
+ * The real backend selection happens in `package.json`'s `exports`
5
+ * conditions: under Bun the `"bun"` condition routes the bare import
6
+ * to `./bun.js`; under Node (and other resolvers that respect the
7
+ * `"node"` condition) it routes to `./node.js`.
8
+ *
9
+ * This file exists for resolvers that ignore conditions entirely (some
10
+ * IDE indexers, certain bundler configurations, or callers using the
11
+ * legacy `main` field). For those, we re-export the Node backend,
12
+ * which works under both runtimes.
13
+ */
14
+ export * from './node.ts';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Default entry for `@agentuity/storage`.
3
+ *
4
+ * The real backend selection happens in `package.json`'s `exports`
5
+ * conditions: under Bun the `"bun"` condition routes the bare import
6
+ * to `./bun.js`; under Node (and other resolvers that respect the
7
+ * `"node"` condition) it routes to `./node.js`.
8
+ *
9
+ * This file exists for resolvers that ignore conditions entirely (some
10
+ * IDE indexers, certain bundler configurations, or callers using the
11
+ * legacy `main` field). For those, we re-export the Node backend,
12
+ * which works under both runtimes.
13
+ */
14
+ export * from "./node.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,WAAW,CAAC"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Node-backed implementation of `S3ClientLike`.
3
+ *
4
+ * Wraps `@aws-sdk/client-s3`. Resolvable on both Node and Bun, so it
5
+ * can serve as the package's default fallback for resolvers that do
6
+ * not honor the `"bun"` exports condition.
7
+ *
8
+ * Design notes:
9
+ *
10
+ * 1. **Lazy SDK loading.** `@aws-sdk/client-s3` is large (~1 MB on
11
+ * disk) and imports several hundred files at startup. To keep the
12
+ * cost off the cold-start path of callers that import this module
13
+ * but never actually upload/download, the SDK is loaded via dynamic
14
+ * `import()` on first method call.
15
+ *
16
+ * 2. **Streamed uploads track byte counts via a counting passthrough.**
17
+ * `PutObjectCommand` does not report bytes uploaded. For
18
+ * fixed-size bodies (`Uint8Array`, `ArrayBuffer`, `Buffer`,
19
+ * `string`, `Blob`) we use `.byteLength` / `.size`. For
20
+ * `ReadableStream` bodies we wrap the source in a counting
21
+ * `Transform` so the returned byte count matches what was actually
22
+ * sent on the wire.
23
+ *
24
+ * 3. **Bucket-in-endpoint addressing.** Agentuity buckets use
25
+ * virtual-host-style endpoints (`<bucket>.<host>`), so the bucket
26
+ * name is implicit in the URL. The SDK still requires a `Bucket`
27
+ * parameter on each command; we extract it from the endpoint's
28
+ * leading hostname label and rely on the endpoint override to route
29
+ * correctly. `forcePathStyle` is `false`.
30
+ */
31
+ import type { BucketConfig, S3ClientLike } from './types.ts';
32
+ export type { BucketConfig, S3ClientLike } from './types.ts';
33
+ export declare function createS3Client(bucket: BucketConfig): S3ClientLike;
34
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAKH,OAAO,KAAK,EACX,YAAY,EAEZ,YAAY,EAMZ,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA4B7D,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CA2IjE"}
package/dist/node.js ADDED
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Node-backed implementation of `S3ClientLike`.
3
+ *
4
+ * Wraps `@aws-sdk/client-s3`. Resolvable on both Node and Bun, so it
5
+ * can serve as the package's default fallback for resolvers that do
6
+ * not honor the `"bun"` exports condition.
7
+ *
8
+ * Design notes:
9
+ *
10
+ * 1. **Lazy SDK loading.** `@aws-sdk/client-s3` is large (~1 MB on
11
+ * disk) and imports several hundred files at startup. To keep the
12
+ * cost off the cold-start path of callers that import this module
13
+ * but never actually upload/download, the SDK is loaded via dynamic
14
+ * `import()` on first method call.
15
+ *
16
+ * 2. **Streamed uploads track byte counts via a counting passthrough.**
17
+ * `PutObjectCommand` does not report bytes uploaded. For
18
+ * fixed-size bodies (`Uint8Array`, `ArrayBuffer`, `Buffer`,
19
+ * `string`, `Blob`) we use `.byteLength` / `.size`. For
20
+ * `ReadableStream` bodies we wrap the source in a counting
21
+ * `Transform` so the returned byte count matches what was actually
22
+ * sent on the wire.
23
+ *
24
+ * 3. **Bucket-in-endpoint addressing.** Agentuity buckets use
25
+ * virtual-host-style endpoints (`<bucket>.<host>`), so the bucket
26
+ * name is implicit in the URL. The SDK still requires a `Bucket`
27
+ * parameter on each command; we extract it from the endpoint's
28
+ * leading hostname label and rely on the endpoint override to route
29
+ * correctly. `forcePathStyle` is `false`.
30
+ */
31
+ import { Buffer } from 'node:buffer';
32
+ import { Readable, Transform } from 'node:stream';
33
+ let sdkModule = null;
34
+ let sdkPromise = null;
35
+ async function loadSdk() {
36
+ if (sdkModule)
37
+ return sdkModule;
38
+ if (!sdkPromise) {
39
+ sdkPromise = import('@aws-sdk/client-s3').then((mod) => {
40
+ sdkModule = mod;
41
+ return mod;
42
+ });
43
+ }
44
+ return sdkPromise;
45
+ }
46
+ export function createS3Client(bucket) {
47
+ const endpoint = bucket.endpoint.startsWith('http')
48
+ ? bucket.endpoint
49
+ : `https://${bucket.endpoint}`;
50
+ // Extract the leading hostname label as the bucket name. The endpoint
51
+ // is virtual-hosted-style (`<bucket>.<host>`), so the SDK's `Bucket`
52
+ // parameter is essentially a placeholder — what actually routes the
53
+ // request is the `endpoint` URL.
54
+ const bucketLabel = extractBucketLabel(endpoint);
55
+ const state = {
56
+ endpoint,
57
+ bucketLabel,
58
+ region: bucket.region || 'auto',
59
+ credentials: {
60
+ accessKeyId: bucket.access_key,
61
+ secretAccessKey: bucket.secret_key,
62
+ },
63
+ clientPromise: null,
64
+ };
65
+ const getClient = async () => {
66
+ if (!state.clientPromise) {
67
+ const sdk = await loadSdk();
68
+ state.clientPromise = Promise.resolve(new sdk.S3Client({
69
+ endpoint: state.endpoint,
70
+ region: state.region,
71
+ credentials: state.credentials,
72
+ forcePathStyle: false,
73
+ }));
74
+ }
75
+ return state.clientPromise;
76
+ };
77
+ return {
78
+ async list(opts) {
79
+ const sdk = await loadSdk();
80
+ const client = await getClient();
81
+ const out = await client.send(new sdk.ListObjectsV2Command({
82
+ Bucket: state.bucketLabel,
83
+ Prefix: opts?.prefix,
84
+ MaxKeys: opts?.maxKeys,
85
+ }));
86
+ return {
87
+ contents: (out.Contents ?? []).map((o) => ({
88
+ key: o.Key ?? '',
89
+ size: o.Size ?? 0,
90
+ lastModified: o.LastModified?.toISOString() ?? '',
91
+ etag: o.ETag,
92
+ })),
93
+ isTruncated: out.IsTruncated ?? false,
94
+ };
95
+ },
96
+ async stat(key) {
97
+ const sdk = await loadSdk();
98
+ const client = await getClient();
99
+ const out = await client.send(new sdk.HeadObjectCommand({ Bucket: state.bucketLabel, Key: key }));
100
+ return {
101
+ size: out.ContentLength ?? 0,
102
+ type: out.ContentType,
103
+ lastModified: out.LastModified,
104
+ etag: out.ETag,
105
+ };
106
+ },
107
+ file(key) {
108
+ return {
109
+ async arrayBuffer() {
110
+ const sdk = await loadSdk();
111
+ const client = await getClient();
112
+ const out = await client.send(new sdk.GetObjectCommand({ Bucket: state.bucketLabel, Key: key }));
113
+ return readBodyAsArrayBuffer(out.Body);
114
+ },
115
+ async text() {
116
+ const buf = await this.arrayBuffer();
117
+ return new TextDecoder().decode(buf);
118
+ },
119
+ stream() {
120
+ // Lazily fetch on first pull so callers can hold a handle
121
+ // without triggering a network call upfront.
122
+ let inner = null;
123
+ let reader = null;
124
+ return new ReadableStream({
125
+ async pull(controller) {
126
+ if (!inner) {
127
+ const sdk = await loadSdk();
128
+ const client = await getClient();
129
+ const out = await client.send(new sdk.GetObjectCommand({
130
+ Bucket: state.bucketLabel,
131
+ Key: key,
132
+ }));
133
+ inner = bodyToWebStream(out.Body);
134
+ reader = inner.getReader();
135
+ }
136
+ const { value, done } = await reader.read();
137
+ if (done)
138
+ controller.close();
139
+ else
140
+ controller.enqueue(value);
141
+ },
142
+ async cancel() {
143
+ await reader?.cancel();
144
+ },
145
+ });
146
+ },
147
+ };
148
+ },
149
+ async write(key, body, opts) {
150
+ const sdk = await loadSdk();
151
+ const client = await getClient();
152
+ const { Body, getBytesUploaded } = prepareBody(body);
153
+ await client.send(new sdk.PutObjectCommand({
154
+ Bucket: state.bucketLabel,
155
+ Key: key,
156
+ Body,
157
+ ContentType: opts?.type,
158
+ }));
159
+ return getBytesUploaded();
160
+ },
161
+ async delete(key) {
162
+ const sdk = await loadSdk();
163
+ const client = await getClient();
164
+ await client.send(new sdk.DeleteObjectCommand({ Bucket: state.bucketLabel, Key: key }));
165
+ },
166
+ };
167
+ }
168
+ /**
169
+ * Convert one of our accepted `S3Body` shapes into something the AWS
170
+ * SDK can consume, while also preparing a way to report the number of
171
+ * bytes that flowed to S3.
172
+ *
173
+ * For fixed-size bodies the count is known up front. For streaming
174
+ * bodies we attach a counting `Transform` and read the tally back after
175
+ * the upload completes.
176
+ */
177
+ function prepareBody(body) {
178
+ if (typeof body === 'string') {
179
+ const bytes = Buffer.byteLength(body, 'utf-8');
180
+ return { Body: body, getBytesUploaded: () => bytes };
181
+ }
182
+ if (body instanceof Uint8Array) {
183
+ return { Body: body, getBytesUploaded: () => body.byteLength };
184
+ }
185
+ if (body instanceof ArrayBuffer) {
186
+ const buf = Buffer.from(body);
187
+ return { Body: buf, getBytesUploaded: () => buf.byteLength };
188
+ }
189
+ if (typeof Blob !== 'undefined' && body instanceof Blob) {
190
+ // Convert the Blob to a Node stream, counting bytes as it flows.
191
+ const webStream = body.stream();
192
+ const nodeStream = Readable.fromWeb(webStream);
193
+ const { stream, getBytes } = countingPassthrough(nodeStream);
194
+ return { Body: stream, getBytesUploaded: getBytes };
195
+ }
196
+ if (isWebReadableStream(body)) {
197
+ const nodeStream = Readable.fromWeb(body);
198
+ const { stream, getBytes } = countingPassthrough(nodeStream);
199
+ return { Body: stream, getBytesUploaded: getBytes };
200
+ }
201
+ // Fallthrough: pass through whatever it is. Should be unreachable
202
+ // given the `S3Body` union, but keeps the function total.
203
+ return {
204
+ Body: body,
205
+ getBytesUploaded: () => 0,
206
+ };
207
+ }
208
+ function isWebReadableStream(value) {
209
+ return (typeof value === 'object' &&
210
+ value !== null &&
211
+ typeof value.getReader === 'function');
212
+ }
213
+ /**
214
+ * Wrap a Node `Readable` in a passthrough that counts bytes flowing
215
+ * through it. The returned `getBytes()` callback returns the running
216
+ * tally; call it after the consumer has finished reading.
217
+ */
218
+ function countingPassthrough(source) {
219
+ let count = 0;
220
+ const counter = new Transform({
221
+ transform(chunk, _enc, cb) {
222
+ count += chunk.length;
223
+ cb(null, chunk);
224
+ },
225
+ });
226
+ source.pipe(counter);
227
+ source.on('error', (err) => counter.destroy(err));
228
+ return { stream: counter, getBytes: () => count };
229
+ }
230
+ /**
231
+ * Read an SDK `GetObjectCommand` response body fully into an
232
+ * `ArrayBuffer`. The SDK returns `unknown` for the body shape because
233
+ * it varies by runtime; in Node it's an `IncomingMessage`-style
234
+ * `Readable`.
235
+ */
236
+ async function readBodyAsArrayBuffer(body) {
237
+ if (!body)
238
+ return new ArrayBuffer(0);
239
+ if (body instanceof Uint8Array) {
240
+ // Some shapes return a Uint8Array directly. Copy into a fresh
241
+ // ArrayBuffer so the return type is the strict ArrayBuffer rather
242
+ // than ArrayBuffer | SharedArrayBuffer (which `.buffer` may be).
243
+ const out = new Uint8Array(body.byteLength);
244
+ out.set(body);
245
+ return out.buffer;
246
+ }
247
+ if (isWebReadableStream(body)) {
248
+ const reader = body.getReader();
249
+ const chunks = [];
250
+ while (true) {
251
+ const { value, done } = await reader.read();
252
+ if (done)
253
+ break;
254
+ if (value)
255
+ chunks.push(value);
256
+ }
257
+ return concatUint8Arrays(chunks).buffer;
258
+ }
259
+ // Otherwise treat as a Node Readable.
260
+ const chunks = [];
261
+ for await (const chunk of body) {
262
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
263
+ }
264
+ const merged = Buffer.concat(chunks);
265
+ // Copy into a tightly-sized ArrayBuffer to avoid sharing the underlying
266
+ // pool buffer with other Buffer instances.
267
+ const out = new Uint8Array(merged.byteLength);
268
+ out.set(merged);
269
+ return out.buffer;
270
+ }
271
+ /**
272
+ * Convert an SDK response body into a Web `ReadableStream<Uint8Array>`.
273
+ * Returns an empty stream when the body is missing.
274
+ */
275
+ function bodyToWebStream(body) {
276
+ if (!body) {
277
+ return new ReadableStream({
278
+ start(controller) {
279
+ controller.close();
280
+ },
281
+ });
282
+ }
283
+ if (isWebReadableStream(body))
284
+ return body;
285
+ if (body instanceof Uint8Array) {
286
+ return new ReadableStream({
287
+ start(controller) {
288
+ controller.enqueue(body);
289
+ controller.close();
290
+ },
291
+ });
292
+ }
293
+ // Assume Node Readable.
294
+ return Readable.toWeb(body);
295
+ }
296
+ function concatUint8Arrays(parts) {
297
+ let total = 0;
298
+ for (const p of parts)
299
+ total += p.byteLength;
300
+ // Allocate against a concrete ArrayBuffer (not SharedArrayBuffer) so
301
+ // the resulting `.buffer` is typed as ArrayBuffer.
302
+ const out = new Uint8Array(new ArrayBuffer(total));
303
+ let offset = 0;
304
+ for (const p of parts) {
305
+ out.set(p, offset);
306
+ offset += p.byteLength;
307
+ }
308
+ return out;
309
+ }
310
+ /**
311
+ * Pull the leading hostname label off a virtual-hosted-style endpoint
312
+ * URL. Falls back to `'bucket'` if parsing fails — which is fine
313
+ * because the endpoint override controls actual routing; the SDK only
314
+ * uses `Bucket` to construct path-style URLs (which we never do).
315
+ */
316
+ function extractBucketLabel(endpoint) {
317
+ try {
318
+ const url = new URL(endpoint);
319
+ const firstLabel = url.hostname.split('.')[0];
320
+ return firstLabel || 'bucket';
321
+ }
322
+ catch {
323
+ return 'bucket';
324
+ }
325
+ }
326
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}