import { createHash , createHmac } from "crypto" ; import rimraf = require ( "rimraf" ) ; import { parse } from "url" ; import { promisify } from "util" ; export const lfsa = require ( "lokijs/src/loki-fs-structured-adapter.js" ) ; export const rimrafAsync = promisify ( rimraf ) ; export function minDate ( date1 , date2 ) { return date1 > date2 ? date2 : date1 ; } export function convertDateTimeStringMsTo7Digital ( dateTimeString ) { return dateTimeString . replace ( "Z" , "0000Z" ) ; } export function convertRawHeadersToMetadata ( rawHeaders = [ ] ) { const metadataPrefix = "x-ms-meta-" ; const res = { } ; 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 ( ) { return ( '"0x' + ( new Date ( ) . getTime ( ) * Math . round ( Math . random ( ) * 30000 + 70000 ) ) . toString ( 16 ) . toUpperCase ( ) + '"' ) ; } export function newTableEntityEtag ( startTime ) { return ( "W/\"datetime'" + encodeURIComponent ( truncatedISO8061Date ( startTime , true ) ) + "'\"" ) ; } param { string } stringToSign param { key } key returns { string } export function computeHMACSHA256 ( stringToSign , key ) { return createHmac ( "sha256" , key ) . update ( stringToSign , "utf8" ) . digest ( "base64" ) ; } export param { Date } date param { boolean } withMilliseconds returns { string } export function truncatedISO8061Date ( date , withMilliseconds = true ) { const dateString = date . toISOString ( ) ; return withMilliseconds ? dateString . substring ( 0 , dateString . length - 1 ) + "0000" + "Z" : dateString . substring ( 0 , dateString . length - 5 ) + "Z" ; } export param { string } url returns { { [ key : string ] : string } } export function getURLQueries ( url ) { let queryString = parse ( url ) . query ; if ( ! queryString ) { return { } ; } queryString = queryString . trim ( ) ; queryString = queryString . startsWith ( "?" ) ? queryString . substr ( 1 ) : queryString ; let querySubStrings = queryString . split ( "&" ) ; querySubStrings = querySubStrings . filter ( ( value ) => { const indexOfEqual = value . indexOf ( "=" ) ; const lastIndexOfEqual = value . lastIndexOf ( "=" ) ; return indexOfEqual > 0 && indexOfEqual === lastIndexOfEqual ; } ) ; const queries = { } ; for ( const querySubString of querySubStrings ) { const splitResults = querySubString . split ( "=" ) ; const key = splitResults [ 0 ] ; const value = splitResults [ 1 ] ; queries [ key ] = value ; } return queries ; } export async function getMD5FromString ( text ) { return createHash ( "md5" ) . update ( text ) . digest ( ) ; } export async function getMD5FromStream ( stream ) { 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 ) ; } ) ; } ) ; } export param { string } etag return { * } export function checkEtagIsInvalidFormat ( etag ) { const match = etag . match ( /^W\/"datetime'\d{4}-\d{2}-\d{2}T\d{2}%3A\d{2}%3A\d{2}.\d{7}Z'"$/ ) ; return match === null ; }