-
Notifications
You must be signed in to change notification settings - Fork 332
/
Copy pathutils.ts
166 lines (148 loc) · 4.83 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import { createHash, createHmac } from "crypto";
import rimraf = require("rimraf");
import { parse } from "url";
import { promisify } from "util";
// LokiFsStructuredAdapter
// tslint:disable-next-line:no-var-requires
export const lfsa = require("lokijs/src/loki-fs-structured-adapter.js");
export const rimrafAsync = promisify(rimraf);
export function minDate(date1: Date, date2: Date): Date {
return date1 > date2 ? date2 : date1;
}
// Blob Snapshot is has 7 digital for Milliseconds, but Datatime has Milliseconds with 3 digital. So need convert.
export function convertDateTimeStringMsTo7Digital(
dateTimeString: string
): string {
return dateTimeString.replace("Z", "0000Z");
}
export function convertRawHeadersToMetadata(
rawHeaders: string[] = []
): { [propertyName: string]: string } | undefined {
const metadataPrefix = "x-ms-meta-";
const res: { [propertyName: string]: string } = {};
let isEmpty = true;
for (let i = 0; i < rawHeaders.length; i = i + 2) {
const header = rawHeaders[i];
if (
header.toLowerCase().startsWith(metadataPrefix) &&
header.length > metadataPrefix.length
) {
const key = header.substr(metadataPrefix.length);
let value = rawHeaders[i + 1] || "";
if (res[key] !== undefined) {
value = `${res[key]},${value}`;
}
res[key] = value;
isEmpty = false;
continue;
}
}
return isEmpty ? undefined : res;
}
export function newEtag(): string {
// Etag should match ^"0x[A-F0-9]{15,}"$
// Date().getTime().toString(16) only has 11 digital
// so multiply a number between 70000-100000, can get a 16 based 15+ digital number
return (
'"0x' +
(new Date().getTime() * Math.round(Math.random() * 30000 + 70000))
.toString(16)
.toUpperCase() +
'"'
);
}
/**
* Generates a hash signature for an HTTP request or for a SAS.
*
* @param {string} stringToSign
* @param {key} key
* @returns {string}
*/
export function computeHMACSHA256(stringToSign: string, key: Buffer): string {
return createHmac("sha256", key)
.update(stringToSign, "utf8")
.digest("base64");
}
/**
* Rounds a date off to seconds.
*
* @export
* @param {Date} date
* @param {boolean} [withMilliseconds=true] If true, YYYY-MM-DDThh:mm:ss.fffffffZ will be returned;
* If false, YYYY-MM-DDThh:mm:ssZ will be returned.
* @returns {string} Date string in ISO8061 format, with or without 7 milliseconds component
*/
export function truncatedISO8061Date(
date: Date,
withMilliseconds: boolean = true,
hrtimePrecision: boolean = false
): string {
// Date.toISOString() will return like "2018-10-29T06:34:36.139Z"
const dateString = date.toISOString();
// some clients are very fast, and require more than ms precision available in JS
// This is an approximation based on the hrtime function in nodejs.
// The nanosecond value is appended to the millisecond value from the datetime
// object which gives us a good enough difference in the case of faster high
// volume transactions
if (hrtimePrecision) {
return (
dateString.substring(0, dateString.length - 1) +
process.hrtime()[1].toString().padStart(4, "0").slice(0, 4) +
"Z"
);
}
return withMilliseconds
? dateString.substring(0, dateString.length - 1) + "0000" + "Z"
: dateString.substring(0, dateString.length - 5) + "Z";
}
/**
* Get URL query key value pairs from an URL string.
*
* @export
* @param {string} url
* @returns {{[key: string]: string}}
*/
export function getURLQueries(url: string): { [key: string]: string } {
let queryString = parse(url).query;
if (!queryString) {
return {};
}
queryString = queryString.trim();
queryString = queryString.startsWith("?")
? queryString.substr(1)
: queryString;
let querySubStrings: string[] = queryString.split("&");
querySubStrings = querySubStrings.filter((value: string) => {
const indexOfEqual = value.indexOf("=");
const lastIndexOfEqual = value.lastIndexOf("=");
return indexOfEqual > 0 && indexOfEqual === lastIndexOfEqual;
});
const queries: { [key: string]: string } = {};
for (const querySubString of querySubStrings) {
const splitResults = querySubString.split("=");
const key: string = splitResults[0];
const value: string = splitResults[1];
queries[key] = value;
}
return queries;
}
export async function getMD5FromString(text: string): Promise<Uint8Array> {
return createHash("md5").update(text).digest();
}
export async function getMD5FromStream(
stream: NodeJS.ReadableStream
): Promise<Uint8Array> {
const hash = createHash("md5");
return new Promise<Uint8Array>((resolve, reject) => {
stream
.on("data", (data) => {
hash.update(data);
})
.on("end", () => {
resolve(hash.digest());
})
.on("error", (err) => {
reject(err);
});
});
}