@brightchain/s3-store 0.24.0
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 +18 -0
- package/package.json +17 -0
- package/src/index.d.ts +3 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +10 -0
- package/src/index.js.map +1 -0
- package/src/lib/factories/s3BlockStoreFactory.d.ts +2 -0
- package/src/lib/factories/s3BlockStoreFactory.d.ts.map +1 -0
- package/src/lib/factories/s3BlockStoreFactory.js +16 -0
- package/src/lib/factories/s3BlockStoreFactory.js.map +1 -0
- package/src/lib/stores/s3BlockStore.d.ts +27 -0
- package/src/lib/stores/s3BlockStore.d.ts.map +1 -0
- package/src/lib/stores/s3BlockStore.js +172 -0
- package/src/lib/stores/s3BlockStore.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @brightchain/s3-store
|
|
2
|
+
|
|
3
|
+
Amazon S3 block store driver for BrightChain. Implements `IBlockStore` and `IPooledBlockStore` backed by S3.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import '@brightchain/s3-store'; // registers factory
|
|
9
|
+
import { BlockStoreFactory } from '@brightchain/brightchain-lib';
|
|
10
|
+
|
|
11
|
+
const store = BlockStoreFactory.createS3Store({
|
|
12
|
+
region: 'us-east-1',
|
|
13
|
+
containerOrBucketName: 'my-brightchain-bucket',
|
|
14
|
+
blockSize: BlockSize.Small,
|
|
15
|
+
accessKeyId: '...',
|
|
16
|
+
secretAccessKey: '...',
|
|
17
|
+
});
|
|
18
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brightchain/s3-store",
|
|
3
|
+
"version": "0.24.0",
|
|
4
|
+
"main": "./src/index.js",
|
|
5
|
+
"types": "./src/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"src",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@aws-sdk/client-s3": "^3.700.0",
|
|
12
|
+
"@brightchain/brightchain-api-lib": "^0.24.0",
|
|
13
|
+
"@brightchain/brightchain-lib": "^0.24.0",
|
|
14
|
+
"tslib": "^2.3.0"
|
|
15
|
+
},
|
|
16
|
+
"type": "commonjs"
|
|
17
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../brightchain-s3-store/src/index.ts"],"names":[],"mappings":"AAEA,OAAO,qCAAqC,CAAC;AAG7C,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3BlockStore = void 0;
|
|
4
|
+
// Import factory registration side effect — registers S3BlockStore
|
|
5
|
+
// with BlockStoreFactory at import time.
|
|
6
|
+
require("./lib/factories/s3BlockStoreFactory");
|
|
7
|
+
// Export public API
|
|
8
|
+
var s3BlockStore_1 = require("./lib/stores/s3BlockStore");
|
|
9
|
+
Object.defineProperty(exports, "S3BlockStore", { enumerable: true, get: function () { return s3BlockStore_1.S3BlockStore; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../brightchain-s3-store/src/index.ts"],"names":[],"mappings":";;;AAAA,mEAAmE;AACnE,yCAAyC;AACzC,+CAA6C;AAE7C,oBAAoB;AACpB,0DAA8E;AAArE,4GAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3BlockStoreFactory.d.ts","sourceRoot":"","sources":["../../../../../brightchain-s3-store/src/lib/factories/s3BlockStoreFactory.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* S3 factory registration side-effect module.
|
|
5
|
+
*
|
|
6
|
+
* Importing this module registers the S3BlockStore factory with
|
|
7
|
+
* BlockStoreFactory so that `BlockStoreFactory.createS3Store(config)`
|
|
8
|
+
* returns an S3BlockStore instance.
|
|
9
|
+
*
|
|
10
|
+
* This module is imported by the library barrel file (src/index.ts) so
|
|
11
|
+
* registration happens automatically when the library is imported.
|
|
12
|
+
*/
|
|
13
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
14
|
+
const s3BlockStore_1 = require("../stores/s3BlockStore");
|
|
15
|
+
brightchain_lib_1.BlockStoreFactory.registerS3StoreFactory((config) => new s3BlockStore_1.S3BlockStore(config));
|
|
16
|
+
//# sourceMappingURL=s3BlockStoreFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3BlockStoreFactory.js","sourceRoot":"","sources":["../../../../../brightchain-s3-store/src/lib/factories/s3BlockStoreFactory.ts"],"names":[],"mappings":";;AAAA;;;;;;;;;GASG;AACH,kEAGsC;AACtC,yDAGgC;AAEhC,mCAAiB,CAAC,sBAAsB,CACtC,CAAC,MAA8B,EAAE,EAAE,CACjC,IAAI,2BAAY,CAAC,MAA6B,CAAC,CAClD,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CloudBlockStoreBase } from '@brightchain/brightchain-api-lib';
|
|
2
|
+
import { ICloudBlockStoreConfig } from '@brightchain/brightchain-lib';
|
|
3
|
+
/**
|
|
4
|
+
* S3-specific configuration extending the shared cloud config.
|
|
5
|
+
*/
|
|
6
|
+
export interface IS3BlockStoreConfig extends ICloudBlockStoreConfig {
|
|
7
|
+
/** AWS access key ID (used with secretAccessKey) */
|
|
8
|
+
accessKeyId?: string;
|
|
9
|
+
/** AWS secret access key (used with accessKeyId) */
|
|
10
|
+
secretAccessKey?: string;
|
|
11
|
+
/** Whether to use IAM role / environment credential chain */
|
|
12
|
+
useIamRole?: boolean;
|
|
13
|
+
/** Custom endpoint URL for S3-compatible services (MinIO, LocalStack) */
|
|
14
|
+
endpoint?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class S3BlockStore extends CloudBlockStoreBase {
|
|
17
|
+
private readonly s3Client;
|
|
18
|
+
private readonly bucketName;
|
|
19
|
+
constructor(config: IS3BlockStoreConfig, indexTtlMs?: number, listPageSize?: number);
|
|
20
|
+
protected uploadObject(key: string, data: Uint8Array): Promise<void>;
|
|
21
|
+
protected downloadObject(key: string): Promise<Uint8Array>;
|
|
22
|
+
protected deleteObject(key: string): Promise<void>;
|
|
23
|
+
protected objectExists(key: string): Promise<boolean>;
|
|
24
|
+
protected listObjects(prefix: string, maxResults?: number): Promise<string[]>;
|
|
25
|
+
protected isTransientError(error: unknown): boolean;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=s3BlockStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3BlockStore.d.ts","sourceRoot":"","sources":["../../../../../brightchain-s3-store/src/lib/stores/s3BlockStore.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,sBAAsB,EAGvB,MAAM,8BAA8B,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,qBAAa,YAAa,SAAQ,mBAAmB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGlC,MAAM,EAAE,mBAAmB,EAC3B,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM;cAoDP,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;cAU1D,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;cAoBhD,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cASxC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;cAoB3C,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC;IAiCpB,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAuCpD"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3BlockStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* S3BlockStore - Amazon S3 implementation of CloudBlockStoreBase.
|
|
6
|
+
*
|
|
7
|
+
* Implements the 6 abstract I/O primitives using the @aws-sdk/client-s3 SDK.
|
|
8
|
+
* Authentication priority: explicit credentials → IAM role / environment credential chain.
|
|
9
|
+
*
|
|
10
|
+
* @see CloudBlockStoreBase for shared cloud store logic
|
|
11
|
+
*/
|
|
12
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
13
|
+
const brightchain_api_lib_1 = require("@brightchain/brightchain-api-lib");
|
|
14
|
+
const brightchain_lib_1 = require("@brightchain/brightchain-lib");
|
|
15
|
+
/** HTTP status codes considered transient for S3 operations */
|
|
16
|
+
const TRANSIENT_HTTP_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
|
|
17
|
+
/** Error names considered transient */
|
|
18
|
+
const TRANSIENT_ERROR_NAMES = new Set(['TimeoutError', 'NetworkingError']);
|
|
19
|
+
/** Network-level error codes considered transient */
|
|
20
|
+
const TRANSIENT_ERROR_CODES = new Set([
|
|
21
|
+
'ETIMEDOUT',
|
|
22
|
+
'ECONNRESET',
|
|
23
|
+
'ECONNREFUSED',
|
|
24
|
+
'EPIPE',
|
|
25
|
+
]);
|
|
26
|
+
/** HTTP status codes indicating authentication failures */
|
|
27
|
+
const AUTH_HTTP_STATUS_CODES = new Set([401, 403]);
|
|
28
|
+
class S3BlockStore extends brightchain_api_lib_1.CloudBlockStoreBase {
|
|
29
|
+
s3Client;
|
|
30
|
+
bucketName;
|
|
31
|
+
constructor(config, indexTtlMs, listPageSize) {
|
|
32
|
+
super(config, indexTtlMs, listPageSize);
|
|
33
|
+
this.bucketName = config.containerOrBucketName;
|
|
34
|
+
const clientConfig = {
|
|
35
|
+
region: config.region || 'us-east-1',
|
|
36
|
+
};
|
|
37
|
+
if (config.endpoint) {
|
|
38
|
+
clientConfig['endpoint'] = config.endpoint;
|
|
39
|
+
clientConfig['forcePathStyle'] = true;
|
|
40
|
+
}
|
|
41
|
+
if (config.accessKeyId && config.secretAccessKey) {
|
|
42
|
+
// Priority 1: Explicit credentials
|
|
43
|
+
clientConfig['credentials'] = {
|
|
44
|
+
accessKeyId: config.accessKeyId,
|
|
45
|
+
secretAccessKey: config.secretAccessKey,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else if (config.accessKeyId && !config.secretAccessKey) {
|
|
49
|
+
// Partial credentials — missing secret key
|
|
50
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.CloudAuthenticationFailed, undefined, {
|
|
51
|
+
message: 'Incomplete S3 credentials: accessKeyId provided without secretAccessKey.',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else if (!config.useIamRole) {
|
|
55
|
+
// No explicit credentials and not using IAM role — error
|
|
56
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.CloudAuthenticationFailed, undefined, {
|
|
57
|
+
message: 'No valid S3 authentication method provided. ' +
|
|
58
|
+
'Supply accessKeyId + secretAccessKey, ' +
|
|
59
|
+
'or set useIamRole to true for IAM role / environment credential chain.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Priority 2: IAM role / environment credential chain (SDK default behavior)
|
|
63
|
+
this.s3Client = new client_s3_1.S3Client(clientConfig);
|
|
64
|
+
}
|
|
65
|
+
// =========================================================================
|
|
66
|
+
// Abstract primitive implementations
|
|
67
|
+
// =========================================================================
|
|
68
|
+
async uploadObject(key, data) {
|
|
69
|
+
await this.s3Client.send(new client_s3_1.PutObjectCommand({
|
|
70
|
+
Bucket: this.bucketName,
|
|
71
|
+
Key: key,
|
|
72
|
+
Body: data,
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
async downloadObject(key) {
|
|
76
|
+
const response = await this.s3Client.send(new client_s3_1.GetObjectCommand({
|
|
77
|
+
Bucket: this.bucketName,
|
|
78
|
+
Key: key,
|
|
79
|
+
}));
|
|
80
|
+
if (!response.Body) {
|
|
81
|
+
throw new brightchain_lib_1.StoreError(brightchain_lib_1.StoreErrorType.CloudOperationFailed, undefined, {
|
|
82
|
+
operation: 'downloadObject',
|
|
83
|
+
blockChecksum: key,
|
|
84
|
+
originalError: 'No body in S3 GetObject response',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const byteArray = await response.Body.transformToByteArray();
|
|
88
|
+
return new Uint8Array(byteArray);
|
|
89
|
+
}
|
|
90
|
+
async deleteObject(key) {
|
|
91
|
+
await this.s3Client.send(new client_s3_1.DeleteObjectCommand({
|
|
92
|
+
Bucket: this.bucketName,
|
|
93
|
+
Key: key,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
async objectExists(key) {
|
|
97
|
+
try {
|
|
98
|
+
await this.s3Client.send(new client_s3_1.HeadObjectCommand({
|
|
99
|
+
Bucket: this.bucketName,
|
|
100
|
+
Key: key,
|
|
101
|
+
}));
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (error instanceof client_s3_1.S3ServiceException &&
|
|
106
|
+
(error.$metadata?.httpStatusCode === 404 || error.name === 'NotFound')) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async listObjects(prefix, maxResults) {
|
|
113
|
+
const names = [];
|
|
114
|
+
let continuationToken;
|
|
115
|
+
do {
|
|
116
|
+
const response = await this.s3Client.send(new client_s3_1.ListObjectsV2Command({
|
|
117
|
+
Bucket: this.bucketName,
|
|
118
|
+
Prefix: prefix,
|
|
119
|
+
MaxKeys: maxResults !== undefined ? maxResults - names.length : 1000,
|
|
120
|
+
ContinuationToken: continuationToken,
|
|
121
|
+
}));
|
|
122
|
+
if (response.Contents) {
|
|
123
|
+
for (const obj of response.Contents) {
|
|
124
|
+
if (obj.Key) {
|
|
125
|
+
names.push(obj.Key);
|
|
126
|
+
if (maxResults !== undefined && names.length >= maxResults) {
|
|
127
|
+
return names;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
continuationToken = response.IsTruncated
|
|
133
|
+
? response.NextContinuationToken
|
|
134
|
+
: undefined;
|
|
135
|
+
} while (continuationToken);
|
|
136
|
+
return names;
|
|
137
|
+
}
|
|
138
|
+
isTransientError(error) {
|
|
139
|
+
// Check AWS SDK $retryable hint
|
|
140
|
+
if (error &&
|
|
141
|
+
typeof error === 'object' &&
|
|
142
|
+
'$retryable' in error &&
|
|
143
|
+
error['$retryable']) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
if (error instanceof client_s3_1.S3ServiceException) {
|
|
147
|
+
// Authentication errors are never transient
|
|
148
|
+
const httpStatus = error.$metadata?.httpStatusCode;
|
|
149
|
+
if (httpStatus && AUTH_HTTP_STATUS_CODES.has(httpStatus)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
// Check HTTP status codes for transient errors
|
|
153
|
+
if (httpStatus && TRANSIENT_HTTP_STATUS_CODES.has(httpStatus)) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Check error name for transient network errors
|
|
158
|
+
if (error instanceof Error) {
|
|
159
|
+
if (TRANSIENT_ERROR_NAMES.has(error.name)) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
// Check for generic error objects with transient network codes
|
|
163
|
+
const code = error.code;
|
|
164
|
+
if (code && TRANSIENT_ERROR_CODES.has(code)) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.S3BlockStore = S3BlockStore;
|
|
172
|
+
//# sourceMappingURL=s3BlockStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3BlockStore.js","sourceRoot":"","sources":["../../../../../brightchain-s3-store/src/lib/stores/s3BlockStore.ts"],"names":[],"mappings":"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"}
|