s3mini 0.2.0 → 0.4.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 +14 -3
- package/dist/s3mini.d.ts +272 -15
- package/dist/s3mini.js +474 -75
- package/dist/s3mini.js.map +1 -1
- package/dist/s3mini.min.js +1 -1
- package/dist/s3mini.min.js.map +1 -1
- package/package.json +18 -18
- package/src/S3.ts +490 -77
- package/src/consts.ts +3 -3
- package/src/index.ts +3 -3
- package/src/types.ts +14 -0
- package/src/utils.ts +35 -14
package/src/consts.ts
CHANGED
|
@@ -15,9 +15,9 @@ export const DEFAULT_REQUEST_SIZE_IN_BYTES = 8 * 1024 * 1024;
|
|
|
15
15
|
export const HEADER_AMZ_CONTENT_SHA256 = 'x-amz-content-sha256';
|
|
16
16
|
export const HEADER_AMZ_DATE = 'x-amz-date';
|
|
17
17
|
export const HEADER_HOST = 'host';
|
|
18
|
-
export const HEADER_AUTHORIZATION = '
|
|
19
|
-
export const HEADER_CONTENT_TYPE = '
|
|
20
|
-
export const HEADER_CONTENT_LENGTH = '
|
|
18
|
+
export const HEADER_AUTHORIZATION = 'authorization';
|
|
19
|
+
export const HEADER_CONTENT_TYPE = 'content-type';
|
|
20
|
+
export const HEADER_CONTENT_LENGTH = 'content-length';
|
|
21
21
|
export const HEADER_ETAG = 'etag';
|
|
22
22
|
export const HEADER_LAST_MODIFIED = 'last-modified';
|
|
23
23
|
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import { s3mini } from './S3.js';
|
|
3
|
+
import { S3mini, s3mini } from './S3.js';
|
|
4
4
|
import { sanitizeETag, runInBatches } from './utils.js';
|
|
5
5
|
|
|
6
6
|
// Export the S3 class as default export and named export
|
|
7
|
-
export { s3mini, sanitizeETag, runInBatches };
|
|
8
|
-
export default
|
|
7
|
+
export { S3mini, s3mini, sanitizeETag, runInBatches };
|
|
8
|
+
export default S3mini;
|
|
9
9
|
|
|
10
10
|
// Re-export types
|
|
11
11
|
export type {
|
package/src/types.ts
CHANGED
|
@@ -8,6 +8,12 @@ export interface S3Config {
|
|
|
8
8
|
logger?: Logger;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export interface SSECHeaders {
|
|
12
|
+
'x-amz-server-side-encryption-customer-algorithm': string;
|
|
13
|
+
'x-amz-server-side-encryption-customer-key': string;
|
|
14
|
+
'x-amz-server-side-encryption-customer-key-md5': string;
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
export interface Crypto {
|
|
12
18
|
createHmac: (
|
|
13
19
|
algorithm: string,
|
|
@@ -33,6 +39,14 @@ export interface UploadPart {
|
|
|
33
39
|
etag: string;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
export interface ListObject {
|
|
43
|
+
Key: string;
|
|
44
|
+
Size: number;
|
|
45
|
+
LastModified: Date;
|
|
46
|
+
ETag: string;
|
|
47
|
+
StorageClass: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
36
50
|
export interface CompleteMultipartUploadResult {
|
|
37
51
|
location: string;
|
|
38
52
|
bucket: string;
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
import type { Crypto, XmlValue, XmlMap, ListBucketResponse, ErrorWithCode } from './types.js';
|
|
4
3
|
declare const crypto: Crypto;
|
|
5
4
|
|
|
@@ -17,6 +16,10 @@ export const hash = (content: string | Buffer): string => {
|
|
|
17
16
|
return _createHash('sha256').update(content).digest('hex') as string;
|
|
18
17
|
};
|
|
19
18
|
|
|
19
|
+
export const md5base64 = (data: string | Buffer): string => {
|
|
20
|
+
return _createHash('md5').update(data).digest('base64') as string;
|
|
21
|
+
};
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Compute HMAC-SHA-256 of arbitrary data and return a hex string.
|
|
22
25
|
* @param {string|Buffer} key – secret key
|
|
@@ -53,6 +56,20 @@ const entityMap = {
|
|
|
53
56
|
'&': '&',
|
|
54
57
|
} as const;
|
|
55
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Escape special characters for XML
|
|
61
|
+
* @param value String to escape
|
|
62
|
+
* @returns XML-escaped string
|
|
63
|
+
*/
|
|
64
|
+
export const escapeXml = (value: string): string => {
|
|
65
|
+
return value
|
|
66
|
+
.replace(/&/g, '&')
|
|
67
|
+
.replace(/</g, '<')
|
|
68
|
+
.replace(/>/g, '>')
|
|
69
|
+
.replace(/"/g, '"')
|
|
70
|
+
.replace(/'/g, ''');
|
|
71
|
+
};
|
|
72
|
+
|
|
56
73
|
const unescapeXml = (value: string): string =>
|
|
57
74
|
value.replace(/&(quot|apos|lt|gt|amp);/g, m => entityMap[m as keyof typeof entityMap] ?? m);
|
|
58
75
|
|
|
@@ -62,31 +79,35 @@ const unescapeXml = (value: string): string =>
|
|
|
62
79
|
* @param input raw XML string
|
|
63
80
|
* @returns string for leaf nodes, otherwise a map of children
|
|
64
81
|
*/
|
|
82
|
+
|
|
65
83
|
export const parseXml = (input: string): XmlValue => {
|
|
66
|
-
const
|
|
84
|
+
const xmlContent = input.replace(/<\?xml[^?]*\?>\s*/, '');
|
|
85
|
+
const RE_TAG = /<([A-Za-z_][\w\-.]*)[^>]*>([\s\S]*?)<\/\1>/gm;
|
|
67
86
|
const result: XmlMap = {}; // strong type, no `any`
|
|
68
87
|
let match: RegExpExecArray | null;
|
|
69
88
|
|
|
70
|
-
while ((match = RE_TAG.exec(
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const node: XmlValue =
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
while ((match = RE_TAG.exec(xmlContent)) !== null) {
|
|
90
|
+
const tagName = match[1];
|
|
91
|
+
const innerContent = match[2];
|
|
92
|
+
const node: XmlValue = innerContent ? parseXml(innerContent) : unescapeXml(innerContent?.trim() || '');
|
|
93
|
+
if (!tagName) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const current = result[tagName];
|
|
76
97
|
if (current === undefined) {
|
|
77
|
-
//
|
|
78
|
-
result[
|
|
98
|
+
// First occurrence
|
|
99
|
+
result[tagName] = node;
|
|
79
100
|
} else if (Array.isArray(current)) {
|
|
80
|
-
//
|
|
101
|
+
// Already an array
|
|
81
102
|
current.push(node);
|
|
82
103
|
} else {
|
|
83
|
-
//
|
|
84
|
-
result[
|
|
104
|
+
// Promote to array on the second occurrence
|
|
105
|
+
result[tagName] = [current, node];
|
|
85
106
|
}
|
|
86
107
|
}
|
|
87
108
|
|
|
88
109
|
// No child tags? — return the text, after entity decode
|
|
89
|
-
return Object.keys(result).length > 0 ? result : unescapeXml(
|
|
110
|
+
return Object.keys(result).length > 0 ? result : unescapeXml(xmlContent.trim());
|
|
90
111
|
};
|
|
91
112
|
|
|
92
113
|
/**
|