@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 +62 -0
- package/README.md +73 -0
- package/dist/bun.d.ts +24 -0
- package/dist/bun.d.ts.map +1 -0
- package/dist/bun.js +83 -0
- package/dist/bun.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +34 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +326 -0
- package/dist/node.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/src/bun.ts +109 -0
- package/src/index.ts +15 -0
- package/src/node.ts +380 -0
- package/src/types.ts +113 -0
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
|
package/dist/bun.js.map
ADDED
|
@@ -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"}
|
package/dist/index.d.ts
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.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
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|