import { createHash } from 'crypto' ; import { Headers } from 'node-fetch' ; import { concat , filter , pipe , type } from 'ramda' ; import { isNull , isUndefined , renameKeysWith } from 'ramda-adjunct' ; import { ObjectMetadata } from '../type/object' ; import ReadableStream = NodeJS . ReadableStream ; const encodeCharCode = new Map < RegExp , string > ( "!'()&^~" . split ( '' ) . map ( char => [ new RegExp ( `\\${ char }` , 'g' ) , `%${ char . charCodeAt ( 0 ) . toString ( 16 ) . toUpperCase ( ) }` , ] as [ RegExp , string ] ) ) ; export function camelCase ( name ) { if ( name === 'ID' ) return 'id' ; name = name . replace ( /^[A-Z]/ , m => m . toLowerCase ( ) ) ; name = name . replace ( /[-_][a-z]/g , m => m [ 1 ] . toUpperCase ( ) ) ; return name ; } export function CamelCase ( name ) { if ( name === 'id' ) return 'ID' ; name = name . replace ( /^[a-z]/ , m => m . toUpperCase ( ) ) ; name = name . replace ( /[-_][a-z]/g , m => m [ 1 ] . toUpperCase ( ) ) ; return name ; } export function kababCase ( name ) { name = name . replace ( /^[A-Z]/ , m => m . toLowerCase ( ) ) ; name = name . replace ( /[A-Z]/g , m => `-${ m . toLowerCase ( ) }` ) ; return name ; } function renameObjectNameFactory ( renameFunc ) { return function changeCase ( obj ) : any { switch ( type ( obj ) ) { case 'Object' : obj = renameKeysWith ( renameFunc , obj ) ; for ( const [ key , value ] of Object . entries ( obj ) ) { obj [ key ] = changeCase ( value ) ; } break ; case 'Array' : for ( let i = 0 ; i < obj . length ; i ++ ) { obj [ i ] = changeCase ( obj [ i ] ) ; } obj = obj . slice ( ) ; break ; } return obj ; } ; } export const camelCaseObject = renameObjectNameFactory ( camelCase ) ; export const CamelCaseObject = renameObjectNameFactory ( CamelCase ) ; export const kababCaseObject = renameObjectNameFactory ( kababCase ) ; export function stream2Buffer ( stream ) { const bufs = [ ] ; return new Promise < Buffer > ( ( resolve , reject ) => { stream . on ( 'data' , buf => bufs . push ( buf ) ) ; stream . on ( 'end' , ( ) => { resolve ( Buffer . concat ( bufs ) ) ; } ) ; stream . on ( 'error' , reject ) ; } ) ; } export const addMetadataPrefix = renameKeysWith ( pipe ( kababCase , concat ( 'x-nos-' ) ) ) ; export function getMetadataFromHeaders ( headers ) { let keyIt = headers . keys ( ) ; const metadata = { } ; let res = keyIt . next ( ) ; while ( ! res . done ) { const key = res . value ; if ( key . startsWith ( 'x-nos-' ) ) { metadata [ key . slice ( 6 ) ] = headers . get ( key ) as string ; } res = keyIt . next ( ) ; } return camelCaseObject ( metadata ) ; } export function isHttpStatusOk ( status ) { return status >= 200 && status < 400 ; } export function md5sum ( data ) { return createHash ( 'md5' ) . update ( data ) . digest ( 'hex' ) ; } export const isNullOrUndefined = ( a ) => isNull ( a ) || isUndefined ( a ) ; export const compactObject = filter < any > ( e => ! isNullOrUndefined ( e ) ) ; export function applyMixins ( derivedCtor , baseCtors ) { baseCtors . forEach ( baseCtor => { Object . getOwnPropertyNames ( baseCtor . prototype ) . forEach ( name => { derivedCtor . prototype [ name ] = baseCtor . prototype [ name ] ; } ) ; } ) ; } export function Callbackable ( target , key , descr ) { const fn = descr . value ; descr . value = function ( ... args ) { if ( typeof args [ args . length - 1 ] === 'function' ) { const cb = args [ args . length - 1 ] ; fn . apply ( this , args . slice ( 0 , - 1 ) ) . then ( ( data ) => cb ( null , data ) ) . catch ( ( e ) => cb ( e , null ) ) ; return ; } return fn . apply ( this , args ) ; } ; } export function normalizeArray ( value ) { if ( ! value ) { return [ ] ; } if ( type ( value ) !== 'Array' ) { return [ value ] ; } return value ; } param key export function encodeKey ( key ) { if ( key [ 0 ] === '/' && key . length > 1 ) { key = key . slice ( 1 ) ; } key = encodeURIComponent ( key ) ; for ( const [ reg , str ] of encodeCharCode ) { key = key . replace ( reg , str ) ; } key = key . replace ( /%2F/g , '/' ) ; return key ; }