import * as grpc from '@grpc/grpc-js' ; import * as luxon from 'luxon' ; import * as vscode from 'vscode' ; import { types } from 'vscode-common' ; import { Timestamp } from './proto/google/protobuf/Timestamp' ; import Long = require ( 'long' ) ; import crypto = require ( 'crypto' ) ; import path = require ( 'path' ) ; export class ConfigurationContext { constructor ( public readonly extensionUri , public readonly globalStorageUri , public readonly workspaceState , public readonly properties = getConfigurationPropertyMapFromPackageJson ( extensionUri ) ) { } extensionFile ( ... names ) { return vscode . Uri . joinPath ( this . extensionUri , path . join ( ... names ) ) ; } protoFile ( name ) { return this . extensionFile ( 'proto' , name ) ; } } export function getConfigurationPropertyMapFromPackageJson ( extensionUri ) { const packageJsonPath = path . join ( extensionUri . fsPath , 'package.json' ) ; const packageJSON = require ( packageJsonPath ) ; return packageJSON [ 'contributes' ] [ 'configuration' ] [ 'properties' ] as ConfigurationPropertyMap ; } export type ConfigurationPropertyMap = { [ key ] : ConfigurationProperty ; } ; export interface ConfigurationProperty { key : string ; name : string ; value : any ; description : string ; type : string ; default ? : any ; } /**
 * This is used to test the 'setContext' functionality.  When gRPC errors occur
 * we set a context value EXTENSION_NAME:ENDPOINT_NAME.STATUS_CODE_NAME and use
 * in 'when' expressions to display different welcome views.  There does not
 * appear to be a 'getContext' command however, so to test this functionality we
 * save it on this singleton map also.
 */ export const contextValues = new Map ( ) ; export function getContextGrpcStatusKey ( extensionName , viewId ) { return `${ extensionName }:${ viewId }:status` ; } export function setContextGrpcStatusValue ( extensionName , viewId , err ? ) { const codeName = err ? grpc . status [ err . code ] : grpc . status [ grpc . status . OK ] ; const key = getContextGrpcStatusKey ( extensionName , viewId ) ; contextValues . set ( key , codeName ) ; return vscode . commands . executeCommand ( 'setContext' , key , codeName ) ; } export function clearContextGrpcStatusValue ( extensionName , viewId ) { const key = getContextGrpcStatusKey ( extensionName , viewId ) ; contextValues . delete ( key ) ; return vscode . commands . executeCommand ( 'setContext' , key , undefined ) ; } export function getContextGrpcStatusValue ( extensionName , viewId ) { const key = getContextGrpcStatusKey ( extensionName , viewId ) ; return contextValues . get ( key ) ; } export function isGrpcServiceError ( e ) { return ! types . isUndefined ( ( e as grpc . ServiceError ) . code ) ; } export interface ITelemetry { sendTelemetryEvent ( eventName , properties ? , measurements ? ) : void ; sendTelemetryErrorEvent ( eventName , properties ? , measurements ? ) : void ; sendTelemetryException ( error , properties ? , measurements ? ) : void ; dispose ( ) : Promise < any > ; } export function md5Hash ( value ) { return crypto . createHash ( 'md5' ) . update ( value ) . digest ( 'hex' ) ; } export function makeCommandURI ( command , ... args ) { const encoded = encodeURIComponent ( JSON . stringify ( args ) ) ; return 'command:' + command + '?' + encoded ; } export function getRelativeDateFromTimestamp ( ts ) { const dateTime = luxon . DateTime . fromSeconds ( Long . fromValue ( ts . seconds ! ) . toNumber ( ) ) ; let when = dateTime . toRelative ( ) ; if ( ! when ) { return 'unknown' ; } if ( when === 'in 0 seconds' ) { when = 'just now' ; } return when ; }