github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/kat/src/clients/doc-exchange.ts (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import { IDocExchangeTransferData, IDocExchangeListener, IDocExchangeDocumentDetails } from '../lib/interfaces';
    16  import { config } from '../lib/config';
    17  import { Stream, Readable } from 'stream';
    18  import io from 'socket.io-client';
    19  import FormData from 'form-data';
    20  import axios from 'axios';
    21  import * as utils from '../lib/utils';
    22  
    23  const log = utils.getLogger('clients/doc-exchange.ts');
    24  
    25  let socket: SocketIOClient.Socket
    26  let listeners: IDocExchangeListener[] = [];
    27  
    28  export const init = async () => {
    29    try {
    30      const response = await axios.get(`${config.docExchange.apiEndpoint}/documents`, {
    31        auth: {
    32          username: config.appCredentials.user,
    33          password: config.appCredentials.password
    34        }
    35      });
    36      if (!Array.isArray(response.data.entries)) {
    37        throw 'Invalid response';
    38      } else {
    39        establishSocketIOConnection();
    40      }
    41    } catch (err) {
    42      throw new Error(`Document exchange REST connection failed. ${err}`);
    43    }
    44  };
    45  
    46  const establishSocketIOConnection = () => {
    47    let error = false;
    48    socket = io.connect(config.docExchange.socketIOEndpoint, {
    49      transportOptions: {
    50        polling: {
    51          extraHeaders: {
    52            Authorization: 'Basic ' + Buffer.from(`${config.appCredentials.user}` +
    53              `:${config.appCredentials.password}`).toString('base64')
    54          }
    55        }
    56      }
    57    }).on('connect', () => {
    58      if (error) {
    59        error = false;
    60        log.info('Document exchange Socket IO connection restored');
    61      }
    62    }).on('connect_error', (err: Error) => {
    63      error = true;
    64      log.error(`Document exchange Socket IO connection error. ${err.toString()}`);
    65    }).on('error', (err: Error) => {
    66      error = true;
    67      log.error(`Document exchange Socket IO error. ${err.toString()}`);
    68    }).on('document_received', (transferData: IDocExchangeTransferData) => {
    69      log.trace(`Doc exchange transfer event ${JSON.stringify(transferData)}`);
    70      for (const listener of listeners) {
    71        listener(transferData);
    72      }
    73    }) as SocketIOClient.Socket;
    74  };
    75  
    76  export const addListener = (listener: IDocExchangeListener) => {
    77    listeners.push(listener);
    78  };
    79  
    80  export const removeListener = (listener: IDocExchangeListener) => {
    81    listeners = listeners.filter(entry => entry != listener);
    82  };
    83  
    84  export const downloadStream = async (documentPath: string): Promise<Buffer> => {
    85    const response = await axios.get(`${config.docExchange.apiEndpoint}/documents/${documentPath}`, {
    86      responseType: 'arraybuffer',
    87      auth: {
    88        username: config.appCredentials.user,
    89        password: config.appCredentials.password
    90      }
    91    });
    92    return response.data;
    93  };
    94  
    95  export const downloadJSON = async <T>(documentPath: string): Promise<T> => {
    96    const response = await axios.get(`${config.docExchange.apiEndpoint}/documents/${documentPath}`, {
    97      responseType: 'json',
    98      auth: {
    99        username: config.appCredentials.user,
   100        password: config.appCredentials.password
   101      }
   102    });
   103    return response.data;
   104  };
   105  
   106  export const findDocumentByHash = async (documentHash: string): Promise<string | null> => {
   107    const result = await axios({
   108      url: `${config.docExchange.apiEndpoint}/search?query=${documentHash}&by_hash=true`,
   109      auth: {
   110        username: config.appCredentials.user,
   111        password: config.appCredentials.password
   112      }
   113    });
   114    if (result.data.documents.length > 0) {
   115      return result.data.documents[0].full_path;
   116    }
   117    return null;
   118  }
   119  
   120  export const uploadString = async (value: string, path: string): Promise<string> => {
   121    const readable = new Readable();
   122    readable.push(value);
   123    readable.push(null);
   124    return uploadStream(readable, path);
   125  };
   126  
   127  export const uploadStream = async (stream: Stream, path: string): Promise<string> => {
   128    const formData = new FormData();
   129    formData.append('document', stream);
   130    const result = await axios({
   131      method: 'put',
   132      url: `${config.docExchange.apiEndpoint}/documents/${path}`,
   133      data: formData,
   134      headers: formData.getHeaders(),
   135      auth: {
   136        username: config.appCredentials.user,
   137        password: config.appCredentials.password
   138      }
   139    });
   140    return result.data.hash;
   141  };
   142  
   143  export const transfer = async (from: string, to: string, document: string) => {
   144    await axios({
   145      method: 'post',
   146      url: `${config.docExchange.apiEndpoint}/transfers`,
   147      auth: {
   148        username: config.appCredentials.user,
   149        password: config.appCredentials.password
   150      },
   151      data: { from, to, document }
   152    });
   153  }
   154  
   155  export const getDocumentDetails = async (filePath: string): Promise<IDocExchangeDocumentDetails> => {
   156    const result = await axios({
   157      url: `${config.docExchange.apiEndpoint}/documents/${filePath}?details_only=true`,
   158      auth: {
   159        username: config.appCredentials.user,
   160        password: config.appCredentials.password
   161      }
   162    });
   163    return result.data;
   164  };
   165  
   166  export const reset = () => {
   167    if (socket) {
   168      log.info('Document exchange Socket IO connection reset');
   169      socket.close();
   170      establishSocketIOConnection();
   171    }
   172  };