|
@@ -1,558 +1 @@
|
|
|
-import express, { Response } from 'express';
|
|
|
-import * as fs from 'fs'
|
|
|
-import { Express } from 'express';
|
|
|
-import { v4 as uuidv4 } from 'uuid'
|
|
|
-import { ConnectedHttpClient, ConnectedHttpServer } from "../transport/http";
|
|
|
-import { BehaviorSubject, Observable, Observer, Subject, Subscription } from "rxjs";
|
|
|
-import { WrappedMessage } from './message.ordering';
|
|
|
-import axios, { AxiosError, AxiosResponse } from 'axios';
|
|
|
-import ConsoleLogger from './log.utils';
|
|
|
-import path from 'path';
|
|
|
-import { ConnectionState, FisMessage, GeneralEvent, TransportMessage } from '../interface/interface';
|
|
|
-const console: ConsoleLogger = new ConsoleLogger(`HttpUtils`, ['transport'])
|
|
|
-
|
|
|
-export function startHttpServer(port: number): Observable<ConnectedHttpClient> {
|
|
|
- return new Observable((observer: Observer<ConnectedHttpClient>) => {
|
|
|
- let app: Express = express();
|
|
|
-
|
|
|
- // Middleware to parse JSON requests
|
|
|
- app.use(express.json());
|
|
|
-
|
|
|
- app.listen(port, () => {
|
|
|
- console.log({ message: `Server running at http://localhost:${port}` });
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-export async function initiateClientToServer(transportServiceId: string, url: string, event: Subject<GeneralEvent<any>>, connectedHttpServers: ConnectedHttpServer[], receiverProfileInfo: ConnectedHttpServer | undefined, browserEnv?: boolean,): Promise<ConnectedHttpServer> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- if (browserEnv) {
|
|
|
- // logic here for using browser fetch
|
|
|
- } else { // axios methods
|
|
|
- if (receiverProfileInfo) {
|
|
|
- console.log({ message: `Is Old profile, reconnecting with server` })
|
|
|
- checkOwnClientInfo(receiverProfileInfo.clientId).then((profile: ConnectedHttpServer) => {
|
|
|
- receiverProfileInfo!.clientId = profile.clientId
|
|
|
- // console.log({ message: 'jsonfile', details: profile })
|
|
|
- postAxiosRequest(url + 'profile', { name: 'Old Client', message: profile }).then((profileInfo: { name: string, message: { id: string } }) => {
|
|
|
- console.log({ message: `Acknowledged as previous client. Id: ${profileInfo.message.id}` })
|
|
|
- event.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'Server Connected',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: profileInfo.message.id,
|
|
|
- message: `Existing Http Channel ${profileInfo.message.id} re-established.`
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- // Update Http instance record
|
|
|
- let clientObj: ConnectedHttpServer | undefined = connectedHttpServers.find(obj => obj.clientId === profileInfo.message.id)
|
|
|
- console.log({ message: 'ClientObj', details: clientObj })
|
|
|
- console.log({ message: 'ReceiverProfile', details: receiverProfileInfo })
|
|
|
- if (clientObj) {
|
|
|
- clientObj.connectionState.next('ONLINE')
|
|
|
- console.log({ message: receiverProfileInfo.connectionState.getValue() })
|
|
|
- resolve(clientObj)
|
|
|
- }
|
|
|
-
|
|
|
- }).catch((error: AxiosError) => {
|
|
|
- reject({ error: error, objRef: receiverProfileInfo })
|
|
|
- })
|
|
|
- }).catch((error) => {
|
|
|
- console.error(error)
|
|
|
- postAxiosRequest(url + 'profile', { name: 'New Client', data: null }).then((profileInfo: { name: string, message: any }) => {
|
|
|
- updateProfileAndPublishEvent(transportServiceId, (receiverProfileInfo as ConnectedHttpServer), profileInfo, event, connectedHttpServers).then((receiverProfileInfo) => {
|
|
|
- resolve(receiverProfileInfo)
|
|
|
- })
|
|
|
- }).catch((error) => {
|
|
|
- reject({ error: error, objRef: receiverProfileInfo })
|
|
|
- })
|
|
|
- reject({ error: error, objRef: receiverProfileInfo })
|
|
|
- })
|
|
|
- } else {
|
|
|
- console.log({ message: `Is New profile, Connecting with server` })
|
|
|
- postAxiosRequest(url + 'profile', { name: 'New Client', data: null }).then((profileInfo: { name: string, message: any }) => {
|
|
|
- updateProfileAndPublishEvent(transportServiceId, receiverProfileInfo, profileInfo, event, connectedHttpServers).then((receiverProfileInfo) => {
|
|
|
- resolve(receiverProfileInfo)
|
|
|
- })
|
|
|
- }).catch((error) => {
|
|
|
- reject({ error: error, objRef: receiverProfileInfo })
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// For client usage
|
|
|
-export function handleClientHttpConnection(url: string, server: ConnectedHttpServer): Observable<GeneralEvent<any>> {
|
|
|
- return new Observable((eventNotification: Observer<GeneralEvent<any>>) => {
|
|
|
- console.log({ message: `Long Poll Attempt for ${server.clientId}` })
|
|
|
- server.connectionState.next('ONLINE');
|
|
|
- let active: boolean = true; // Flag to control polling lifecycle
|
|
|
-
|
|
|
- const longPoll = async () => {
|
|
|
- while (active) {
|
|
|
- try {
|
|
|
- // Axios request with timeout
|
|
|
- const response = await axios.get(`${url}poll`); // removing the timeout temporarily.
|
|
|
- // const response = await axios.get(`${url}response`, {
|
|
|
- // timeout: 3000, // 10s timeout this one will trigger error. That's why it keeps on throwing error
|
|
|
- // });
|
|
|
-
|
|
|
- if (response.status === 200) {
|
|
|
- const data = response.data;
|
|
|
- console.log({ message: 'Long Poll Response', details: data })
|
|
|
- eventNotification.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'New Message',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- id: uuidv4(),
|
|
|
- dateCreated: new Date(),
|
|
|
- transport: `Http`,
|
|
|
- target: server.clientId,
|
|
|
- payload: data,
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- });
|
|
|
- } else if (response.status === 204) {
|
|
|
- console.log({ message: 'No new messages from the server.' });
|
|
|
- } else {
|
|
|
- console.error({ message: `Unexpected response status: ${response.status}` })
|
|
|
- handleServerConnectionError(active, eventNotification, server)
|
|
|
- throw new Error(`Unexpected response status: ${response.status}`);
|
|
|
- }
|
|
|
- } catch (error: unknown) {
|
|
|
- console.error({ message: `Unknown Error.`, details: error }) // culprit is here
|
|
|
- handleServerConnectionError(active, eventNotification, server)
|
|
|
- // Error handling with server disconnect notification
|
|
|
- let errorMessage: string;
|
|
|
-
|
|
|
- if (axios.isAxiosError(error)) {
|
|
|
- if (error.response) {
|
|
|
- errorMessage = `Server returned status ${error.response.status}: ${error.response.statusText}`;
|
|
|
- } else if (error.code === 'ECONNABORTED') {
|
|
|
- errorMessage = 'Request timed out.';
|
|
|
- } else {
|
|
|
- errorMessage = error.message || 'An Axios error occurred.';
|
|
|
- }
|
|
|
- } else if (error instanceof Error) {
|
|
|
- errorMessage = error.message;
|
|
|
- } else {
|
|
|
- errorMessage = 'An unknown error occurred during polling.';
|
|
|
- }
|
|
|
-
|
|
|
- console.error({ message: `Polling error: ${errorMessage}` });
|
|
|
- // observer.error(new Error(errorMessage)); // Notify subscribers of the error
|
|
|
- break; // Stop polling on error
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- longPoll();
|
|
|
-
|
|
|
- // Cleanup logic for unsubscribing
|
|
|
- return () => {
|
|
|
- console.log({ message: 'Unsubscribed from the long-polling channel.' });
|
|
|
- eventNotification.complete(); // Notify completion
|
|
|
- };
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function handleServerConnectionError(active: boolean, observer: Observer<GeneralEvent<any>>, server: ConnectedHttpServer): void {
|
|
|
- server.connectionState.next('OFFLINE');
|
|
|
- console.log({ message: 'Server lost connection' });
|
|
|
- active = false; // Stop polling
|
|
|
- observer.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'Server Disconnected',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: server.clientId,
|
|
|
- message: '',
|
|
|
- payload: {
|
|
|
- objRef: server
|
|
|
- },
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- });
|
|
|
- observer.complete()
|
|
|
-}
|
|
|
-
|
|
|
-async function updateProfileAndPublishEvent(transportServiceId: string, receiverProfileInfo: ConnectedHttpServer | undefined, profile: { name: string, message: any }, event: Subject<GeneralEvent<any>>, connectedHttpServers: ConnectedHttpServer[]): Promise<ConnectedHttpServer> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- console.log({ message: `Assigned client Name: ${(profile.message as ConnectedHttpServer).clientId}` })
|
|
|
- receiverProfileInfo = profile.message as ConnectedHttpServer
|
|
|
- writeFile(profile.message as ConnectedHttpServer, (profile.message as ConnectedHttpServer).clientId).then(() => {
|
|
|
- event.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: `New Server`,
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: (profile.message as ConnectedHttpServer).clientId,
|
|
|
- message: `New Http Channel ${(profile.message as ConnectedHttpServer).clientId} established.`
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- // broadcast event to allow retransmission to relase buffered messages
|
|
|
- event.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: `Server Connected`,
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: (profile.message as ConnectedHttpServer).clientId,
|
|
|
- message: `Server ${(profile.message as ConnectedHttpServer).clientId} connected and ready to go.`
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- }).catch((error) => {
|
|
|
- reject(error)
|
|
|
- })
|
|
|
-
|
|
|
- // Update http instance record
|
|
|
- receiverProfileInfo = {
|
|
|
- clientId: (profile.message as ConnectedHttpServer).clientId,
|
|
|
- dateCreated: new Date(),
|
|
|
- connectionState: new BehaviorSubject<ConnectionState>(`ONLINE`),
|
|
|
- transport: `Http`,
|
|
|
- transportServiceId: transportServiceId
|
|
|
- }
|
|
|
- connectedHttpServers.push(receiverProfileInfo)
|
|
|
- resolve(receiverProfileInfo)
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-export async function postAxiosRequest(url: string, data: any): Promise<any> {
|
|
|
- return new Promise(async (resolve, reject) => {
|
|
|
- try {
|
|
|
- const response: AxiosResponse<any> = await axios.post(url, data);
|
|
|
- console.log({ message: 'Response', details: response.data });
|
|
|
- resolve(response.data)
|
|
|
- } catch (error) {
|
|
|
- if (axios.isAxiosError(error)) {
|
|
|
- console.error({ message: 'Axios Error:', details: error.code });
|
|
|
- } else {
|
|
|
- console.error({ message: 'Unexpected Error:', details: error });
|
|
|
- }
|
|
|
- reject(error)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-export function handleHttpClient(transportServiceId: string, clientInfo: ConnectedHttpClient, connectedClientHttp: ConnectedHttpClient[]): Observable<GeneralEvent<any>> {
|
|
|
- return new Observable((event: Observer<GeneralEvent<any>>) => {
|
|
|
- clientInfo.instance.post('/profile', (req, res) => {
|
|
|
- // Client will declare this first before attempting to poll for response channel
|
|
|
- handleProfile(transportServiceId, clientInfo.instance, req.body, res, event, connectedClientHttp)
|
|
|
- });
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-function handleProfile(transportServiceId: string, app: Express, data: { name: `Old Client` | `New Client`, message: any }, res: Response, event: Observer<GeneralEvent<any>>, connectedClientHttp: ConnectedHttpClient[]): void {
|
|
|
- if (data.name == `New Client`) {
|
|
|
- let clientInstance: ConnectedHttpClient = {
|
|
|
- clientId: uuidv4(), // client should only be assigned at this level. And is passed around for reference pointing
|
|
|
- dateCreated: new Date(),
|
|
|
- instance: app,
|
|
|
- connectionState: new BehaviorSubject<ConnectionState>(`OFFLINE`), // for now it's offline because it needs to establish the long polling first
|
|
|
- responseStream: new Subject<WrappedMessage>(),
|
|
|
- transportServiceId: transportServiceId,
|
|
|
- transport: `Http`
|
|
|
- }
|
|
|
-
|
|
|
- // send to receiver for reference
|
|
|
- res.json({
|
|
|
- name: `New Profile`, message: { id: clientInstance.clientId }
|
|
|
- })
|
|
|
- // publish first event notification
|
|
|
- event.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: `New Client`,
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: clientInstance.clientId,
|
|
|
- message: `New Http Client Connected. Adapter ID assigned: ${clientInstance.clientId}`,
|
|
|
- payload: clientInstance
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- // Update connected clientInstance info to adapter
|
|
|
- connectedClientHttp.push(clientInstance)
|
|
|
- addClientToDB(clientInstance)
|
|
|
- startListeningAndStreaming(app, clientInstance, event)
|
|
|
- } else if (data.name == 'Old Client') {
|
|
|
- console.log({ message: `Is old client`, details: data })
|
|
|
- // update first
|
|
|
- let clientInstance: ConnectedHttpClient | undefined
|
|
|
- if (connectedClientHttp.length > 0) {
|
|
|
- clientInstance = connectedClientHttp.find(obj => obj.clientId === data.message.id)
|
|
|
- handleFoundClient(clientInstance)
|
|
|
- } else {
|
|
|
- // for the case server itself got shit down or something
|
|
|
- checkIfClientExists(data.message.id).then((client: ConnectedHttpClient) => {
|
|
|
- clientInstance = client
|
|
|
- handleFoundClient(clientInstance)
|
|
|
- }).catch(error => console.error(error))
|
|
|
- }
|
|
|
- function handleFoundClient(clientInstance: ConnectedHttpClient | undefined): void {
|
|
|
- if (clientInstance) {
|
|
|
- console.log({ message: `Http Client ${clientInstance. clientId} Found` })
|
|
|
- res.json({ name: 'Adjusted Profile', message: { id: clientInstance.clientId } })
|
|
|
- // replace socket instance since the previous has been terminated
|
|
|
- clientInstance.instance = app
|
|
|
- // some explanation here. For the case where the server reads from the DB, no need to terminate subject, since all instances would be destroyed alongside the server shut down. This case is specificd only when there's a need to read from local file
|
|
|
- if (!clientInstance.connectionState) {
|
|
|
- clientInstance.connectionState = new BehaviorSubject<ConnectionState>(`OFFLINE`)
|
|
|
- }
|
|
|
- // need to start listening again, because it's assigned a different socket instance this time round
|
|
|
- startListeningAndStreaming(app, clientInstance, event, true)
|
|
|
- event.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'Client Connected',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: clientInstance.clientId,
|
|
|
- message: `Client ${clientInstance.clientId} connection re-established`,
|
|
|
- payload: clientInstance
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
-
|
|
|
- } else {
|
|
|
- console.log({ message: `Profile Not Found` })
|
|
|
- res.json({ name: 'Error', message: 'Receiver Profile Not found' })
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-export async function checkIfClientExists(id: string): Promise<ConnectedHttpClient> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- try {
|
|
|
- // Check if the file exists
|
|
|
- let filePath = process.env.FolderPath as string + 'clients.json'
|
|
|
- if (!fs.existsSync(filePath)) {
|
|
|
- console.log({ message: `File does not exist.` })
|
|
|
- reject('File does not exist');
|
|
|
- }
|
|
|
-
|
|
|
- // Read and parse the data
|
|
|
- const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
|
- const data: any[] = JSON.parse(fileContent);
|
|
|
-
|
|
|
- // Check if an details with the given id exists
|
|
|
- let obj = data.find(entry => entry.id === id);
|
|
|
-
|
|
|
- if (obj) {
|
|
|
- console.log({ message: `Client with ID ${id} exists.` })
|
|
|
- } else {
|
|
|
- console.log({ message: `Client with ID ${id} does not exist.` })
|
|
|
- }
|
|
|
- resolve(obj);
|
|
|
- } catch (error) {
|
|
|
- reject(`Error reading the file`)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-/* For Internal Usage only. Temporary serve as a way for server to keep track of clients. To be replaced in the future with better alternatives. */
|
|
|
-export function addClientToDB(entry: ConnectedHttpClient): void {
|
|
|
- try {
|
|
|
- let data: ConnectedHttpClient[] = [];
|
|
|
- let filePath = process.env.FolderPath as string + 'clients.json'
|
|
|
- // Check if the file exists and load existing data
|
|
|
- if (fs.existsSync(filePath)) {
|
|
|
- const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
|
- data = JSON.parse(fileContent);
|
|
|
- }
|
|
|
-
|
|
|
- // Append the new object to the array
|
|
|
- data.push({
|
|
|
- id: entry.clientId,
|
|
|
- dateCreated: entry.dateCreated,
|
|
|
- connectionState: null,
|
|
|
- instance: null
|
|
|
- } as unknown as ConnectedHttpClient);
|
|
|
-
|
|
|
- // Write the updated array back to the file
|
|
|
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
|
- console.log({ message: `Entry added successfully.` });
|
|
|
- } catch (error) {
|
|
|
- console.error({ message: 'Error writing to file:', details: error });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// this is for server usage only
|
|
|
-export function startListeningAndStreaming(app: Express, client: ConnectedHttpClient, eventListener: Observer<GeneralEvent<any>>, oldClient?: boolean): void {
|
|
|
- /* Generally, we don't need this unless in the case of being the receiver */
|
|
|
- app.post('/message', (req, res) => {
|
|
|
- eventListener.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'New Message',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- id: uuidv4(),
|
|
|
- dateCreated: new Date(),
|
|
|
- transport: `Http`,
|
|
|
- target: client.clientId, // this ref to be associated with the client/channel
|
|
|
- payload: req.body
|
|
|
- } as TransportMessage,
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- res.json(`Received ${((req.body as WrappedMessage)?.payload as FisMessage)?.header?.messageID ?? `Undefined`}`)
|
|
|
- })
|
|
|
-
|
|
|
- app.get('/poll', (req, res) => {
|
|
|
- console.log({ message: 'Client connected for long polling.' });
|
|
|
- client.connectionState.next('ONLINE');
|
|
|
-
|
|
|
- // notify it's associated retransmission to start releaseing buffer
|
|
|
- eventListener.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: oldClient ? 'Client Re-connected' : `Client Connected`,
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: client.clientId,
|
|
|
- message: `Socket Client ${oldClient ? `Re-Connected` : `Connected`}. Adapter ID assigned: ${client.clientId}`,
|
|
|
- payload: client
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
-
|
|
|
- // Flag to track if the response has been sent
|
|
|
- let responseSent = false;
|
|
|
-
|
|
|
- // Subscribe to the data stream
|
|
|
- const subscription = client.responseStream.asObservable().subscribe({
|
|
|
- next: (message: WrappedMessage) => {
|
|
|
- if (!responseSent) {
|
|
|
- console.log({ message: `Sending data ${message.thisMessageID} to client ${client.clientId}}` });
|
|
|
- res.json(message); // Send the data to the client
|
|
|
- responseSent = true; // Mark response as sent
|
|
|
- subscription.unsubscribe(); // Unsubscribe to close this request
|
|
|
- }
|
|
|
- },
|
|
|
- error: (err) => {
|
|
|
- if (!responseSent) {
|
|
|
- console.error({ message: 'Error in data stream:', details: err });
|
|
|
- res.status(500).send('Internal Server Error');
|
|
|
- responseSent = true; // Mark response as sent
|
|
|
- }
|
|
|
- subscription.unsubscribe(); // Ensure cleanup
|
|
|
- },
|
|
|
- complete: () => {
|
|
|
- if (!responseSent) {
|
|
|
- console.log({ message: 'Data stream completed.' });
|
|
|
- res.status(204).send(); // No Content
|
|
|
- responseSent = true; // Mark response as sent
|
|
|
- }
|
|
|
- subscription.unsubscribe(); // Ensure cleanup
|
|
|
- },
|
|
|
- });
|
|
|
-
|
|
|
- // Timeout if no data is emitted within a specified duration
|
|
|
- const timeout = setTimeout(() => {
|
|
|
- if (!responseSent) {
|
|
|
- console.log({ message: 'No data emitted. Sending timeout response.' });
|
|
|
- res.status(204).send(); // No Content
|
|
|
- responseSent = true; // Mark response as sent
|
|
|
- subscription.unsubscribe(); // Ensure cleanup
|
|
|
- }
|
|
|
- }, 15000); // 15 seconds timeout (adjust as needed)
|
|
|
-
|
|
|
- // Handle client disconnection
|
|
|
- res.on('close', () => {
|
|
|
- if (!responseSent) {
|
|
|
- console.error({ message: `Http Client ${client.clientId} disconnected` });
|
|
|
- eventListener.next({
|
|
|
- id: uuidv4(),
|
|
|
- type: `Transport Event`,
|
|
|
- event: 'Client Disconnected',
|
|
|
- date: new Date(),
|
|
|
- data: {
|
|
|
- clientId: client.clientId,
|
|
|
- },
|
|
|
- transport: `Http`
|
|
|
- })
|
|
|
- client.connectionState.next(`OFFLINE`)
|
|
|
- subscription.unsubscribe(); // Ensure cleanup
|
|
|
- }
|
|
|
- clearTimeout(timeout); // Clear timeout to avoid unnecessary execution
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Check if filename exists. Return profile information if there's any
|
|
|
-export async function checkOwnClientInfo(filename?: string): Promise<ConnectedHttpServer> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // Check if the file exists
|
|
|
- let filePath = process.env.FolderPath as string
|
|
|
- if (fs.existsSync(filePath + `${filename}.json`)) {
|
|
|
- try {
|
|
|
- // Read the file contents
|
|
|
- const fileData = fs.readFileSync(`${filename}.json`, 'utf8');
|
|
|
-
|
|
|
- // If the file is empty, return an error
|
|
|
- if (fileData.trim() === "") {
|
|
|
- throw new Error("File is empty");
|
|
|
- }
|
|
|
-
|
|
|
- // Parse and return the data if present
|
|
|
- const jsonData = JSON.parse(fileData);
|
|
|
- resolve(jsonData)
|
|
|
-
|
|
|
- } catch (err) {
|
|
|
- // Handle parsing errors or other file-related errors
|
|
|
- let errMsg: string = ("Error reading or parsing file: " + err)
|
|
|
- reject(errMsg);
|
|
|
- }
|
|
|
- } else {
|
|
|
- reject("File does not exist");
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// Specifically to write receiver profile information
|
|
|
-async function writeFile(data: ConnectedHttpServer, filename: string): Promise<boolean> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // Ensure the folder exists
|
|
|
- const folderPath = process.env.FolderPath as string
|
|
|
- console.log({ message: folderPath })
|
|
|
- // const folderPath = path.join(__dirname, folder);
|
|
|
- if (!fs.existsSync(folderPath)) {
|
|
|
- fs.mkdirSync(folderPath, { recursive: true }); // Create folder if it doesn't exist
|
|
|
- } else {
|
|
|
- console.log({ message: 'Folder already exist' })
|
|
|
- }
|
|
|
-
|
|
|
- // Construct the full file path (include the folder)
|
|
|
- const filePath = path.join(folderPath, `${filename}.json`);
|
|
|
-
|
|
|
- // Write JSON data to a file
|
|
|
- fs.writeFile(filePath, JSON.stringify(data, null, 2), (err) => {
|
|
|
- if (err) {
|
|
|
- console.log({ message: 'Error writing file', details: err });
|
|
|
- reject(false);
|
|
|
- } else {
|
|
|
- console.log({ message: 'File has been written', details: filePath });
|
|
|
- resolve(true);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
+// code here.
|