{"version":3,"file":"json-file-log.mjs","names":[],"sources":["../../../../../../../@warlock.js/logger/src/channels/json-file-log.ts"],"sourcesContent":["import { ensureDirectoryAsync, fileExistsAsync, getJsonFileAsync } from \"@warlock.js/fs\";\r\nimport dayjs from \"dayjs\";\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\nimport type { LogContract, LogMessage, LoggingData } from \"../types\";\r\nimport { safeJsonStringify } from \"../utils/safe-json-stringify\";\r\nimport { FileLog } from \"./file-log\";\r\n\r\nexport class JSONFileLog extends FileLog implements LogContract {\r\n  /**\r\n   * {@inheritdoc}\r\n   */\r\n  public name = \"fileJson\";\r\n\r\n  /**\r\n   * Get file extension\r\n   */\r\n  public get extension(): string {\r\n    return \"json\";\r\n  }\r\n\r\n  /**\r\n   * Synchronously flush messages\r\n   */\r\n  public flushSync(): void {\r\n    if (this.messages.length === 0 && Object.keys(this.groupedMessages).length === 0) return;\r\n\r\n    if (this.messagedShouldBeGrouped) {\r\n      this.prepareGroupedMessages();\r\n      for (const key in this.groupedMessages) {\r\n        const directoryPath = path.join(this.storagePath, key);\r\n        fs.mkdirSync(directoryPath, { recursive: true });\r\n        const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n\r\n        let fileContents = { messages: [] as any[] };\r\n        if (fs.existsSync(filePath)) {\r\n          try {\r\n            fileContents = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\r\n            if (!Array.isArray(fileContents.messages)) fileContents.messages = [];\r\n          } catch (e) {\r\n            fileContents = { messages: [] };\r\n          }\r\n        }\r\n        fileContents.messages.push(...this.groupedMessages[key]);\r\n        fs.writeFileSync(filePath, safeJsonStringify(fileContents, 2));\r\n      }\r\n    } else {\r\n      fs.mkdirSync(this.storagePath, { recursive: true });\r\n      let fileContents = { messages: [] as any[] };\r\n      if (fs.existsSync(this.filePath)) {\r\n        try {\r\n          fileContents = JSON.parse(fs.readFileSync(this.filePath, \"utf-8\"));\r\n          if (!Array.isArray(fileContents.messages)) fileContents.messages = [];\r\n        } catch (e) {\r\n          fileContents = { messages: [] };\r\n        }\r\n      }\r\n      fileContents.messages.push(...this.messages);\r\n      fs.writeFileSync(this.filePath, safeJsonStringify(fileContents, 2));\r\n    }\r\n\r\n    this.onSave();\r\n  }\r\n\r\n  /**\r\n   * {@inheritdoc}\r\n   */\r\n  public async log(data: LoggingData) {\r\n    let stack: string[] | undefined;\r\n\r\n    if (data.message instanceof Error) {\r\n      stack = data.message.stack?.split(\"\\n\");\r\n      data.message = data.message.message;\r\n    }\r\n\r\n    const { module, action, message, type: level, context } = data;\r\n\r\n    if (!this.shouldBeLogged(data)) return;\r\n\r\n    const { date: dateFormat, time } = this.getDateAndTimeFormat();\r\n\r\n    const date = dayjs().format(dateFormat + \" \" + time);\r\n\r\n    this.messages.push({\r\n      content: message,\r\n      level,\r\n      date,\r\n      module,\r\n      action,\r\n      stack,\r\n      context,\r\n      timestamp: new Date().toISOString(),\r\n    } as LogMessage);\r\n\r\n    await this.checkIfMessagesShouldBeWritten(); // Immediate check on buffer size\r\n  }\r\n\r\n  /**\r\n   * Write messages to the file\r\n   */\r\n  protected async writeMessagesToFile(): Promise<void> {\r\n    if (this.messages.length === 0 || this.isWriting || !this.isInitialized) return;\r\n\r\n    this.isWriting = true;\r\n\r\n    if (this.messagedShouldBeGrouped) {\r\n      return await this.writeGroupedMessagesToFile();\r\n    }\r\n\r\n    await this.checkAndRotateFile(); // Ensure file rotation is handled\r\n\r\n    let fileContents = { messages: [] as any[] };\r\n\r\n    if (await fileExistsAsync(this.filePath)) {\r\n      try {\r\n        fileContents = (await getJsonFileAsync(this.filePath)) as { messages: any[] };\r\n      } catch (error) {\r\n        console.error(\"Error reading log file, reinitializing:\", error);\r\n        fileContents = { messages: [] }; // Reinitialize the file if corrupted\r\n      }\r\n    } else {\r\n      fileContents = { messages: [] }; // Reinitialize the file if corrupted\r\n    }\r\n\r\n    fileContents.messages.push(...this.messages);\r\n\r\n    try {\r\n      await fs.promises.writeFile(this.filePath, safeJsonStringify(fileContents, 2));\r\n\r\n      this.onSave();\r\n    } catch (error) {\r\n      console.error(\"Failed to write log:\", error);\r\n      // Implement fallback logic here\r\n      this.isWriting = false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Write grouped messages to the file\r\n   */\r\n  protected async writeGroupedMessagesToFile(): Promise<void> {\r\n    // first step, is to group the messages\r\n    this.prepareGroupedMessages();\r\n\r\n    // now each key in the grouped messages, represents the directory path that should extend the storage path\r\n    for (const key in this.groupedMessages) {\r\n      const directoryPath = path.join(this.storagePath, key);\r\n\r\n      await ensureDirectoryAsync(directoryPath);\r\n\r\n      const filePath = path.join(directoryPath, `${this.fileName}.${this.extension}`);\r\n\r\n      await this.checkAndRotateFile(filePath); // Ensure we check file size before writing\r\n\r\n      let fileContents: { messages: any[] } = { messages: [] };\r\n      if (await fileExistsAsync(filePath)) {\r\n        try {\r\n          fileContents = (await getJsonFileAsync(filePath)) as { messages: any[] };\r\n        } catch (error) {\r\n          console.error(\"Error reading log file, reinitializing:\", error);\r\n          fileContents = { messages: [] };\r\n        }\r\n      } else {\r\n        fileContents = { messages: [] };\r\n      }\r\n\r\n      fileContents.messages.push(...this.groupedMessages[key]);\r\n\r\n      try {\r\n        await fs.promises.writeFile(filePath, safeJsonStringify(fileContents, 2));\r\n      } catch (error) {\r\n        console.error(\"Failed to write log:\", error);\r\n        this.isWriting = false;\r\n      }\r\n    }\r\n\r\n    this.onSave();\r\n  }\r\n}\r\n"],"mappings":"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"}