import { isIPv4 } from "net" ; type ArgumentsOf < T > = T extends ( ... args : infer A ) => any ? A : never ; type AnyAsyncFunction = ( ... args : any [ ] ) => Promise < any > ; const INVALID_TLDS = new Set ( [ "arpa" , "example" , "invalid" , "localhost" , "test" , "localdomain" , "local" , "onion" , ] ) ; const INVALID_HOST_CHARS = new Set ( "\0\t\n\r #%/:?@[\\]" ) ; export const ns = ( prefix ) => ( name ) : string => prefix + name ; export const noop = ( ) : void => { } ; export const identity = < T > ( x ) : T => x ; export const ensureArray = < T > ( value ) : T [ ] => value == null ? [ ] : Array . isArray ( value ) ? value : [ value ] ; export const words = ( s ) : string [ ] => s . trim ( ) . split ( /\s+/g ) ; export const sample = < T > ( arr ) : T => arr [ Math . floor ( Math . random ( ) * arr . length ) ] ; export const sortBy = < T , S extends number > ( arr , pred ) : T [ ] => { const values = arr . map ( pred ) ; return arr . map ( ( _value , idx ) => idx ) . sort ( ( a , b ) => values [ a ] - values [ b ] ) . map ( ( idx ) => arr [ idx ] ) ; } ; export const detach = < F extends AnyAsyncFunction > ( fn ) : ( ( ... args : ArgumentsOf < F > ) => Promise < void > ) => async ( ... args ) => fn ( ... args ) . then ( exports . noop , ( err ) => { console . error ( err ) ; } ) ; export const originOf = ( url ) : string | undefined => { const match = /^[a-z][a-z0-9.+-]*:\/\/[^/]+/i . exec ( url ) ; return match ? match [ 0 ] : undefined ; } ; export const checkPublicUrl = ( url ) : boolean => { if ( url . slice ( 0 , 8 ) !== "https://" ) { return false ; } const [ host ] = url . slice ( 8 ) . split ( "/" ) ; if ( ! host || ! host . includes ( "." ) || isIPv4 ( host ) || [ ... host ] . find ( ( c ) => INVALID_HOST_CHARS . has ( c ) ) ) { return false ; } const tld = host . split ( "." ) . pop ( ) ; if ( ! tld || INVALID_TLDS . has ( tld ) ) { return false ; } return true ; } ;