cordova-plugin-unvired-logger 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordova-plugin-unvired-logger",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "A logger plugin for Electron, Android, Browser, and iOS that appends logs to log.txt files organized by user ID.",
5
5
  "cordova": {
6
6
  "id": "cordova-plugin-unvired-logger",
package/plugin.xml CHANGED
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <plugin id="cordova-plugin-unvired-logger" version="0.0.10"
2
+ <plugin id="cordova-plugin-unvired-logger" version="0.0.11"
3
3
  xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
4
  xmlns:android="http://schemas.android.com/apk/res/android">
5
5
 
@@ -21,7 +21,7 @@ public class Logger extends CordovaPlugin {
21
21
  private static final String BACKUP_LOG_FILE_NAME = "log_backup.txt";
22
22
  private static final long MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
23
23
 
24
- private String defaultLogLevel = "info";
24
+ private String defaultLogLevel = "important";
25
25
 
26
26
  @Override
27
27
  public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
@@ -111,8 +111,8 @@ public class Logger extends CordovaPlugin {
111
111
  private boolean shouldSkipLog(String level) {
112
112
  String normLevel = level.toLowerCase();
113
113
  String normDefault = defaultLogLevel.toLowerCase();
114
- if (normDefault.equals("error") && (normLevel.equals("debug") || normLevel.equals("info"))) return true;
115
- if (normDefault.equals("info") && normLevel.equals("debug")) return true;
114
+ if (normDefault.equals("error") && (normLevel.equals("debug") || normLevel.equals("important"))) return true;
115
+ if (normDefault.equals("important") && normLevel.equals("debug")) return true;
116
116
  return false;
117
117
  }
118
118
 
@@ -229,7 +229,7 @@ public class Logger extends CordovaPlugin {
229
229
 
230
230
  private String getStringFromLevel(String level) {
231
231
  switch (level.toLowerCase()) {
232
- case "info": return "IMPORTANT";
232
+ case "important": return "IMPORTANT";
233
233
  case "error": return "ERROR";
234
234
  case "debug": return "DEBUG";
235
235
  default: return "";
@@ -6,7 +6,7 @@ const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
6
6
  const LogLevel = {
7
7
  Debug: 'debug',
8
8
  Error: 'error',
9
- Info: 'info',
9
+ Info: 'important',
10
10
  };
11
11
 
12
12
  let defaultLogLevel = LogLevel.Info;
@@ -29,12 +29,12 @@ module.exports.logInfo = async function (successCallback, errorCallback, args) {
29
29
 
30
30
  module.exports.setLogLevel = function(successCallback, errorCallback, level) {
31
31
  // If level is an array (from Cordova), extract the first element
32
- if (Array.isArray(level)) {
33
- defaultLogLevel = level[0];
34
- } else {
35
- defaultLogLevel = level;
36
- }
37
- successCallback("")
32
+ let levelToSet = Array.isArray(level) ? level[0] : level;
33
+
34
+ // Normalize the level to lowercase for consistency
35
+ defaultLogLevel = (levelToSet || '').toLowerCase();
36
+
37
+ successCallback("");
38
38
  }
39
39
 
40
40
  module.exports.getLogLevel = function(successCallback, errorCallback) {
@@ -3,6 +3,35 @@ const path = require('path');
3
3
  const fs = require('fs');
4
4
  const fsPromises = fs.promises;
5
5
 
6
+ // --- Proper async lock for log file operations ---
7
+ let logLockPromise = Promise.resolve();
8
+ let isLocked = false;
9
+
10
+ async function withLogLock(fn) {
11
+ // Wait for any existing lock to complete
12
+ await logLockPromise;
13
+
14
+ // Create a new promise for this operation
15
+ const operationPromise = (async () => {
16
+ try {
17
+ isLocked = true;
18
+ const result = await fn();
19
+ return result;
20
+ } catch (error) {
21
+ console.error('[Logger] Error in log operation:', error);
22
+ // Return error message instead of throwing to prevent unhandled promise rejections
23
+ return `Error in log operation: ${error.message}`;
24
+ } finally {
25
+ isLocked = false;
26
+ }
27
+ })();
28
+
29
+ // Update the lock promise to wait for this operation
30
+ logLockPromise = operationPromise;
31
+
32
+ return operationPromise;
33
+ }
34
+
6
35
  const LOG_FOLDER_NAME = 'log';
7
36
  const LOG_FILE_NAME = 'log.txt';
8
37
  const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
@@ -10,7 +39,7 @@ const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
10
39
  const LogLevel = {
11
40
  Debug: 'debug',
12
41
  Error: 'error',
13
- Info: 'info',
42
+ Info: 'important',
14
43
  };
15
44
 
16
45
  let defaultLogLevel = LogLevel.Info;
@@ -29,15 +58,11 @@ function logInfo(args) {
29
58
  }
30
59
 
31
60
  function setLogLevel(level) {
32
- return new Promise((resolve) => {
33
- // If level is an array (from Cordova), extract the first element
34
- if (Array.isArray(level)) {
35
- defaultLogLevel = level[0];
36
- } else {
37
- defaultLogLevel = level;
38
- }
39
- resolve();
40
- });
61
+ // If level is an array (from Cordova), extract the first element
62
+ let levelToSet = Array.isArray(level) ? level[0] : level;
63
+
64
+ // Normalize the level to lowercase for consistency
65
+ defaultLogLevel = (levelToSet || '').toLowerCase();
41
66
  }
42
67
 
43
68
  function getLogLevel() {
@@ -68,14 +93,10 @@ function getLogFileContent(args) {
68
93
  }
69
94
 
70
95
  function clearLogFile(args) {
71
- return new Promise(async (resolve, reject) => {
72
- try {
73
- const logPath = getLogFileURL(args);
74
- await fsPromises.writeFile(logPath, '');
75
- resolve();
76
- } catch (err) {
77
- reject(new Error(`Failed to clear log file: ${err.message}`));
78
- }
96
+ return withLogLock(async () => {
97
+ const logPath = getLogFileURL(args);
98
+ await fsPromises.writeFile(logPath, '');
99
+ return 'Log file cleared successfully';
79
100
  });
80
101
  }
81
102
 
@@ -101,69 +122,58 @@ function getBackupLogFileContent(args) {
101
122
  }
102
123
 
103
124
  function copyLogToBackup(args) {
104
- return new Promise(async (resolve, reject) => {
105
- try {
106
- const logPath = getLogFileURL(args);
107
- const backupPath = getBackupLogFileURL(args);
108
- await fsPromises.copyFile(logPath, backupPath);
109
- resolve();
110
- } catch (err) {
111
- reject(new Error(`Failed to copy log file to backup: ${err.message}`));
112
- }
125
+ return withLogLock(async () => {
126
+ const logPath = getLogFileURL(args);
127
+ const backupPath = getBackupLogFileURL(args);
128
+ await fsPromises.copyFile(logPath, backupPath);
129
+ return 'Log file copied to backup successfully';
113
130
  });
114
131
  }
115
132
 
116
133
  function loggerWithLevel(args) {
117
- return new Promise(async (resolve, reject) => {
118
- try {
119
-
120
- if (!args || !args[0]) {
121
- return reject(new Error("Invalid arguments provided"));
122
- }
123
- const { userId, level, sourceClass, sourceMethod, message } = args[0];
124
- if (!userId) return reject(new Error("userId is required"));
125
- if (!level) return reject(new Error("level is required"));
126
- if (!message) return reject(new Error("message is required"));
127
-
128
- // Normalize log levels for comparison
129
- const normalizedDefaultLogLevel = (defaultLogLevel || '').toLowerCase();
130
- const normalizedLevel = (level || '').toLowerCase();
131
-
132
- // Log level filtering using normalized values
133
- if (
134
- (normalizedDefaultLogLevel === LogLevel.Error && (normalizedLevel === LogLevel.Debug || normalizedLevel === LogLevel.Info)) ||
135
- (normalizedDefaultLogLevel === LogLevel.Info && normalizedLevel === LogLevel.Debug)
136
- ) {
137
- return resolve();
138
- }
139
-
140
- await checkAndRotateLogFile(args);
134
+ return withLogLock(async () => {
135
+ if (!args || !args[0]) throw new Error("Invalid arguments provided");
136
+ const { userId, level, sourceClass, sourceMethod, message } = args[0];
137
+ if (!userId) throw new Error("userId is required");
138
+ if (!level) throw new Error("level is required");
139
+ if (!message) throw new Error("message is required");
140
+
141
+ // Normalize log levels for comparison
142
+ const normalizedDefaultLogLevel = (defaultLogLevel || '').toLowerCase();
143
+ const normalizedLevel = (level || '').toLowerCase();
144
+
145
+ // Log level filtering using normalized values
146
+ if (
147
+ (normalizedDefaultLogLevel === LogLevel.Error && (normalizedLevel === LogLevel.Debug || normalizedLevel === LogLevel.Info)) ||
148
+ (normalizedDefaultLogLevel === LogLevel.Info && normalizedLevel === LogLevel.Debug)
149
+ ) {
150
+ return;
151
+ }
141
152
 
142
- const logPath = getLogFileURL(args);
143
- const currentDate = new Date();
144
- const formatter = new Intl.DateTimeFormat('en-US', {
145
- day: '2-digit', month: '2-digit', year: 'numeric',
146
- hour: '2-digit', minute: '2-digit', second: '2-digit'
147
- });
148
- const localDateString = formatter.format(currentDate);
149
-
150
- const dateUtc = new Date(currentDate.toUTCString());
151
- const utcFormatter = new Intl.DateTimeFormat('en-US', {
152
- day: '2-digit', month: '2-digit', year: 'numeric',
153
- hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC'
154
- });
155
- const utcDateString = utcFormatter.format(dateUtc);
156
-
157
- let data = `${localDateString} | UTC:${utcDateString} | ${getStringFromLevel(level)} | ${sourceClass} | ${sourceMethod} | ${message}\n`;
158
- if (level === LogLevel.Error) {
159
- data = `⭕️⭕️⭕️ ${data}`;
160
- }
161
- console.log(data);
162
- await fsPromises.appendFile(logPath, data, 'utf8');
163
- resolve(`Logged to ${logPath}`);
164
- } catch (err) {
165
- reject(new Error(`Logging failed: ${err.message}`));
153
+ await checkAndRotateLogFile(args);
154
+
155
+ const logPath = getLogFileURL(args);
156
+ const currentDate = new Date();
157
+ const formatter = new Intl.DateTimeFormat('en-US', {
158
+ day: '2-digit', month: '2-digit', year: 'numeric',
159
+ hour: '2-digit', minute: '2-digit', second: '2-digit'
160
+ });
161
+ const localDateString = formatter.format(currentDate);
162
+
163
+ const dateUtc = new Date(currentDate.toUTCString());
164
+ const utcFormatter = new Intl.DateTimeFormat('en-US', {
165
+ day: '2-digit', month: '2-digit', year: 'numeric',
166
+ hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC'
167
+ });
168
+ const utcDateString = utcFormatter.format(dateUtc);
169
+
170
+ let data = `${localDateString} | UTC:${utcDateString} | ${getStringFromLevel(level)} | ${sourceClass} | ${sourceMethod} | ${message}\n`;
171
+ if (level === LogLevel.Error) {
172
+ data = `⭕️⭕️⭕️ ${data}`;
166
173
  }
174
+ console.log(data);
175
+ await fsPromises.appendFile(logPath, data, 'utf8');
176
+ return `Logged to ${logPath}`;
167
177
  });
168
178
  }
169
179
 
@@ -190,21 +200,18 @@ function getStringFromLevel(level) {
190
200
  }
191
201
 
192
202
  function checkAndRotateLogFile(args) {
193
- return new Promise(async (resolve, reject) => {
194
- try {
195
- const logPath = getLogFileURL(args);
196
- if (fs.existsSync(logPath)) {
197
- const stats = await fsPromises.stat(logPath);
198
- if (stats.size > MAX_LOG_SIZE) {
199
- const backupPath = getBackupLogFileURL(args);
200
- await fsPromises.copyFile(logPath, backupPath);
201
- await fsPromises.writeFile(logPath, '');
202
- }
203
+ return withLogLock(async () => {
204
+ const logPath = getLogFileURL(args);
205
+ if (fs.existsSync(logPath)) {
206
+ const stats = await fsPromises.stat(logPath);
207
+ if (stats.size > MAX_LOG_SIZE) {
208
+ const backupPath = getBackupLogFileURL(args);
209
+ await fsPromises.copyFile(logPath, backupPath);
210
+ await fsPromises.writeFile(logPath, '');
211
+ return 'Log file rotated due to size limit';
203
212
  }
204
- resolve();
205
- } catch (err) {
206
- reject(new Error(`Failed to rotate log file: ${err.message}`));
207
213
  }
214
+ return 'Log file rotation check completed';
208
215
  });
209
216
  }
210
217
 
@@ -8,7 +8,7 @@ import UIKit
8
8
  private let BACKUP_LOG_FILE_NAME = "log_backup.txt"
9
9
  private let MAX_LOG_SIZE: Int64 = 5 * 1024 * 1024 // 5MB
10
10
 
11
- private var defaultLogLevel: String = "info"
11
+ private var defaultLogLevel: String = "important"
12
12
 
13
13
  @objc(logDebug:)
14
14
  func logDebug(_ command: CDVInvokedUrlCommand) {
@@ -193,10 +193,10 @@ import UIKit
193
193
  let normLevel = level.lowercased()
194
194
  let normDefault = defaultLogLevel.lowercased()
195
195
 
196
- if normDefault == "error" && (normLevel == "debug" || normLevel == "info") {
196
+ if normDefault == "error" && (normLevel == "debug" || normLevel == "important") {
197
197
  return true
198
198
  }
199
- if normDefault == "info" && normLevel == "debug" {
199
+ if normDefault == "important" && normLevel == "debug" {
200
200
  return true
201
201
  }
202
202
  return false
@@ -251,7 +251,7 @@ import UIKit
251
251
 
252
252
  private func getStringFromLevel(level: String) -> String {
253
253
  switch level.lowercased() {
254
- case "info": return "IMPORTANT"
254
+ case "important": return "IMPORTANT"
255
255
  case "error": return "ERROR"
256
256
  case "debug": return "DEBUG"
257
257
  default: return ""
package/www/logger.js CHANGED
@@ -4,7 +4,7 @@ var exec = require('cordova/exec');
4
4
  exports.LogLevel = {
5
5
  Debug: 'debug',
6
6
  Error: 'error',
7
- Info: 'info'
7
+ Info: 'important'
8
8
  };
9
9
 
10
10
  /**