s3mini 0.2.0 → 0.3.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/dist/s3mini.d.ts +229 -0
- package/dist/s3mini.js +391 -39
- 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 +1 -1
- package/src/S3.ts +373 -41
- package/src/utils.ts +35 -13
package/src/utils.ts
CHANGED
|
@@ -17,6 +17,10 @@ export const hash = (content: string | Buffer): string => {
|
|
|
17
17
|
return _createHash('sha256').update(content).digest('hex') as string;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
export const md5base64 = (data: string | Buffer): string => {
|
|
21
|
+
return _createHash('md5').update(data).digest('base64') as string;
|
|
22
|
+
};
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* Compute HMAC-SHA-256 of arbitrary data and return a hex string.
|
|
22
26
|
* @param {string|Buffer} key – secret key
|
|
@@ -53,6 +57,20 @@ const entityMap = {
|
|
|
53
57
|
'&': '&',
|
|
54
58
|
} as const;
|
|
55
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Escape special characters for XML
|
|
62
|
+
* @param value String to escape
|
|
63
|
+
* @returns XML-escaped string
|
|
64
|
+
*/
|
|
65
|
+
export const escapeXml = (value: string): string => {
|
|
66
|
+
return value
|
|
67
|
+
.replace(/&/g, '&')
|
|
68
|
+
.replace(/</g, '<')
|
|
69
|
+
.replace(/>/g, '>')
|
|
70
|
+
.replace(/"/g, '"')
|
|
71
|
+
.replace(/'/g, ''');
|
|
72
|
+
};
|
|
73
|
+
|
|
56
74
|
const unescapeXml = (value: string): string =>
|
|
57
75
|
value.replace(/&(quot|apos|lt|gt|amp);/g, m => entityMap[m as keyof typeof entityMap] ?? m);
|
|
58
76
|
|
|
@@ -62,31 +80,35 @@ const unescapeXml = (value: string): string =>
|
|
|
62
80
|
* @param input raw XML string
|
|
63
81
|
* @returns string for leaf nodes, otherwise a map of children
|
|
64
82
|
*/
|
|
83
|
+
|
|
65
84
|
export const parseXml = (input: string): XmlValue => {
|
|
66
|
-
const
|
|
85
|
+
const xmlContent = input.replace(/<\?xml[^?]*\?>\s*/, '');
|
|
86
|
+
const RE_TAG = /<([A-Za-z_][\w\-.]*)[^>]*>([\s\S]*?)<\/\1>/gm;
|
|
67
87
|
const result: XmlMap = {}; // strong type, no `any`
|
|
68
88
|
let match: RegExpExecArray | null;
|
|
69
89
|
|
|
70
|
-
while ((match = RE_TAG.exec(
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const node: XmlValue =
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
while ((match = RE_TAG.exec(xmlContent)) !== null) {
|
|
91
|
+
const tagName = match[1];
|
|
92
|
+
const innerContent = match[2];
|
|
93
|
+
const node: XmlValue = innerContent ? parseXml(innerContent) : unescapeXml(innerContent?.trim() || '');
|
|
94
|
+
if (!tagName) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const current = result[tagName];
|
|
76
98
|
if (current === undefined) {
|
|
77
|
-
//
|
|
78
|
-
result[
|
|
99
|
+
// First occurrence
|
|
100
|
+
result[tagName] = node;
|
|
79
101
|
} else if (Array.isArray(current)) {
|
|
80
|
-
//
|
|
102
|
+
// Already an array
|
|
81
103
|
current.push(node);
|
|
82
104
|
} else {
|
|
83
|
-
//
|
|
84
|
-
result[
|
|
105
|
+
// Promote to array on the second occurrence
|
|
106
|
+
result[tagName] = [current, node];
|
|
85
107
|
}
|
|
86
108
|
}
|
|
87
109
|
|
|
88
110
|
// No child tags? — return the text, after entity decode
|
|
89
|
-
return Object.keys(result).length > 0 ? result : unescapeXml(
|
|
111
|
+
return Object.keys(result).length > 0 ? result : unescapeXml(xmlContent.trim());
|
|
90
112
|
};
|
|
91
113
|
|
|
92
114
|
/**
|