|
@@ -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();
|
|
|
-
|
|
|
-
|
|
|
- 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) {
|
|
|
-
|
|
|
- } else {
|
|
|
- if (receiverProfileInfo) {
|
|
|
- console.log({ message: `Is Old profile, reconnecting with server` })
|
|
|
- checkOwnClientInfo(receiverProfileInfo.clientId).then((profile: ConnectedHttpServer) => {
|
|
|
- receiverProfileInfo!.clientId = profile.clientId
|
|
|
-
|
|
|
- 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`
|
|
|
- })
|
|
|
-
|
|
|
- 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 })
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-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;
|
|
|
-
|
|
|
- const longPoll = async () => {
|
|
|
- while (active) {
|
|
|
- try {
|
|
|
-
|
|
|
- const response = await axios.get(`${url}poll`);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- 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 })
|
|
|
- handleServerConnectionError(active, eventNotification, server)
|
|
|
-
|
|
|
- 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}` });
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- longPoll();
|
|
|
-
|
|
|
-
|
|
|
- return () => {
|
|
|
- console.log({ message: 'Unsubscribed from the long-polling channel.' });
|
|
|
- eventNotification.complete();
|
|
|
- };
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function handleServerConnectionError(active: boolean, observer: Observer<GeneralEvent<any>>, server: ConnectedHttpServer): void {
|
|
|
- server.connectionState.next('OFFLINE');
|
|
|
- console.log({ message: 'Server lost connection' });
|
|
|
- active = false;
|
|
|
- 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`
|
|
|
- })
|
|
|
-
|
|
|
- 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)
|
|
|
- })
|
|
|
-
|
|
|
-
|
|
|
- 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) => {
|
|
|
-
|
|
|
- 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(),
|
|
|
- dateCreated: new Date(),
|
|
|
- instance: app,
|
|
|
- connectionState: new BehaviorSubject<ConnectionState>(`OFFLINE`),
|
|
|
- responseStream: new Subject<WrappedMessage>(),
|
|
|
- transportServiceId: transportServiceId,
|
|
|
- transport: `Http`
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- res.json({
|
|
|
- name: `New Profile`, message: { id: clientInstance.clientId }
|
|
|
- })
|
|
|
-
|
|
|
- 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`
|
|
|
- })
|
|
|
-
|
|
|
- connectedClientHttp.push(clientInstance)
|
|
|
- addClientToDB(clientInstance)
|
|
|
- startListeningAndStreaming(app, clientInstance, event)
|
|
|
- } else if (data.name == 'Old Client') {
|
|
|
- console.log({ message: `Is old client`, details: data })
|
|
|
-
|
|
|
- let clientInstance: ConnectedHttpClient | undefined
|
|
|
- if (connectedClientHttp.length > 0) {
|
|
|
- clientInstance = connectedClientHttp.find(obj => obj.clientId === data.message.id)
|
|
|
- handleFoundClient(clientInstance)
|
|
|
- } else {
|
|
|
-
|
|
|
- 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 } })
|
|
|
-
|
|
|
- clientInstance.instance = app
|
|
|
-
|
|
|
- if (!clientInstance.connectionState) {
|
|
|
- clientInstance.connectionState = new BehaviorSubject<ConnectionState>(`OFFLINE`)
|
|
|
- }
|
|
|
-
|
|
|
- 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 {
|
|
|
-
|
|
|
- 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');
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
|
- const data: any[] = JSON.parse(fileContent);
|
|
|
-
|
|
|
-
|
|
|
- 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`)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-export function addClientToDB(entry: ConnectedHttpClient): void {
|
|
|
- try {
|
|
|
- let data: ConnectedHttpClient[] = [];
|
|
|
- let filePath = process.env.FolderPath as string + 'clients.json'
|
|
|
-
|
|
|
- if (fs.existsSync(filePath)) {
|
|
|
- const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
|
- data = JSON.parse(fileContent);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- data.push({
|
|
|
- id: entry.clientId,
|
|
|
- dateCreated: entry.dateCreated,
|
|
|
- connectionState: null,
|
|
|
- instance: null
|
|
|
- } as unknown as ConnectedHttpClient);
|
|
|
-
|
|
|
-
|
|
|
- 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 });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-export function startListeningAndStreaming(app: Express, client: ConnectedHttpClient, eventListener: Observer<GeneralEvent<any>>, oldClient?: boolean): void {
|
|
|
-
|
|
|
- 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,
|
|
|
- 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');
|
|
|
-
|
|
|
-
|
|
|
- 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`
|
|
|
- })
|
|
|
-
|
|
|
-
|
|
|
- let responseSent = false;
|
|
|
-
|
|
|
-
|
|
|
- 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);
|
|
|
- responseSent = true;
|
|
|
- subscription.unsubscribe();
|
|
|
- }
|
|
|
- },
|
|
|
- error: (err) => {
|
|
|
- if (!responseSent) {
|
|
|
- console.error({ message: 'Error in data stream:', details: err });
|
|
|
- res.status(500).send('Internal Server Error');
|
|
|
- responseSent = true;
|
|
|
- }
|
|
|
- subscription.unsubscribe();
|
|
|
- },
|
|
|
- complete: () => {
|
|
|
- if (!responseSent) {
|
|
|
- console.log({ message: 'Data stream completed.' });
|
|
|
- res.status(204).send();
|
|
|
- responseSent = true;
|
|
|
- }
|
|
|
- subscription.unsubscribe();
|
|
|
- },
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- const timeout = setTimeout(() => {
|
|
|
- if (!responseSent) {
|
|
|
- console.log({ message: 'No data emitted. Sending timeout response.' });
|
|
|
- res.status(204).send();
|
|
|
- responseSent = true;
|
|
|
- subscription.unsubscribe();
|
|
|
- }
|
|
|
- }, 15000);
|
|
|
-
|
|
|
-
|
|
|
- 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();
|
|
|
- }
|
|
|
- clearTimeout(timeout);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-export async function checkOwnClientInfo(filename?: string): Promise<ConnectedHttpServer> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
-
|
|
|
- let filePath = process.env.FolderPath as string
|
|
|
- if (fs.existsSync(filePath + `${filename}.json`)) {
|
|
|
- try {
|
|
|
-
|
|
|
- const fileData = fs.readFileSync(`${filename}.json`, 'utf8');
|
|
|
-
|
|
|
-
|
|
|
- if (fileData.trim() === "") {
|
|
|
- throw new Error("File is empty");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- const jsonData = JSON.parse(fileData);
|
|
|
- resolve(jsonData)
|
|
|
-
|
|
|
- } catch (err) {
|
|
|
-
|
|
|
- let errMsg: string = ("Error reading or parsing file: " + err)
|
|
|
- reject(errMsg);
|
|
|
- }
|
|
|
- } else {
|
|
|
- reject("File does not exist");
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-async function writeFile(data: ConnectedHttpServer, filename: string): Promise<boolean> {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
-
|
|
|
- const folderPath = process.env.FolderPath as string
|
|
|
- console.log({ message: folderPath })
|
|
|
-
|
|
|
- if (!fs.existsSync(folderPath)) {
|
|
|
- fs.mkdirSync(folderPath, { recursive: true });
|
|
|
- } else {
|
|
|
- console.log({ message: 'Folder already exist' })
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- const filePath = path.join(folderPath, `${filename}.json`);
|
|
|
-
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
+
|