UNPKG

alwaysai

Version:

The alwaysAI command-line interface (CLI)

402 lines (345 loc) 10.7 kB
import { CliTerseError } from '@alwaysai/alwayscli'; import { PLEASE_REPORT_THIS_ERROR_MESSAGE } from '../constants'; import { serviceEndpointBuilder } from '../infrastructure/urls'; import { logger, stringifyError } from '../util'; import { CliAuthenticationClient } from './authentication-client'; import { getRestURL } from './urls'; export type DeviceMode = 'development' | 'production'; export type Cert = { iotKeys: { certificateArn: string; certificateId: string; certificatePem: string; keyPair: { PublicKey: string; PrivateKey: string; }; rootCA: string; }; }; export type AddedDevice = { deviceId: number; deviceUUID: string; accessToken: string; refreshToken: string; idToken: string; iotKeys: { certificateArn: string; certificateId: string; certificatePem: string; keyPair: { PublicKey: string; PrivateKey: string; }; rootCA: string; }; }; export type AaiDevice = { id: number; uuid: string; owner: string; friendly_name: string; description?: string; host_name: string; device_user_name?: string; hardware_ids?: string; device_hash?: string; deleted: boolean; created_at: string; updated_at: string; cognito_device_key?: string; mode?: string; iot_keys?: any; status?: string; device_log?: any; unit?: string; ip?: string; coordinates?: any; }; export type RefreshedDevice = { accessToken: string; refreshToken: string; idToken: string; }; export type ReleaseURLandKey = { key: string; presignedAppUrl: string; }; export type ReleaseHistoryArray = ReleaseHistoryDict[]; export type ReleaseHistoryDict = { name: string; hash: string; version: string; timestamp: string; releaseHash: string; // this is the same as hash created_at: string; size: number; }; export type ApplicationPackage = { tarFileName: string; tarFile: Buffer; releaseManifestName: string; releaseManifestFile: string; }; export type ApplicationRecord = { hash: string; s3Path: string; projectId: number; name: string; }; export type PipelineChannel = { name: string; uuid: string; }; export async function addDevice(device, deviceMode: DeviceMode) { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = `${getRestURL()}/createDeviceIot`; const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ ...device, deviceMode }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`addDevice: ${response.statusText}`); throw new CliTerseError( `addDevice: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJSon = JSON.parse(readerStream.toString()); return parsedJSon as AddedDevice; } export async function refreshDevice(deviceId: string) { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = `${getRestURL()}/refreshDevice`; const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ deviceId }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`refreshDevice: ${response.statusText}`); throw new CliTerseError( `refreshDevice: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJSon = JSON.parse(readerStream.toString()); return parsedJSon as RefreshedDevice; } interface UploadResult { uploadURL: string; } export async function getPresignedUrlAppUpload( fileName: string, fileType: string ): Promise<UploadResult> { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = serviceEndpointBuilder( 'remote-deployment', 'presigned-url-app-upload' ); const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ fileName, fileType }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`get-presigned-url-app-upload: ${response.statusText}`); throw new CliTerseError( `get-presigned-url-app-upload: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJSon = JSON.parse(readerStream.toString()); return parsedJSon; } export async function usePresignedUrlAppUpload( presignedUrl: string, fileStream: any ) { try { const response = await fetch(presignedUrl, { method: 'PUT', body: fileStream, headers: { 'Content-Type': 'application/octet-stream' } }); if (response.status !== 200) { logger.error(`use-presigned-url-app-upload: ${response.statusText}`); throw new CliTerseError( `use-presigned-url-app-upload: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } } catch (error) { logger.error(stringifyError(error)); throw new CliTerseError( `app-upload: ${stringifyError( error )} ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } } export async function insertAppRecord(record: ApplicationRecord) { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const response = await fetch( serviceEndpointBuilder('remote-deployment', 'create-application-release'), { method: 'post', body: JSON.stringify({ ...record }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } } ); const readerStream = Buffer.from(await response.arrayBuffer()); const jsonStr = readerStream.toString(); if (response.status !== 200) { logger.error(`insertAppRecord: ${jsonStr}`); throw new CliTerseError( `insertAppRecord: ${jsonStr}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } } export async function getReleaseURL(projectId: string, releaseHash?: string) { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = serviceEndpointBuilder( 'remote-deployment', 'get-presigned-app-url' ); const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ projectId, releaseHash }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`getReleaseUrl: ${response.statusText}`); throw new CliTerseError( `getReleaseUrl: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJSon = JSON.parse(readerStream.toString()); return parsedJSon as ReleaseURLandKey; } export async function fetchAppReleaseHistory(projectUuid: string) { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = serviceEndpointBuilder( 'remote-deployment', 'get-app-release-history' ); const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ projectUuid }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`fetchAppReleaseHistory: ${response.statusText}`); throw new CliTerseError( `fetchAppReleaseHistory: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJSon = JSON.parse(readerStream.toString()); return parsedJSon as ReleaseHistoryArray; } export async function getDeviceByUuid({ uuid }: { uuid: string; }): Promise<AaiDevice> { const { getIdAuthorizationHeader } = CliAuthenticationClient(); const idTokenAuthorizationHeader = await getIdAuthorizationHeader(); const requestURL = serviceEndpointBuilder('devices', 'get-device-by-uuid'); const response = await fetch(requestURL, { method: 'post', body: JSON.stringify({ uuid }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } }); if (response.status !== 200) { logger.error(`get-device-by-uuid: ${response.statusText}`); throw new CliTerseError( `get-device-by-uuid: ${response.statusText}. ${PLEASE_REPORT_THIS_ERROR_MESSAGE}` ); } const readerStream = Buffer.from(await response.arrayBuffer()); const parsedJson = JSON.parse(readerStream.toString()); return parsedJson as AaiDevice; } export async function createAnalyticsPipeline( pipelineName: string, idTokenAuthorizationHeader: Record<string, string> ): Promise<PipelineChannel> { const response = await fetch( serviceEndpointBuilder('aai-analytics', 'createAnalyticsPipeline'), { method: 'POST', body: JSON.stringify({ name: pipelineName }), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } } ); if (response.status !== 200) { logger.error(`createPipeline failed: ${response.statusText}`); throw new CliTerseError(`createPipeline failed: ${response.statusText}`); } const pipeline: PipelineChannel = (await response.json()) as PipelineChannel; return pipeline; } export async function fetchAnalyticsPipelinesForOrg( idTokenAuthorizationHeader: Record<string, string> ): Promise<PipelineChannel[]> { const response = await fetch( serviceEndpointBuilder( 'aai-analytics', 'getAnalyticsChannelIdsForOrganization' ), { method: 'POST', body: JSON.stringify({}), headers: { ...idTokenAuthorizationHeader, 'Content-Type': 'application/json' } } ); if (response.status !== 200) { logger.error(`fetchPipelinesForOrg failed: ${response.statusText}`); throw new CliTerseError( `fetchPipelinesForOrg failed: ${response.statusText}` ); } const orgPipelines: PipelineChannel[] = (await response.json()) as PipelineChannel[]; return orgPipelines; }