UNPKG

license-bb

Version:

SDK to create license for any project.

1 lines 78.4 kB
{"version":3,"sources":["../Security/AES.ts","../Security/RSA.ts","../Main.ts"],"sourcesContent":["import crypto from \"crypto\";\r\n\r\nconst defaultKeyLength: number = 32;\r\nconst algorithum = 'aes-256-ecb';\r\n/* const algorithum = 'aes-256-gcm'; */\r\nexport function aesGenerateKeys(): string {\r\n try {\r\n const newAesKey: string = crypto.randomBytes(defaultKeyLength).toString(\"base64\");\r\n return newAesKey || \"\";\r\n } catch (error: any) {\r\n console.error(\"AES Keygen Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred AES Keygen.\");\r\n }\r\n}\r\n\r\nexport function aesEncrypt(secretKey: string = \"\", plainText: string = \"\"): String {\r\n try {\r\n let encmsg = \"\";\r\n if (typeof plainText == \"object\") {\r\n plainText = JSON.stringify(plainText);\r\n }\r\n\r\n let aesKey = Buffer.from(secretKey, \"base64\");\r\n\r\n const cipher = crypto.createCipheriv(algorithum, aesKey, null); // Note the use of null for IV\r\n encmsg = cipher.update(plainText, \"utf8\", \"base64\");\r\n encmsg += cipher.final(\"base64\");\r\n\r\n return encmsg;\r\n } catch (error: any) {\r\n console.error(\"AES Keygen Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred AES Keygen.\");\r\n }\r\n}\r\n\r\nexport function aesDecrypt(secretKey: string = \"\", encryptedText: string = \"\"): String {\r\n try {\r\n \r\n if(!secretKey || secretKey === \"\"){\r\n return \"Invalid / blank secret key received for decryption\";\r\n }\r\n \r\n if(!encryptedText || encryptedText === \"\"){\r\n return \"Invalid / blank encrypted data received for decryption\";\r\n }\r\n\r\n\r\n let decryptedData = null;\r\n\r\n let aesKey = Buffer.from(secretKey, \"base64\");\r\n // const decipher = crypto.createDecipheriv(\"aes-256-ecb\", aesKey, null); // Note the use of null for IV\r\n const decipher = crypto.createDecipheriv(algorithum, aesKey, null); // Note the use of null for IV\r\n decryptedData = decipher.update(encryptedText, \"base64\", \"utf8\");\r\n decryptedData += decipher.final(\"utf8\");\r\n\r\n let plainText = decryptedData || \"\";\r\n\r\n if (plainText.trim() !== \"\" && plainText.includes(\"{\") && typeof plainText === \"string\") {\r\n plainText = JSON.parse(plainText);\r\n }\r\n\r\n return plainText;\r\n } catch (error: any) {\r\n console.error(\"AES Keygen Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred AES Keygen.\");\r\n }\r\n}\r\n","import forge from \"node-forge\";\r\nimport fs from \"fs\";\r\nimport { rsaKey } from \"../DataFormats\";\r\n\r\nconst forgeKeyCreationOptions: any = {\r\n bits: 2048,\r\n // e: 0x10001,\r\n};\r\n\r\nexport function rsaGenerateKeys(): rsaKey {\r\n try {\r\n const keys = forge.pki.rsa.generateKeyPair(forgeKeyCreationOptions);\r\n const privateKey = forge.pki.privateKeyToPem(keys.privateKey);\r\n const publicKey = forge.pki.publicKeyToPem(keys.publicKey);\r\n\r\n return { privateKey, publicKey };\r\n } catch (error) {\r\n console.error(\"RSA Keygen exception: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> RSA Keygen.\");\r\n }\r\n}\r\n\r\nexport function rsaEncrypt(keyFilePath: string = \"\", plainText: string = \"\"): String {\r\n try {\r\n let PUBKEY = fs.readFileSync(keyFilePath, \"utf8\");\r\n let _input = plainText;\r\n if (typeof plainText == \"object\") {\r\n _input = JSON.stringify(plainText);\r\n }\r\n const forgePublicKey = forge.pki.publicKeyFromPem(PUBKEY);\r\n const _encryptedData = forgePublicKey.encrypt(_input);\r\n const encmsg = forge.util.encode64(_encryptedData);\r\n\r\n return encmsg;\r\n } catch (error) {\r\n console.error(\"RSA Keygen exception: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> RSA Keygen.\");\r\n }\r\n}\r\n\r\nexport function rsaDecrypt(keyFilePath: string = \"\", encryptedText: string = \"\"): String {\r\n try {\r\n\r\n if(!keyFilePath || keyFilePath === \"\"){\r\n return \"Invalid / blank Private key file path received for decryption\";\r\n }\r\n \r\n if(!encryptedText || encryptedText === \"\"){\r\n return \"Invalid / blank encrypted data received for decryption\";\r\n }\r\n\r\n let PRIVKEY = fs.readFileSync(keyFilePath, \"utf8\");\r\n let plainText = \"\";\r\n\r\n const forgePrivateKey = forge.pki.privateKeyFromPem(PRIVKEY);\r\n const base64Decode_to_byte = forge.util.decode64(encryptedText);\r\n plainText = forgePrivateKey.decrypt(base64Decode_to_byte);\r\n\r\n if (plainText.trim() !== \"\" && plainText.includes(\"{\") && typeof plainText === \"string\") {\r\n plainText = JSON.parse(plainText);\r\n }\r\n\r\n return plainText;\r\n } catch (error) {\r\n console.error(\"RSA Keygen exception: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> RSA Keygen.\");\r\n }\r\n}\r\n","import ip from \"ip\";\r\nimport os from \"os\";\r\nimport axios from \"axios\";\r\nimport moment from \"moment-timezone\";\r\nimport { clientInputData, DeviceDetails, responseData, rsaKey } from \"./DataFormats\";\r\nimport fs from \"fs\";\r\nimport { rsaDecrypt, rsaEncrypt, rsaGenerateKeys } from \"./Security/RSA\";\r\nimport { aesDecrypt, aesEncrypt, aesGenerateKeys } from \"./Security/AES\";\r\nimport cron from \"node-cron\";\r\nimport path from \"path\";\r\nimport { sha256 } from \"hash.js\";\r\n\r\nconst licenseBaseFolder: string = \"License\";\r\nconst licenseFile: string = \"License.pem\";\r\nconst baseFolderPath: string = \"bbLicenseUtils\";\r\nconst infoTracerFile: string = \"infoTrace.json\";\r\nconst initFile: string = \"init\";\r\nconst deviceFile: string = \"device.json\";\r\nconst publicFile: string = \"public.pem\";\r\nconst privateFile: string = \"private.pem\";\r\nconst serverFile: string = \"server.pem\";\r\nconst logFile: string = \"log\";\r\n\r\nconst OSLIST: Array<string> = [\"win32\", \"win64\", \"linux\", \"darwin\"];\r\n\r\nconst logging = async (org_Id: String = \"\", reason: String = \"\", result: String = \"\") => {\r\n if (fs) {\r\n if (fs.existsSync(`${baseFolderPath}/${logFile}`)) {\r\n try {\r\n // Read existing content of the file\r\n const existingData = fs.readFileSync(`${baseFolderPath}/${logFile}`, \"utf8\");\r\n\r\n const newData = `${new Date().toISOString()} > ${org_Id}: ${reason}: ${result}`;\r\n // Append new data with a newline character\r\n const updatedData = `${existingData.trim()}\\n${newData}`;\r\n\r\n // Write the updated content back to the file\r\n fs.writeFileSync(`${baseFolderPath}/${logFile}`, updatedData);\r\n } catch (err) {\r\n console.error(`Error updating file log file`);\r\n }\r\n } else {\r\n try {\r\n const newData = `${new Date().toISOString()} > ${org_Id}: ${reason}: ${result}`;\r\n // Append new data with a newline character\r\n const updatedData = `${newData}`;\r\n\r\n // Write the updated content back to the file\r\n fs.writeFileSync(`${baseFolderPath}/${logFile}`, updatedData);\r\n } catch (err) {\r\n console.error(`Error updating file log file`);\r\n }\r\n }\r\n }\r\n // return true;\r\n};\r\n\r\nconst getTrace = async (org_Id: String = \"\") => {\r\n if (fs) {\r\n if (fs.existsSync(`${baseFolderPath}/${org_Id}/${infoTracerFile}`)) {\r\n let traceFileData = fs.readFileSync(`${baseFolderPath}/${org_Id}/${infoTracerFile}`, \"utf8\");\r\n\r\n if (traceFileData) {\r\n return JSON.parse(traceFileData);\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n};\r\n\r\nconst updateTrace = async (org_Id: String = \"\", JsonData: any) => {\r\n if (fs) {\r\n let oldTrace = await getTrace(org_Id);\r\n\r\n if (oldTrace && oldTrace !== null && JsonData) {\r\n let newTraceData = { ...oldTrace, ...JsonData };\r\n\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id}/${infoTracerFile}`, JSON.stringify(newTraceData, null, 2));\r\n } else if (!oldTrace && JsonData) {\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id}/${infoTracerFile}`, JSON.stringify(JsonData, null, 2));\r\n }\r\n }\r\n};\r\n\r\nconst hashString = async (input: string) => {\r\n const data = new TextEncoder().encode(input);\r\n\r\n const hash = sha256().update(data).digest(\"hex\");\r\n\r\n return hash;\r\n};\r\n\r\nconst getDeviceDetails = async (): Promise<DeviceDetails> => {\r\n let _deviceDetails: DeviceDetails = {\r\n deviceId: \"\",\r\n osType: \"\",\r\n deviceType: \"\",\r\n browser: \"\",\r\n };\r\n\r\n let filePath = `${baseFolderPath}/${deviceFile}`;\r\n if (fs.existsSync(filePath)) {\r\n let fileData = fs.readFileSync(`${baseFolderPath}/${deviceFile}`, \"utf8\");\r\n const parseData = fileData ? JSON.parse(fileData) : null;\r\n if (parseData) {\r\n return parseData || null;\r\n }\r\n }\r\n\r\n const platform = process?.platform || os.platform();\r\n const _host = process?.env?.HOSTNAME || os.hostname();\r\n /** Type of Device ID Start */\r\n\r\n const systemInfo = `${_host || \"\"}${process?.arch || \"\"}${platform}${process?.version || \"\"}`;\r\n\r\n const hashedData = await hashString(systemInfo);\r\n _deviceDetails.deviceId = hashedData;\r\n\r\n /** Type of Device ID End */\r\n\r\n /** Type of OS Start */\r\n if (platform?.toLowerCase() === \"linux\") {\r\n _deviceDetails.osType = \"Linux\";\r\n } else if (platform?.toLowerCase() === \"darwin\") {\r\n _deviceDetails.osType = \"Mac\";\r\n } else if (platform?.toLowerCase() === \"win32\") {\r\n _deviceDetails.osType = \"Windows\";\r\n } else {\r\n _deviceDetails.osType = \"Unknown\";\r\n }\r\n\r\n /** Type of OS END */\r\n\r\n /** Type of Device Start */\r\n if (fs.existsSync(\"/proc/1/cgroup\")) {\r\n fs.readFile(\"/proc/1/cgroup\", \"utf8\", (err, data) => {\r\n if (err) {\r\n console.error(\"Error reading /proc/1/cgroup to identify MACHINE :\", err);\r\n } else {\r\n if (data.includes(\"/docker/\")) {\r\n _deviceDetails.deviceType = \"Docker\";\r\n } else if (data.includes(\"/machine.slice/machine-qemu\") || data.includes(\"/machine.slice/machine-vmware\")) {\r\n _deviceDetails.deviceType = \"Virtual Machine\";\r\n } else {\r\n _deviceDetails.deviceType = \"Server\";\r\n }\r\n }\r\n });\r\n } else {\r\n _deviceDetails.deviceType = \"Server\";\r\n }\r\n /** Type of Device END */\r\n\r\n try {\r\n fs.writeFileSync(`${baseFolderPath}/${deviceFile}`, JSON.stringify(_deviceDetails, null, 2));\r\n } catch (error) {\r\n console.error(\"SDK EXCEPTION :> on device details save \", error);\r\n // throw new Error(error instanceof Error ? error.message : \"License Device File Save Exception.\");\r\n }\r\n\r\n return _deviceDetails;\r\n};\r\nexport class License {\r\n private static task: any;\r\n\r\n private static licenseKey: string = \"\";\r\n private static baseUrl: string = \"\";\r\n private static secretId: string = \"\";\r\n // private static platform: string = \"\";\r\n // private static deviceId: string = \"\";\r\n private static device: object = {};\r\n private static org_Id: string = \"default\";\r\n // private static _ip: string = ip.address() || \"\";\r\n private static dateTime: Date = new Date();\r\n private static timeZone: string = moment.tz.guess();\r\n\r\n private static doExchange = async (org_Id: string = this.org_Id, clientData: any): Promise<responseData> => {\r\n try {\r\n // const clientData = await this.readFileAndParse(org_Id);\r\n\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n if (clientData) {\r\n let publicFilePath = `${baseFolderPath}/${org_Id.toString().trim()}/${publicFile}`;\r\n let tempPublicFilePath = `${baseFolderPath}/${org_Id.toString().trim()}/temp_${publicFile}`;\r\n\r\n let _public_Key = fs.existsSync(tempPublicFilePath)\r\n ? await fs.readFileSync(tempPublicFilePath, \"utf8\")\r\n : await fs.readFileSync(publicFilePath, \"utf8\");\r\n\r\n if (!clientData?.licenseKey) {\r\n console.error(`No client license key found, please call init() again with required data.`);\r\n throw new Error(`No client license key found, please call init() again with required data.`);\r\n } else if (!_public_Key) {\r\n console.error(`No client public key found, please call init() again with required data.`);\r\n throw new Error(`No client public key found, please call init() again with required data.`);\r\n }\r\n\r\n const _doExchangeApi = `${clientData.baseUrl}/sdk/api/doExchange`;\r\n\r\n const _clientData = { ...clientData };\r\n if (_clientData.secretId) delete _clientData.secretId;\r\n if (_clientData.baseUrl) delete _clientData.baseUrl;\r\n\r\n const apiBody = {\r\n key: _public_Key.toString(),\r\n licenseKey: _clientData?.licenseKey,\r\n email: _clientData?.email,\r\n orgId: _clientData?.orgId,\r\n assignType: _clientData?.assignType,\r\n };\r\n\r\n return await axios\r\n .post(`${_doExchangeApi}`, apiBody, {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n })\r\n .then(async (res) => {\r\n if (res.data?.resultCode == 1) {\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id.toString().trim()}/${serverFile}`, res.data?.data || \"\");\r\n\r\n return await this.getLicense(org_Id.toString().trim(), clientData).then((getLic) => {\r\n if (Number(getLic?.code) < 0) {\r\n // file deepcode ignore PromiseNotCaughtGeneral: not blocking next execution if we add catch everywhere.\r\n return getLic;\r\n } else {\r\n return {\r\n code: 1,\r\n data: null,\r\n result: \"Successfully exchanged and received license.\",\r\n };\r\n }\r\n });\r\n } else {\r\n console.error(`Exchange fail with license server for org '${org_Id}'.`);\r\n throw new Error(`Exchange fail with license server for org '${org_Id}'.`);\r\n }\r\n })\r\n .catch((err: any) => {\r\n if (err?.code == \"ECONNREFUSED\" || err?.message?.includes(\"ECONNREFUSED\")) {\r\n console.error(\"Unable to connect License server :\", err?.message);\r\n throw new Error(\r\n err instanceof Error\r\n ? `Unable to connect License server : ${err?.message}`\r\n : \"Something went wrong at licensing server end.\"\r\n );\r\n }\r\n console.debug(\r\n \"License Server Response : \",\r\n `Status: ${err?.response?.status} : ${err?.message} : `,\r\n err?.response?.data\r\n );\r\n\r\n let _errorMsg = err?.response?.data?.message || \"Fail to get license from server.\";\r\n\r\n console.error({ _errorMsg });\r\n throw new Error(_errorMsg);\r\n });\r\n } else {\r\n console.error(`Invalid client details for org id '${org_Id}'.`, { clientData });\r\n throw new Error(`Invalid client details for org id '${org_Id}'.`);\r\n }\r\n } catch (error) {\r\n console.error(\"Exchange exception : \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> Exchange Files.\");\r\n }\r\n };\r\n\r\n private static getLicense = async (org_Id: String = \"\", clientData: any): Promise<responseData> => {\r\n try {\r\n const _clientEncryptedData = await aesEncrypt(clientData?.secretId, clientData);\r\n const _clientKeyData = await rsaEncrypt(`${baseFolderPath}/${org_Id}/${serverFile}`, clientData?.secretId);\r\n\r\n const licenseServerAPI = `${clientData?.baseUrl}/sdk/api/generateLicense`;\r\n\r\n const apiBody = {\r\n key: _clientKeyData,\r\n licenseKey: clientData?.licenseKey,\r\n client: _clientEncryptedData,\r\n };\r\n\r\n let licenseUrl = \"\";\r\n return await axios\r\n .post(`${licenseServerAPI}`, apiBody, {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n })\r\n .then((res) => {\r\n if (res.data?.resultCode == 1) {\r\n try {\r\n fs.writeFileSync(\r\n `${licenseBaseFolder}/${org_Id}/${licenseFile}`,\r\n JSON.stringify(JSON.parse(res.data?.data), null, 2)\r\n );\r\n } catch (error) {\r\n console.error(\"SDK EXCEPTION :> \", error);\r\n throw new Error(error instanceof Error ? error.message : \"License File Save Exception.\");\r\n }\r\n licenseUrl = res.data?.downloadUrl;\r\n\r\n updateTrace(org_Id, { isExpired: false, isActive: true, dateTime: new Date() });\r\n\r\n return {\r\n code: 1,\r\n data: { licenseUrl },\r\n result: \"License received and saved.\",\r\n };\r\n } else {\r\n console.error(`Get License fail with license server. '${org_Id}'.`);\r\n throw new Error(`Get License fail with license server. '${org_Id}'.`);\r\n }\r\n })\r\n .catch((err: any) => {\r\n if (err?.code == \"ECONNREFUSED\" || err?.message?.includes(\"ECONNREFUSED\")) {\r\n console.error(\"Unable to connect License server :\", err?.message);\r\n throw new Error(\r\n err instanceof Error\r\n ? `Unable to connect License server : ${err?.message}`\r\n : \"Something went wrong at licensing server end.\"\r\n );\r\n }\r\n\r\n console.debug(\r\n \"License Server Response : \",\r\n `Status: ${err?.response?.status} : ${err?.message} : `,\r\n err?.response?.data\r\n );\r\n\r\n let _errorMsg = err?.response?.data?.message || \"Fail to get license from server.\";\r\n\r\n console.error({ _errorMsg });\r\n throw new Error(_errorMsg);\r\n });\r\n } catch (error) {\r\n console.error(\"Get License Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> Get License.\");\r\n }\r\n };\r\n\r\n private static checkValidKey = async (license_Key: String = \"\", baseUrl: String = \"\"): Promise<responseData> => {\r\n try {\r\n const licenseServerAPI = `${baseUrl}/sdk/api/keyCheck/${license_Key}`;\r\n\r\n return await axios\r\n .get(`${licenseServerAPI}`, {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n })\r\n .then((res) => {\r\n if (res.data?.resultCode == 1) {\r\n return {\r\n code: 1,\r\n data: null,\r\n result: res.data?.message || \"Key is valid\",\r\n };\r\n } else {\r\n console.error(`Key is invalid.`);\r\n throw new Error(`Key is invalid.`);\r\n }\r\n })\r\n .catch((err: any) => {\r\n if (err?.code == \"ECONNREFUSED\" || err?.message?.includes(\"ECONNREFUSED\")) {\r\n console.error(\"Unable to connect License server :\", err?.message);\r\n throw new Error(\r\n err instanceof Error\r\n ? `Unable to connect License server : ${err?.message}`\r\n : \"Something went wrong at licensing server end.\"\r\n );\r\n }\r\n console.debug(\r\n \"License Server Response : \",\r\n `Status: ${err?.response?.status} : ${err?.message} :`,\r\n err?.response?.data || err?.response || err\r\n );\r\n\r\n let _errorMsg =\r\n err?.response?.status == 400\r\n ? `Invalid license key '${license_Key}', please check the license key`\r\n : `Fail to check license key '${license_Key}'`;\r\n\r\n console.error({ _errorMsg });\r\n throw new Error(_errorMsg);\r\n });\r\n } catch (error) {\r\n console.error(\"Key Check Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> Key Check.\");\r\n }\r\n };\r\n\r\n private static checkPreinit = async (org_Id: String = \"\"): Promise<any> => {\r\n let isInitFile: Boolean = fs.existsSync(`${baseFolderPath}/${org_Id}/${initFile}`) || false;\r\n let isPublicFile: Boolean = fs.existsSync(`${baseFolderPath}/${org_Id}/${publicFile}`) || false;\r\n let isPrivateFile: Boolean = fs.existsSync(`${baseFolderPath}/${org_Id}/${privateFile}`) || false;\r\n return { isInitFile, isPublicFile, isPrivateFile };\r\n };\r\n\r\n private static checkExchangeFiles = async (org_Id: String = \"\"): Promise<any> => {\r\n let isServerFile: Boolean = fs.existsSync(`${baseFolderPath}/${org_Id}/${serverFile}`) || false;\r\n let isLicenseFile: Boolean = fs.existsSync(`${licenseBaseFolder}/${org_Id}/${licenseFile}`) || false;\r\n return { isServerFile, isLicenseFile };\r\n };\r\n\r\n private static removeKeyFiles = async (org_Id: String = \"\", reason: String = \"init()\") => {\r\n let orgPublicFile = `${baseFolderPath}/${org_Id}/${publicFile}`;\r\n let orgPrivateFile = `${baseFolderPath}/${org_Id}/${privateFile}`;\r\n let orgServerFile = `${baseFolderPath}/${org_Id}/${serverFile}`;\r\n\r\n const filesToDelete = [orgPublicFile, orgPrivateFile, orgServerFile];\r\n\r\n try {\r\n filesToDelete.forEach((filePath) => {\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n });\r\n } catch (error) {\r\n console.error(\"Remove Files Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> Remove Files.\");\r\n }\r\n\r\n return true;\r\n };\r\n\r\n private static readFileAndParse = async (org_Id: String = \"\"): Promise<any> => {\r\n let fileData = fs.readFileSync(`${baseFolderPath}/${org_Id}/${initFile}`, \"utf8\");\r\n const parseData = JSON.parse(fileData);\r\n return parseData || null;\r\n };\r\n\r\n private static extractLicense = async (org_Id: String = \"\"): Promise<responseData> => {\r\n try {\r\n const filePath = `${licenseBaseFolder}/${org_Id}/${licenseFile}`;\r\n\r\n let oldTrace = await getTrace(org_Id);\r\n\r\n if (oldTrace && oldTrace.isActive == false) {\r\n return { code: -2, result: \"License is not active, please contact admin.\", data: null };\r\n } else if (oldTrace && oldTrace.isExpired == true) {\r\n return { code: -2, result: \"License is Expired, please contact admin.\", data: null };\r\n }\r\n if (fs.existsSync(filePath)) {\r\n /** Read License File */\r\n let _encryptedLicense: any = await fs.readFileSync(filePath, \"utf8\");\r\n\r\n /** Format JSON and decode sign */\r\n _encryptedLicense = JSON.parse(_encryptedLicense);\r\n\r\n const decodedSign: any = rsaDecrypt(`${baseFolderPath}/${org_Id}/${privateFile}`, _encryptedLicense?.sign);\r\n\r\n if (decodedSign?.toString()?.includes(\"Invalid\")) {\r\n console.error(decodedSign || `Invalid encrypted data received for decrypt signature for org ${org_Id}`);\r\n throw new Error(decodedSign || \"Invalid encrypted data received for decrypt signature.\");\r\n }\r\n /** after success of sign decode use decoded sign and do 'enc' decryption using AES */\r\n let decodedLicense: any = aesDecrypt(decodedSign, _encryptedLicense?.enc);\r\n\r\n if (decodedLicense?.toString()?.includes(\"Invalid\")) {\r\n console.error(decodedSign || `Invalid encrypted data received for decrypt license for org ${org_Id}`);\r\n throw new Error(decodedSign || \"Invalid encrypted data received for decrypt license.\");\r\n }\r\n\r\n const fullLicense: any = typeof decodedLicense == \"string\" ? JSON.parse(decodedLicense) : decodedLicense;\r\n\r\n return { code: 1, result: \"License extracted.\", data: fullLicense };\r\n } else {\r\n console.log(`No License found at '${filePath}' for org id ${org_Id}`);\r\n console.error(`No license found for organization ${org_Id || \"blank org id\"}, please initialize again.`);\r\n throw new Error(`No license found for organization ${org_Id || \"blank org id\"}, please initialize again.`);\r\n }\r\n } catch (error) {\r\n console.error(\"Extract License Exception>>\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Extract License Exception\");\r\n }\r\n };\r\n\r\n /** External access functions */\r\n\r\n static async init(\r\n base_Url: string = \"\",\r\n license_Key: string = \"\",\r\n clientData: clientInputData\r\n ): Promise<responseData> {\r\n try {\r\n try {\r\n [baseFolderPath, licenseBaseFolder].forEach((folderPath) => {\r\n if (!fs.existsSync(folderPath)) {\r\n fs.mkdirSync(folderPath, { recursive: true });\r\n }\r\n });\r\n } catch (error) {\r\n console.error(\"SDK EXCEPTION older Creation Exception:> \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred> init folder create.\");\r\n }\r\n if (!base_Url) {\r\n console.error(`Please provide valid base url of license server.`);\r\n throw new Error(`Please provide valid base url of license server.`);\r\n }\r\n\r\n if (!license_Key) {\r\n console.error(`Please provide valid license key.`);\r\n throw new Error(`Please provide valid license key.`);\r\n }\r\n\r\n const keyCheckRes = await this.checkValidKey(license_Key, base_Url);\r\n\r\n if (Number(keyCheckRes?.code) < 0) {\r\n return keyCheckRes;\r\n }\r\n\r\n if (!clientData.assignType) {\r\n clientData.assignType = \"default\";\r\n }\r\n\r\n if (!clientData.email || !clientData.orgId || !clientData.userName) {\r\n console.error(\r\n `Please provide required client data {email,orgId,userName}. Data received ${JSON.stringify(clientData)}`\r\n );\r\n throw new Error(`Please provide required client data {email,orgId,userName}.`);\r\n }\r\n\r\n let org_Id = clientData?.orgId?.toString()?.trim() || \"\";\r\n\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n // /** make ORG ID path */\r\n try {\r\n [`${baseFolderPath}/${org_Id}`, `${licenseBaseFolder}/${org_Id}`].forEach((folderPath) => {\r\n if (!fs.existsSync(folderPath)) {\r\n fs.mkdirSync(folderPath, { recursive: true });\r\n }\r\n });\r\n } catch (error) {\r\n console.error(\"Path creation error for org id. \", error);\r\n throw new Error(\r\n error instanceof Error ? error.message : \"Unknown error occurred > Path creation error for org id.\"\r\n );\r\n }\r\n\r\n let preChecks: any = await this.checkPreinit(org_Id);\r\n let clientConfig: any = null;\r\n if (!preChecks.isInitFile) {\r\n // If init file not present then need to create with clientData\r\n\r\n // await machineId().then((id) => {\r\n // this.deviceId = id;\r\n // });\r\n // this.platform = process?.platform || \"\";\r\n this.licenseKey = license_Key;\r\n this.baseUrl = base_Url;\r\n\r\n this.device = await getDeviceDetails();\r\n this.secretId = await aesGenerateKeys();\r\n\r\n clientConfig = {\r\n baseUrl: this.baseUrl,\r\n licenseKey: this.licenseKey,\r\n device: this.device,\r\n secretId: this.secretId || \"\",\r\n dateTime: this.dateTime,\r\n timeZone: this.timeZone,\r\n ...clientData,\r\n orgId: org_Id,\r\n };\r\n\r\n // fs.writeFileSync(`${baseFolderPath}/${org_Id}/${initFile}`, JSON.stringify(_configData));\r\n } else {\r\n const existingClientObj = await this.readFileAndParse(org_Id);\r\n\r\n if (existingClientObj.licenseKey !== license_Key) {\r\n existingClientObj.licenseKey = license_Key;\r\n existingClientObj.dateTime = new Date();\r\n\r\n if (existingClientObj) {\r\n clientConfig = { ...existingClientObj };\r\n } else {\r\n console.warn(`Empty existing client details found:${org_Id}`, { existingClientObj });\r\n }\r\n\r\n // fs.writeFileSync(`${baseFolderPath}/${org_Id}/${initFile}`, JSON.stringify(existingClientObj));\r\n\r\n try {\r\n // await this.removeKeyFiles(org_Id, \"init()\");\r\n // preChecks = await this.checkPreinit(org_Id);\r\n preChecks = { isPublicFile: false, isPrivateFile: false };\r\n } catch (error) {\r\n console.error(\"EXCEPTION removeKeyFiles/configFiles :> \", error);\r\n throw new Error(\r\n error instanceof Error ? error.message : \"Unknown error occurred > While updating user config files.\"\r\n );\r\n }\r\n } else {\r\n clientConfig = { ...existingClientObj };\r\n }\r\n }\r\n\r\n let isExchangeNow: Boolean = false;\r\n\r\n let keyGen: rsaKey;\r\n if (!preChecks.isPublicFile || !preChecks.isPrivateFile) {\r\n keyGen = await rsaGenerateKeys();\r\n\r\n // fs.writeFileSync(`${baseFolderPath}/${org_Id}/${publicFile}`, keyGen.publicKey);\r\n // fs.writeFileSync(`${baseFolderPath}/${org_Id}/${privateFile}`, keyGen.privateKey);\r\n\r\n /** store temprary till exchange success */\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id}/temp_${publicFile}`, keyGen.publicKey);\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id}/temp_${privateFile}`, keyGen.privateKey);\r\n\r\n isExchangeNow = true;\r\n }\r\n\r\n if (!isExchangeNow) {\r\n let exchangeFiles = await this.checkExchangeFiles(org_Id);\r\n // console.debug(\"Exchange Files : \", { exchangeFiles });\r\n isExchangeNow = !exchangeFiles?.isServerFile || !exchangeFiles?.isLicenseFile ? true : false;\r\n }\r\n\r\n if (isExchangeNow) {\r\n return await this.doExchange(org_Id, clientConfig).then((exchRes) => {\r\n if (Number(exchRes?.code) < 0) {\r\n return exchRes;\r\n } else {\r\n try {\r\n /** remove existing files and check temp file is available then rename it */\r\n if (fs.existsSync(`${baseFolderPath}/${org_Id}/temp_${publicFile}`)) {\r\n fs.renameSync(\r\n `${baseFolderPath}/${org_Id}/temp_${publicFile}`,\r\n `${baseFolderPath}/${org_Id}/${publicFile}`\r\n );\r\n }\r\n if (fs.existsSync(`${baseFolderPath}/${org_Id}/temp_${privateFile}`)) {\r\n fs.renameSync(\r\n `${baseFolderPath}/${org_Id}/temp_${privateFile}`,\r\n `${baseFolderPath}/${org_Id}/${privateFile}`\r\n );\r\n }\r\n fs.writeFileSync(`${baseFolderPath}/${org_Id}/${initFile}`, JSON.stringify(clientConfig));\r\n } catch (error) {\r\n console.error(\"EXCEPTION writing client config File :> \", error);\r\n throw new Error(\r\n error instanceof Error ? error.message : \"Unknown error occurred > While writing client config File.\"\r\n );\r\n }\r\n return {\r\n code: 1,\r\n data: null,\r\n result: \"Successfully license exchange/received.\",\r\n };\r\n }\r\n });\r\n } else {\r\n /** If already init file present then sync only */\r\n return await License.sync(license_Key, org_Id).then((syncRes) => {\r\n if (Number(syncRes?.code) < 0) {\r\n return syncRes;\r\n } else {\r\n return {\r\n code: 1,\r\n data: null,\r\n result: \"Successfully license sync.\",\r\n };\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n console.error(\"Initialization fail: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred > Initialization failed.\");\r\n }\r\n }\r\n\r\n static async getConfig(org_Id: String = \"\"): Promise<responseData> {\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n const clientData = await this.readFileAndParse(org_Id.toString().trim());\r\n\r\n if (!clientData) {\r\n console.error(`No client config found. please call init() with org id ${org_Id}.`);\r\n throw new Error(`No client config found. please call init() with org id ${org_Id}.`);\r\n }\r\n\r\n return {\r\n code: 1,\r\n data: clientData,\r\n result: \"Success\",\r\n };\r\n }\r\n\r\n static async update(\r\n license_Key: string = \"\",\r\n org_Id: string = \"\",\r\n assignType: string = \"update\"\r\n ): Promise<responseData> {\r\n if (!license_Key || !org_Id) {\r\n console.error(`license_Key & org_Id should't be blank '${org_Id}'.`);\r\n throw new Error(`license_Key & org_Id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n let orgInitFile = `${baseFolderPath}/${org_Id.toString().trim()}/${initFile}`;\r\n\r\n if (fs.existsSync(orgInitFile)) {\r\n let fileData = fs.readFileSync(orgInitFile, \"utf8\");\r\n const parseData = JSON.parse(fileData);\r\n\r\n // parseData.assignType == license_Key.toString().trim() ? \"default\" : assignType;\r\n parseData.assignType = assignType;\r\n parseData.device = await getDeviceDetails();\r\n parseData.licenseKey = license_Key;\r\n parseData.orgId = org_Id.toString().trim();\r\n parseData.dateTime = new Date();\r\n\r\n const res_init = await License.init(parseData?.baseUrl, license_Key, parseData);\r\n return res_init;\r\n } else {\r\n console.error(`No exiting init file found please do initialize client using init() org id ${org_Id}.`);\r\n throw new Error(`No exiting init file found please do initialize client using init()`);\r\n }\r\n }\r\n\r\n static async sync(license_Key: string = \"\", org_Id: string = \"\"): Promise<responseData> {\r\n if (!license_Key || !org_Id) {\r\n console.error(`license_Key & org_Id should't be blank '${org_Id}'.`);\r\n throw new Error(`license_Key & org_Id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n let orgInitFile = `${baseFolderPath}/${org_Id.toString().trim()}/${initFile}`;\r\n\r\n if (fs.existsSync(orgInitFile)) {\r\n let fileData = fs.readFileSync(orgInitFile, \"utf8\");\r\n const parseData = JSON.parse(fileData);\r\n\r\n if (parseData.licenseKey !== license_Key) {\r\n console.error(`License key '${license_Key}' doesn't match with existing license to sync.`);\r\n throw new Error(`License key '${license_Key}' doesn't match with existing license to sync.`);\r\n } else {\r\n return await this.getLicense(org_Id.toString().trim(), parseData).then((exchRes) => {\r\n if (Number(exchRes?.code) < 0) {\r\n return exchRes;\r\n } else {\r\n return {\r\n code: 1,\r\n data: null,\r\n result: \"License synced successfully.\",\r\n };\r\n }\r\n });\r\n }\r\n } else {\r\n console.error(`No exiting init file found for org id ${org_Id}, please do initialize client again.`);\r\n throw new Error(`No exiting init file found for org id ${org_Id}, please do initialize client again.`);\r\n }\r\n }\r\n\r\n private static calculateDays(startDate: string = \"\"): number {\r\n if (startDate !== \"\") {\r\n const date = new Date(startDate);\r\n\r\n // Get today's date\r\n const today = new Date();\r\n\r\n date.setUTCHours(0, 0, 0, 0);\r\n today.setUTCHours(0, 0, 0, 0);\r\n // Calculate the difference in milliseconds between the two dates\r\n const differenceInMilliseconds = today.getTime() - date.getTime();\r\n\r\n // Convert milliseconds to days\r\n const differenceInDays = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24)) + 1;\r\n\r\n return differenceInDays;\r\n }\r\n return -1;\r\n }\r\n\r\n static async getFeatures(org_Id: string = \"\", featureName: string | string[] | any = \"all\"): Promise<responseData> {\r\n try {\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n if (!featureName) {\r\n console.debug(`Feature name should't be blank '${featureName}', Now auto set to \"all\".`);\r\n // throw new Error(`Feature name should't be blank '${featureName}'.`);\r\n featureName = \"all\";\r\n }\r\n\r\n let licenseData = await this.extractLicense(org_Id.toString().trim());\r\n\r\n if (Number(licenseData?.code) < 0) return licenseData;\r\n\r\n let fullLicense = { ...licenseData?.data };\r\n\r\n let _lic_package = fullLicense?.include?.package;\r\n let _features = _lic_package?.featuresList || _lic_package?.features || [];\r\n let _lic_meta = {\r\n issueDate: fullLicense?.meta?.issued || \"\",\r\n expiryDate: fullLicense?.meta?.expiry || \"\",\r\n package_id: _lic_package?._id || \"\",\r\n isExpired: false,\r\n };\r\n\r\n if (fullLicense?.include?.package && _features && _features?.length > 0) {\r\n /** Expiry logic checking */\r\n\r\n let expiryDateDays: number = License.calculateDays(_lic_meta?.expiryDate);\r\n if (expiryDateDays >= 2) {\r\n _lic_meta.isExpired = true;\r\n }\r\n\r\n /** If not Expired extract the features */\r\n\r\n if (typeof featureName === \"string\" && featureName?.toLowerCase() === \"all\") {\r\n let _fList: any = [];\r\n _features.forEach((item: any) => {\r\n _fList.push({\r\n ...item,\r\n data:\r\n item?.type == \"number\" && item?.data !== \"\"\r\n ? Number(item?.data)\r\n : item?.type == \"boolean\" && item?.data !== \"\"\r\n ? item.data === \"false\"\r\n ? false\r\n : Boolean(item.data)\r\n : item?.type == \"date\" && item?.data !== \"\"\r\n ? new Date(item?.data)\r\n : item.data,\r\n });\r\n });\r\n\r\n return {\r\n code: 1,\r\n data: _fList,\r\n result: \"List of all features\",\r\n meta: _lic_meta || null,\r\n };\r\n } else if (typeof featureName === \"object\" && Array.isArray(featureName)) {\r\n const filteredList =\r\n _features.length > 0 ? _features?.filter((obj: any) => featureName?.includes(obj.name)) : [];\r\n let _fList: any = [];\r\n if (filteredList && filteredList?.length > 0) {\r\n filteredList?.forEach((item: any) => {\r\n _fList.push({\r\n ...item,\r\n data:\r\n item?.type == \"number\" && item?.data !== \"\"\r\n ? Number(item?.data)\r\n : item?.type == \"boolean\" && item?.data !== \"\"\r\n ? item.data === \"false\"\r\n ? false\r\n : Boolean(item.data)\r\n : item?.type == \"date\" && item?.data !== \"\"\r\n ? new Date(item?.data)\r\n : item.data,\r\n });\r\n });\r\n\r\n return {\r\n code: 1,\r\n data: _fList,\r\n result: \"List of features\",\r\n meta: _lic_meta || null,\r\n };\r\n }\r\n } else {\r\n const item =\r\n _features.length > 0\r\n ? _features?.find((data: any) => data?.name?.toLowerCase() === featureName?.toLowerCase())\r\n : null;\r\n\r\n if (item) {\r\n return {\r\n code: 1,\r\n data: {\r\n ...item,\r\n data:\r\n item?.type == \"number\" && item?.data !== \"\"\r\n ? Number(item?.data)\r\n : item?.type == \"boolean\" && item?.data !== \"\"\r\n ? item.data === \"false\"\r\n ? false\r\n : Boolean(item.data)\r\n : item?.type == \"date\" && item?.data !== \"\"\r\n ? new Date(item?.data)\r\n : item.data,\r\n },\r\n meta: _lic_meta || null,\r\n result: item ? \"Success\" : \"No Feature Found.\",\r\n };\r\n }\r\n }\r\n\r\n let _errorMsg = `No Feature found with this name '${\r\n typeof featureName === \"string\" ? featureName : featureName?.join(\",\")\r\n }'`;\r\n\r\n console.error({ _errorMsg });\r\n throw new Error(_errorMsg);\r\n } else {\r\n console.error(\"No feature available in current license.\");\r\n throw new Error(\"No feature available in current license.\");\r\n }\r\n } catch (error) {\r\n console.error(\"Get License Features fail: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred > GetFeatures().\");\r\n }\r\n }\r\n\r\n static async getLicenseDetails(org_Id: string = \"\"): Promise<responseData> {\r\n try {\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n\r\n let licenseData = await this.extractLicense(org_Id.toString().trim());\r\n\r\n if (Number(licenseData?.code) < 0) return licenseData;\r\n\r\n let fullLicense = { ...licenseData?.data };\r\n let _lic_package = fullLicense?.include?.package;\r\n let _lic_meta = {\r\n issueDate: fullLicense?.meta?.issued || \"\",\r\n expiryDate: fullLicense?.meta?.expiry || \"\",\r\n package_id: _lic_package?._id || \"\",\r\n isExpired: false,\r\n };\r\n\r\n let expiryDateDays: number = License.calculateDays(_lic_meta?.expiryDate);\r\n if (expiryDateDays >= 2) {\r\n _lic_meta.isExpired = true;\r\n }\r\n\r\n let featuresList = _lic_package?.featuresList || _lic_package?.features || [];\r\n\r\n fullLicense.meta = _lic_meta;\r\n\r\n /*if (fullLicense?.include?.package && featuresList) {*/\r\n\r\n let _fList: any = [];\r\n if (featuresList?.length > 0) {\r\n featuresList.forEach((item: any) => {\r\n _fList.push({\r\n ...item,\r\n data:\r\n item?.type == \"number\" && item?.data !== \"\"\r\n ? Number(item?.data)\r\n : item?.type == \"boolean\" && item?.data !== \"\"\r\n ? item.data === \"false\"\r\n ? false\r\n : Boolean(item.data)\r\n : item?.type == \"date\" && item?.data !== \"\"\r\n ? new Date(item?.data)\r\n : item.data,\r\n });\r\n });\r\n }\r\n /*else {\r\n console.error(`No License found for org Id '${org_Id}' to get details.`);\r\n throw new Error(`No License found for org Id '${org_Id}' to get details.`);\r\n \r\n }*/\r\n fullLicense.include.package.features = _fList;\r\n\r\n return {\r\n code: 1,\r\n data: fullLicense,\r\n result: \"License Details\",\r\n meta: _lic_meta || null,\r\n };\r\n /*} else {\r\n console.error(`No Feature Available.`);\r\n throw new Error(`No Feature Available.`); \r\n }*/\r\n } catch (error) {\r\n console.error(\"Get License Details fail: \", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred > GetLicenseDetail().\");\r\n }\r\n }\r\n\r\n static delete = async (org_Id: String = \"\"): Promise<responseData> => {\r\n if (!org_Id) {\r\n console.error(`Org id should't be blank '${org_Id}'.`);\r\n throw new Error(`Org id should't be blank '${org_Id}'.`);\r\n }\r\n try {\r\n let orgInitFile = `${baseFolderPath}/${org_Id.toString().trim()}/${initFile}`;\r\n\r\n if (fs.existsSync(orgInitFile)) {\r\n let fileData = fs.readFileSync(orgInitFile, \"utf8\");\r\n const parseData = JSON.parse(fileData);\r\n\r\n return await axios\r\n .delete(`${parseData?.baseUrl}/sdk/api/delete/${org_Id}`, {\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n })\r\n .then((res) => {\r\n if (res.data?.resultCode == 1) {\r\n try {\r\n this.removeKeyFiles(org_Id, \"deleteLicense()\");\r\n if (fs.existsSync(`${licenseBaseFolder}/${org_Id}/${licenseFile}`)) {\r\n fs.unlink(`${licenseBaseFolder}/${org_Id}/${licenseFile}`, () => {});\r\n }\r\n } catch (error) {\r\n console.error(\"Fail to delete files after delete license. \", error);\r\n throw new Error(error instanceof Error ? error.message : \"License File Delete Exception.\");\r\n }\r\n\r\n return {\r\n code: 1,\r\n data: {},\r\n result: \"License deleted.\",\r\n };\r\n } else {\r\n console.error(`Fail to delete license on server. '${org_Id}'.`);\r\n throw new Error(`Fail to delete license on server. '${org_Id}'.`);\r\n }\r\n })\r\n .catch((err: any) => {\r\n if (err?.code == \"ECONNREFUSED\" || err?.message?.includes(\"ECONNREFUSED\")) {\r\n console.error(\"Unable to connect License server :\", err?.message);\r\n throw new Error(\r\n err instanceof Error\r\n ? `Unable to connect License server : ${err?.message}`\r\n : \"Something went wrong at licensing server end.\"\r\n );\r\n }\r\n\r\n console.debug(\r\n \"License Server Response : \",\r\n `Status: ${err?.response?.status} : ${err?.message} : `,\r\n err?.response?.data\r\n );\r\n\r\n let _errorMsg = err?.response?.data?.message || \"Fail to delete license from server.\";\r\n\r\n console.error({ _errorMsg });\r\n throw new Error(_errorMsg);\r\n });\r\n } else {\r\n console.error(`No License issued to org id ${org_Id}.`);\r\n throw new Error(`No License issued to org id ${org_Id}. Unable to delete.`);\r\n }\r\n } catch (error) {\r\n console.error(\"Delete License Exception :\", error);\r\n throw new Error(error instanceof Error ? error.message : \"Unknown error occurred > Delete License.\");\r\n }\r\n };\r\n}\r\n(async function () {\r\n function readDirectories(directoryPath: string): string[] {\r\n const subFolders: string[] = [];\r\n\r\n // Read the contents of the directory\r\n const contents = fs.readdirSync(directoryPath);\r\n\r\n // Iterate through the contents\r\n for (const item of contents) {\r\n const itemPath = path.join(directoryPath, item);\r\n // Check if the item is a directory\r\n if (fs.statSync(itemPath).isDirectory()) {\r\n subFolders.push(item);\r\n }\r\n }\r\n\r\n return subFolders;\r\n }\r\n\r\n // cron.schedule(\"*/10 * * * * *\", async () => { // this is 10 sec\r\n // Define your scheduler initialization logic\r\n const midnight = \"0 30 0 * * *\";\r\n cron.schedule(midnight, async () => {\r\n /** this is 30 min */\r\n try {\r\n const subFolders = (await readDirectories(baseFolderPath)) || [];\r\n\r\n for (const orgId of subFolders) {\r\n let orgInitFile = `${baseFolderPath}/${orgId}/${initFile}`;\r\n\r\n if (fs.existsSync(orgInitFile)) {\r\n let fileData = fs.readFileSync(orgInitFile, \"utf8\");\r\n const parseData = JSON.parse(fileData);\r\n\r\n parseData.device = await getDeviceDetails();\r\n\r\n if (\r\n parseData &&\r\n parseData?.licenseKey &&\r\n parseData?.licenseKey !== \"\" &&\r\n fs.existsSync(`${baseFolderPath}/${orgId}/${serverFile}`)\r