@twin.org/blob-storage-connector-aws-s3 0.0.2-next.3 → 0.0.2-next.5

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,7 +13,7 @@ npm install @twin.org/blob-storage-connector-aws-s3
13
13
  The tests developed are functional tests and need an instance of AWS S3 up and running. To run AWS S3 locally using local stack:
14
14
 
15
15
  ```shell
16
- docker run -p 4566:4566 -p 4510-4559:4510-4559 --name twin-blob-aws-s3 -d localstack/localstack -e AWS_DEFAULT_REGION='eu-central-1' -e AWS_ACCESS_KEY_ID='test' -e AWS_SECRET_ACCESS_KEY='test' -e SERVICE='S3'
16
+ docker run -p 4566:4566 --name twin-blob-aws-s3 -d localstack/localstack -e AWS_DEFAULT_REGION='eu-central-1' -e AWS_ACCESS_KEY_ID='test' -e AWS_SECRET_ACCESS_KEY='test' -e SERVICE='S3'
17
17
  ```
18
18
 
19
19
  Afterwards you can run the tests as follows:
@@ -18,7 +18,7 @@ class S3BlobStorageConnector {
18
18
  /**
19
19
  * Runtime name for the class.
20
20
  */
21
- CLASS_NAME = "S3BlobStorageConnector";
21
+ static CLASS_NAME = "S3BlobStorageConnector";
22
22
  /**
23
23
  * The configuration for the connector.
24
24
  * @internal
@@ -34,20 +34,25 @@ class S3BlobStorageConnector {
34
34
  * @param options The options for the connector.
35
35
  */
36
36
  constructor(options) {
37
- core.Guards.object(this.CLASS_NAME, "options", options);
38
- core.Guards.object(this.CLASS_NAME, "options.config", options.config);
39
- core.Guards.stringValue(this.CLASS_NAME, "options.config.region", options.config.region);
40
- core.Guards.stringValue(this.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
41
- core.Guards.stringValue(this.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
42
- core.Guards.stringValue(this.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
37
+ core.Guards.object(S3BlobStorageConnector.CLASS_NAME, "options", options);
38
+ core.Guards.object(S3BlobStorageConnector.CLASS_NAME, "options.config", options.config);
39
+ core.Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.region", options.config.region);
40
+ core.Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
41
+ options.config.authMode ??= "credentials";
42
+ let credentials;
43
+ if (options.config.authMode === "credentials") {
44
+ core.Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
45
+ core.Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
46
+ credentials = {
47
+ accessKeyId: options.config.accessKeyId,
48
+ secretAccessKey: options.config.secretAccessKey
49
+ };
50
+ }
43
51
  this._config = options.config;
44
52
  this._s3Client = new clientS3.S3Client({
45
53
  region: this._config.region,
46
54
  endpoint: this._config.endpoint,
47
- credentials: {
48
- accessKeyId: this._config.accessKeyId,
49
- secretAccessKey: this._config.secretAccessKey
50
- },
55
+ credentials,
51
56
  forcePathStyle: true
52
57
  });
53
58
  }
@@ -61,7 +66,7 @@ class S3BlobStorageConnector {
61
66
  try {
62
67
  await nodeLogging?.log({
63
68
  level: "info",
64
- source: this.CLASS_NAME,
69
+ source: S3BlobStorageConnector.CLASS_NAME,
65
70
  message: "bucketCreating",
66
71
  data: {
67
72
  bucket: this._config.bucketName
@@ -73,7 +78,7 @@ class S3BlobStorageConnector {
73
78
  if (bucketExists) {
74
79
  await nodeLogging?.log({
75
80
  level: "info",
76
- source: this.CLASS_NAME,
81
+ source: S3BlobStorageConnector.CLASS_NAME,
77
82
  message: "bucketExists",
78
83
  data: {
79
84
  bucket: this._config.bucketName
@@ -84,7 +89,7 @@ class S3BlobStorageConnector {
84
89
  await this._s3Client.send(new clientS3.CreateBucketCommand({ Bucket: this._config.bucketName }));
85
90
  await nodeLogging?.log({
86
91
  level: "info",
87
- source: this.CLASS_NAME,
92
+ source: S3BlobStorageConnector.CLASS_NAME,
88
93
  message: "bucketCreated",
89
94
  data: {
90
95
  bucket: this._config.bucketName
@@ -95,7 +100,7 @@ class S3BlobStorageConnector {
95
100
  catch (err) {
96
101
  await nodeLogging?.log({
97
102
  level: "error",
98
- source: this.CLASS_NAME,
103
+ source: S3BlobStorageConnector.CLASS_NAME,
99
104
  message: "bucketCreateFailed",
100
105
  data: {
101
106
  bucket: this._config.bucketName
@@ -112,7 +117,7 @@ class S3BlobStorageConnector {
112
117
  * @returns The id of the stored blob in urn format.
113
118
  */
114
119
  async set(blob) {
115
- core.Guards.uint8Array(this.CLASS_NAME, "blob", blob);
120
+ core.Guards.uint8Array(S3BlobStorageConnector.CLASS_NAME, "blob", blob);
116
121
  try {
117
122
  const id = core.Converter.bytesToHex(crypto.Sha256.sum256(blob));
118
123
  const command = new clientS3.PutObjectCommand({
@@ -124,7 +129,7 @@ class S3BlobStorageConnector {
124
129
  return `blob:${new core.Urn(S3BlobStorageConnector.NAMESPACE, id).toString()}`;
125
130
  }
126
131
  catch (err) {
127
- throw new core.GeneralError(this.CLASS_NAME, "setBlobFailed", undefined, err);
132
+ throw new core.GeneralError(S3BlobStorageConnector.CLASS_NAME, "setBlobFailed", undefined, err);
128
133
  }
129
134
  }
130
135
  /**
@@ -133,10 +138,10 @@ class S3BlobStorageConnector {
133
138
  * @returns The data for the blob if it can be found or undefined.
134
139
  */
135
140
  async get(id) {
136
- core.Urn.guard(this.CLASS_NAME, "id", id);
141
+ core.Urn.guard(S3BlobStorageConnector.CLASS_NAME, "id", id);
137
142
  const urnParsed = core.Urn.fromValidString(id);
138
143
  if (urnParsed.namespaceMethod() !== S3BlobStorageConnector.NAMESPACE) {
139
- throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
144
+ throw new core.GeneralError(S3BlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
140
145
  namespace: S3BlobStorageConnector.NAMESPACE,
141
146
  id
142
147
  });
@@ -152,7 +157,12 @@ class S3BlobStorageConnector {
152
157
  return new Uint8Array(await response.Body.transformToByteArray());
153
158
  }
154
159
  }
155
- catch { }
160
+ catch (err) {
161
+ throw new core.GeneralError(S3BlobStorageConnector.CLASS_NAME, "getBlobFailed", {
162
+ id,
163
+ namespace: S3BlobStorageConnector.NAMESPACE
164
+ }, err);
165
+ }
156
166
  }
157
167
  /**
158
168
  * Remove the blob.
@@ -160,10 +170,10 @@ class S3BlobStorageConnector {
160
170
  * @returns True if the blob was found.
161
171
  */
162
172
  async remove(id) {
163
- core.Urn.guard(this.CLASS_NAME, "id", id);
173
+ core.Urn.guard(S3BlobStorageConnector.CLASS_NAME, "id", id);
164
174
  const urnParsed = core.Urn.fromValidString(id);
165
175
  if (urnParsed.namespaceMethod() !== S3BlobStorageConnector.NAMESPACE) {
166
- throw new core.GeneralError(this.CLASS_NAME, "namespaceMismatch", {
176
+ throw new core.GeneralError(S3BlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
167
177
  namespace: S3BlobStorageConnector.NAMESPACE,
168
178
  id
169
179
  });
@@ -191,7 +201,7 @@ class S3BlobStorageConnector {
191
201
  return true;
192
202
  }
193
203
  catch (err) {
194
- throw new core.GeneralError(this.CLASS_NAME, "removeBlobFailed", { id }, err);
204
+ throw new core.GeneralError(S3BlobStorageConnector.CLASS_NAME, "removeBlobFailed", { id }, err);
195
205
  }
196
206
  }
197
207
  }
@@ -16,7 +16,7 @@ class S3BlobStorageConnector {
16
16
  /**
17
17
  * Runtime name for the class.
18
18
  */
19
- CLASS_NAME = "S3BlobStorageConnector";
19
+ static CLASS_NAME = "S3BlobStorageConnector";
20
20
  /**
21
21
  * The configuration for the connector.
22
22
  * @internal
@@ -32,20 +32,25 @@ class S3BlobStorageConnector {
32
32
  * @param options The options for the connector.
33
33
  */
34
34
  constructor(options) {
35
- Guards.object(this.CLASS_NAME, "options", options);
36
- Guards.object(this.CLASS_NAME, "options.config", options.config);
37
- Guards.stringValue(this.CLASS_NAME, "options.config.region", options.config.region);
38
- Guards.stringValue(this.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
39
- Guards.stringValue(this.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
40
- Guards.stringValue(this.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
35
+ Guards.object(S3BlobStorageConnector.CLASS_NAME, "options", options);
36
+ Guards.object(S3BlobStorageConnector.CLASS_NAME, "options.config", options.config);
37
+ Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.region", options.config.region);
38
+ Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.bucketName", options.config.bucketName);
39
+ options.config.authMode ??= "credentials";
40
+ let credentials;
41
+ if (options.config.authMode === "credentials") {
42
+ Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
43
+ Guards.stringValue(S3BlobStorageConnector.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
44
+ credentials = {
45
+ accessKeyId: options.config.accessKeyId,
46
+ secretAccessKey: options.config.secretAccessKey
47
+ };
48
+ }
41
49
  this._config = options.config;
42
50
  this._s3Client = new S3Client({
43
51
  region: this._config.region,
44
52
  endpoint: this._config.endpoint,
45
- credentials: {
46
- accessKeyId: this._config.accessKeyId,
47
- secretAccessKey: this._config.secretAccessKey
48
- },
53
+ credentials,
49
54
  forcePathStyle: true
50
55
  });
51
56
  }
@@ -59,7 +64,7 @@ class S3BlobStorageConnector {
59
64
  try {
60
65
  await nodeLogging?.log({
61
66
  level: "info",
62
- source: this.CLASS_NAME,
67
+ source: S3BlobStorageConnector.CLASS_NAME,
63
68
  message: "bucketCreating",
64
69
  data: {
65
70
  bucket: this._config.bucketName
@@ -71,7 +76,7 @@ class S3BlobStorageConnector {
71
76
  if (bucketExists) {
72
77
  await nodeLogging?.log({
73
78
  level: "info",
74
- source: this.CLASS_NAME,
79
+ source: S3BlobStorageConnector.CLASS_NAME,
75
80
  message: "bucketExists",
76
81
  data: {
77
82
  bucket: this._config.bucketName
@@ -82,7 +87,7 @@ class S3BlobStorageConnector {
82
87
  await this._s3Client.send(new CreateBucketCommand({ Bucket: this._config.bucketName }));
83
88
  await nodeLogging?.log({
84
89
  level: "info",
85
- source: this.CLASS_NAME,
90
+ source: S3BlobStorageConnector.CLASS_NAME,
86
91
  message: "bucketCreated",
87
92
  data: {
88
93
  bucket: this._config.bucketName
@@ -93,7 +98,7 @@ class S3BlobStorageConnector {
93
98
  catch (err) {
94
99
  await nodeLogging?.log({
95
100
  level: "error",
96
- source: this.CLASS_NAME,
101
+ source: S3BlobStorageConnector.CLASS_NAME,
97
102
  message: "bucketCreateFailed",
98
103
  data: {
99
104
  bucket: this._config.bucketName
@@ -110,7 +115,7 @@ class S3BlobStorageConnector {
110
115
  * @returns The id of the stored blob in urn format.
111
116
  */
112
117
  async set(blob) {
113
- Guards.uint8Array(this.CLASS_NAME, "blob", blob);
118
+ Guards.uint8Array(S3BlobStorageConnector.CLASS_NAME, "blob", blob);
114
119
  try {
115
120
  const id = Converter.bytesToHex(Sha256.sum256(blob));
116
121
  const command = new PutObjectCommand({
@@ -122,7 +127,7 @@ class S3BlobStorageConnector {
122
127
  return `blob:${new Urn(S3BlobStorageConnector.NAMESPACE, id).toString()}`;
123
128
  }
124
129
  catch (err) {
125
- throw new GeneralError(this.CLASS_NAME, "setBlobFailed", undefined, err);
130
+ throw new GeneralError(S3BlobStorageConnector.CLASS_NAME, "setBlobFailed", undefined, err);
126
131
  }
127
132
  }
128
133
  /**
@@ -131,10 +136,10 @@ class S3BlobStorageConnector {
131
136
  * @returns The data for the blob if it can be found or undefined.
132
137
  */
133
138
  async get(id) {
134
- Urn.guard(this.CLASS_NAME, "id", id);
139
+ Urn.guard(S3BlobStorageConnector.CLASS_NAME, "id", id);
135
140
  const urnParsed = Urn.fromValidString(id);
136
141
  if (urnParsed.namespaceMethod() !== S3BlobStorageConnector.NAMESPACE) {
137
- throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
142
+ throw new GeneralError(S3BlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
138
143
  namespace: S3BlobStorageConnector.NAMESPACE,
139
144
  id
140
145
  });
@@ -150,7 +155,12 @@ class S3BlobStorageConnector {
150
155
  return new Uint8Array(await response.Body.transformToByteArray());
151
156
  }
152
157
  }
153
- catch { }
158
+ catch (err) {
159
+ throw new GeneralError(S3BlobStorageConnector.CLASS_NAME, "getBlobFailed", {
160
+ id,
161
+ namespace: S3BlobStorageConnector.NAMESPACE
162
+ }, err);
163
+ }
154
164
  }
155
165
  /**
156
166
  * Remove the blob.
@@ -158,10 +168,10 @@ class S3BlobStorageConnector {
158
168
  * @returns True if the blob was found.
159
169
  */
160
170
  async remove(id) {
161
- Urn.guard(this.CLASS_NAME, "id", id);
171
+ Urn.guard(S3BlobStorageConnector.CLASS_NAME, "id", id);
162
172
  const urnParsed = Urn.fromValidString(id);
163
173
  if (urnParsed.namespaceMethod() !== S3BlobStorageConnector.NAMESPACE) {
164
- throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
174
+ throw new GeneralError(S3BlobStorageConnector.CLASS_NAME, "namespaceMismatch", {
165
175
  namespace: S3BlobStorageConnector.NAMESPACE,
166
176
  id
167
177
  });
@@ -189,7 +199,7 @@ class S3BlobStorageConnector {
189
199
  return true;
190
200
  }
191
201
  catch (err) {
192
- throw new GeneralError(this.CLASS_NAME, "removeBlobFailed", { id }, err);
202
+ throw new GeneralError(S3BlobStorageConnector.CLASS_NAME, "removeBlobFailed", { id }, err);
193
203
  }
194
204
  }
195
205
  }
@@ -10,14 +10,21 @@ export interface IS3BlobStorageConnectorConfig {
10
10
  * The S3 bucket name.
11
11
  */
12
12
  bucketName: string;
13
+ /**
14
+ * The authentication mode.
15
+ * - "credentials": Use access key ID and secret access key.
16
+ * - "pod": Use IAM role attached to the pod (e.g., in EKS).
17
+ * @default credentials
18
+ */
19
+ authMode?: "credentials" | "pod";
13
20
  /**
14
21
  * The AWS access key ID.
15
22
  */
16
- accessKeyId: string;
23
+ accessKeyId?: string;
17
24
  /**
18
25
  * The AWS secret access key.
19
26
  */
20
- secretAccessKey: string;
27
+ secretAccessKey?: string;
21
28
  /**
22
29
  * Optional endpoint for S3-compatible storage (e.g., MinIO).
23
30
  */
@@ -12,7 +12,7 @@ export declare class S3BlobStorageConnector implements IBlobStorageConnector {
12
12
  /**
13
13
  * Runtime name for the class.
14
14
  */
15
- readonly CLASS_NAME: string;
15
+ static readonly CLASS_NAME: string;
16
16
  /**
17
17
  * Create a new instance of S3BlobStorageConnector.
18
18
  * @param options The options for the connector.
package/docs/changelog.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @twin.org/blob-storage-connector-aws-s3 - Changelog
2
2
 
3
+ ## [0.0.2-next.5](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-aws-s3-v0.0.2-next.4...blob-storage-connector-aws-s3-v0.0.2-next.5) (2025-10-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * add validate-locales ([f20fcec](https://github.com/twinfoundation/blob-storage/commit/f20fceced91e39a0c9edb770b2e43ce944c92f3c))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/blob-storage-models bumped from 0.0.2-next.4 to 0.0.2-next.5
16
+
17
+ ## [0.0.2-next.4](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-aws-s3-v0.0.2-next.3...blob-storage-connector-aws-s3-v0.0.2-next.4) (2025-10-02)
18
+
19
+
20
+ ### Features
21
+
22
+ * add AWS pod authentication mode ([c34b11c](https://github.com/twinfoundation/blob-storage/commit/c34b11cb32d3310a9e59840341a2b0b4221bc780))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @twin.org/blob-storage-models bumped from 0.0.2-next.3 to 0.0.2-next.4
30
+
3
31
  ## [0.0.2-next.3](https://github.com/twinfoundation/blob-storage/compare/blob-storage-connector-aws-s3-v0.0.2-next.2...blob-storage-connector-aws-s3-v0.0.2-next.3) (2025-08-29)
4
32
 
5
33
 
@@ -39,14 +39,10 @@ The namespace for the items.
39
39
 
40
40
  ### CLASS\_NAME
41
41
 
42
- > `readonly` **CLASS\_NAME**: `string`
42
+ > `readonly` `static` **CLASS\_NAME**: `string`
43
43
 
44
44
  Runtime name for the class.
45
45
 
46
- #### Implementation of
47
-
48
- `IBlobStorageConnector.CLASS_NAME`
49
-
50
46
  ## Methods
51
47
 
52
48
  ### bootstrap()
@@ -20,17 +20,33 @@ The S3 bucket name.
20
20
 
21
21
  ***
22
22
 
23
- ### accessKeyId
23
+ ### authMode?
24
24
 
25
- > **accessKeyId**: `string`
25
+ > `optional` **authMode**: `"credentials"` \| `"pod"`
26
+
27
+ The authentication mode.
28
+ - "credentials": Use access key ID and secret access key.
29
+ - "pod": Use IAM role attached to the pod (e.g., in EKS).
30
+
31
+ #### Default
32
+
33
+ ```ts
34
+ credentials
35
+ ```
36
+
37
+ ***
38
+
39
+ ### accessKeyId?
40
+
41
+ > `optional` **accessKeyId**: `string`
26
42
 
27
43
  The AWS access key ID.
28
44
 
29
45
  ***
30
46
 
31
- ### secretAccessKey
47
+ ### secretAccessKey?
32
48
 
33
- > **secretAccessKey**: `string`
49
+ > `optional` **secretAccessKey**: `string`
34
50
 
35
51
  The AWS secret access key.
36
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/blob-storage-connector-aws-s3",
3
- "version": "0.0.2-next.3",
3
+ "version": "0.0.2-next.5",
4
4
  "description": "Blob Storage connector implementation using AWS S3",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,8 +14,8 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@aws-sdk/client-s3": "3.878.0",
18
- "@twin.org/blob-storage-models": "0.0.2-next.3",
17
+ "@aws-sdk/client-s3": "3.906.0",
18
+ "@twin.org/blob-storage-models": "0.0.2-next.5",
19
19
  "@twin.org/core": "next",
20
20
  "@twin.org/crypto": "next",
21
21
  "@twin.org/logging-models": "next",
@@ -38,5 +38,24 @@
38
38
  "dist/types",
39
39
  "locales",
40
40
  "docs"
41
- ]
41
+ ],
42
+ "keywords": [
43
+ "twin",
44
+ "trade",
45
+ "iota",
46
+ "framework",
47
+ "blockchain",
48
+ "blob-storage",
49
+ "blob",
50
+ "storage",
51
+ "files",
52
+ "binary",
53
+ "connector",
54
+ "adapter",
55
+ "integration"
56
+ ],
57
+ "bugs": {
58
+ "url": "git+https://github.com/twinfoundation/blob-storage/issues"
59
+ },
60
+ "homepage": "https://twindev.org"
42
61
  }