cordova-plugin-unvired-logger 0.0.1

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.
@@ -0,0 +1,242 @@
1
+ const LOG_FOLDER_NAME = 'AppLogs';
2
+ const LOG_FILE_NAME = 'log.txt';
3
+ const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
4
+ const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
5
+
6
+ const LogLevel = {
7
+ Debug: 'debug',
8
+ Error: 'error',
9
+ Info: 'info',
10
+ };
11
+
12
+ let defaultLogLevel = LogLevel.Info;
13
+
14
+ // Browser storage keys
15
+ const getStorageKey = (userId, fileName) => `unvired_logger_${userId}_${fileName}`;
16
+ const getLogLevelKey = (userId) => `unvired_logger_${userId}_level`;
17
+
18
+ function logDebug(args) {
19
+ return loggerWithLevel(args);
20
+ }
21
+
22
+ function logError(args) {
23
+ return loggerWithLevel(args);
24
+ }
25
+
26
+ function logInfo(args) {
27
+ return loggerWithLevel(args);
28
+ }
29
+
30
+ function setLogLevel(level) {
31
+ return new Promise((resolve) => {
32
+ // If level is an array (from Cordova), extract the first element
33
+ if (Array.isArray(level)) {
34
+ defaultLogLevel = level[0];
35
+ } else {
36
+ defaultLogLevel = level;
37
+ }
38
+ resolve();
39
+ });
40
+ }
41
+
42
+ function getLogLevel() {
43
+ return new Promise((resolve) => {
44
+ resolve(defaultLogLevel);
45
+ });
46
+ }
47
+
48
+ function getLogFileURL(args) {
49
+ // In browser, we return a data URL or storage reference
50
+ return `browser://${getStorageKey(args[0].userId, LOG_FILE_NAME)}`;
51
+ }
52
+
53
+ function getLogFileContent(args) {
54
+ return new Promise((resolve, reject) => {
55
+ try {
56
+ const userId = args[0].userId;
57
+ const storageKey = getStorageKey(userId, LOG_FILE_NAME);
58
+ const content = localStorage.getItem(storageKey) || '';
59
+ resolve(content);
60
+ } catch (err) {
61
+ reject(new Error(`Failed to read log file: ${err.message}`));
62
+ }
63
+ });
64
+ }
65
+
66
+ function clearLogFile(args) {
67
+ return new Promise((resolve, reject) => {
68
+ try {
69
+ const userId = args[0].userId;
70
+ const storageKey = getStorageKey(userId, LOG_FILE_NAME);
71
+ localStorage.removeItem(storageKey);
72
+ resolve();
73
+ } catch (err) {
74
+ reject(new Error(`Failed to clear log file: ${err.message}`));
75
+ }
76
+ });
77
+ }
78
+
79
+ function getBackupLogFileURL(args) {
80
+ return `browser://${getStorageKey(args[0].userId, BACKUP_LOG_FILE_NAME)}`;
81
+ }
82
+
83
+ function getBackupLogFileContent(args) {
84
+ return new Promise((resolve, reject) => {
85
+ try {
86
+ const userId = args[0].userId;
87
+ const storageKey = getStorageKey(userId, BACKUP_LOG_FILE_NAME);
88
+ const content = localStorage.getItem(storageKey) || '';
89
+ resolve(content);
90
+ } catch (err) {
91
+ reject(new Error(`Failed to read backup log file: ${err.message}`));
92
+ }
93
+ });
94
+ }
95
+
96
+ function copyLogToBackup(args) {
97
+ return new Promise((resolve, reject) => {
98
+ try {
99
+ const userId = args[0].userId;
100
+ const logStorageKey = getStorageKey(userId, LOG_FILE_NAME);
101
+ const backupStorageKey = getStorageKey(userId, BACKUP_LOG_FILE_NAME);
102
+ const logContent = localStorage.getItem(logStorageKey) || '';
103
+ localStorage.setItem(backupStorageKey, logContent);
104
+ resolve();
105
+ } catch (err) {
106
+ reject(new Error(`Failed to copy log file to backup: ${err.message}`));
107
+ }
108
+ });
109
+ }
110
+
111
+ function loggerWithLevel(args) {
112
+ return new Promise(async (resolve, reject) => {
113
+ try {
114
+ if (!args || !args[0]) {
115
+ return reject(new Error("Invalid arguments provided"));
116
+ }
117
+
118
+ const { userId, level, sourceClass, sourceMethod, message } = args[0];
119
+
120
+ if (!userId) return reject(new Error("userId is required"));
121
+ if (!level) return reject(new Error("level is required"));
122
+ if (!message) return reject(new Error("message is required"));
123
+
124
+ // Normalize log levels for comparison
125
+ const normalizedDefaultLogLevel = (defaultLogLevel || '').toLowerCase();
126
+ const normalizedLevel = (level || '').toLowerCase();
127
+
128
+ // Log level filtering using normalized values
129
+ if (
130
+ (normalizedDefaultLogLevel === LogLevel.Error && (normalizedLevel === LogLevel.Debug || normalizedLevel === LogLevel.Info)) ||
131
+ (normalizedDefaultLogLevel === LogLevel.Info && normalizedLevel === LogLevel.Debug)
132
+ ) {
133
+ return resolve();
134
+ }
135
+
136
+ await checkAndRotateLogFile(args);
137
+
138
+ const currentDate = new Date();
139
+ const formatter = new Intl.DateTimeFormat('en-US', {
140
+ day: '2-digit', month: '2-digit', year: 'numeric',
141
+ hour: '2-digit', minute: '2-digit', second: '2-digit'
142
+ });
143
+ const localDateString = formatter.format(currentDate);
144
+
145
+ const dateUtc = new Date(currentDate.toUTCString());
146
+ const utcFormatter = new Intl.DateTimeFormat('en-US', {
147
+ day: '2-digit', month: '2-digit', year: 'numeric',
148
+ hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC'
149
+ });
150
+ const utcDateString = utcFormatter.format(dateUtc);
151
+
152
+ let data = `${localDateString} | UTC:${utcDateString} | ${getStringFromLevel(level)} | ${sourceClass} | ${sourceMethod} | ${message}\n`;
153
+ if (level === LogLevel.Error) {
154
+ data = `⭕️⭕️⭕️ ${data}`;
155
+ }
156
+
157
+ // Log to console for browser debugging
158
+ console.log(data);
159
+
160
+ // Store in localStorage
161
+ const storageKey = getStorageKey(userId, LOG_FILE_NAME);
162
+ const existingContent = localStorage.getItem(storageKey) || '';
163
+ const newContent = existingContent + data;
164
+
165
+ // Check size limit
166
+ if (newContent.length > MAX_LOG_SIZE) {
167
+ // If content is too large, truncate it
168
+ const truncatedContent = newContent.substring(newContent.length - MAX_LOG_SIZE / 2);
169
+ localStorage.setItem(storageKey, truncatedContent);
170
+ } else {
171
+ localStorage.setItem(storageKey, newContent);
172
+ }
173
+
174
+ resolve(`Logged to browser storage: ${storageKey}`);
175
+ } catch (err) {
176
+ reject(new Error(`Logging failed: ${err.message}`));
177
+ }
178
+ });
179
+ }
180
+
181
+ function getStringFromLevel(level) {
182
+ switch (level) {
183
+ case LogLevel.Info: return 'IMPORTANT';
184
+ case LogLevel.Error: return 'ERROR';
185
+ case LogLevel.Debug: return 'DEBUG';
186
+ default: return '';
187
+ }
188
+ }
189
+
190
+ function checkAndRotateLogFile(args) {
191
+ return new Promise(async (resolve, reject) => {
192
+ try {
193
+ const userId = args[0].userId;
194
+ const storageKey = getStorageKey(userId, LOG_FILE_NAME);
195
+ const content = localStorage.getItem(storageKey) || '';
196
+
197
+ if (content.length > MAX_LOG_SIZE) {
198
+ const backupStorageKey = getStorageKey(userId, BACKUP_LOG_FILE_NAME);
199
+ localStorage.setItem(backupStorageKey, content);
200
+ localStorage.setItem(storageKey, '');
201
+ }
202
+ resolve();
203
+ } catch (err) {
204
+ reject(new Error(`Failed to rotate log file: ${err.message}`));
205
+ }
206
+ });
207
+ }
208
+
209
+ // Export for browser environment
210
+ if (typeof module !== 'undefined' && module.exports) {
211
+ module.exports = {
212
+ logDebug,
213
+ logError,
214
+ logInfo,
215
+ setLogLevel,
216
+ getLogLevel,
217
+ getLogFileContent,
218
+ clearLogFile,
219
+ getBackupLogFileContent,
220
+ LogLevel,
221
+ copyLogToBackup,
222
+ getLogFileURL,
223
+ getBackupLogFileURL,
224
+ };
225
+ } else if (typeof window !== 'undefined') {
226
+ // Browser environment
227
+ window.UnviredLogger = {
228
+ logDebug,
229
+ logError,
230
+ logInfo,
231
+ setLogLevel,
232
+ getLogLevel,
233
+ getLogFileContent,
234
+ clearLogFile,
235
+ getBackupLogFileContent,
236
+ LogLevel,
237
+ copyLogToBackup,
238
+ getLogFileURL,
239
+ getBackupLogFileURL,
240
+ };
241
+ window.Logger = window.UnviredLogger;
242
+ }
@@ -0,0 +1,224 @@
1
+ const { app } = require('electron');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const fsPromises = fs.promises;
5
+
6
+ const LOG_FOLDER_NAME = 'log';
7
+ const LOG_FILE_NAME = 'log.txt';
8
+ const BACKUP_LOG_FILE_NAME = 'log_backup.txt';
9
+
10
+ const LogLevel = {
11
+ Debug: 'debug',
12
+ Error: 'error',
13
+ Info: 'info',
14
+ };
15
+
16
+ let defaultLogLevel = LogLevel.Info;
17
+ const MAX_LOG_SIZE = 5 * 1024 * 1024; // 5MB
18
+
19
+ function logDebug(args) {
20
+ return loggerWithLevel(args);
21
+ }
22
+
23
+ function logError(args) {
24
+ return loggerWithLevel(args);
25
+ }
26
+
27
+ function logInfo(args) {
28
+ return loggerWithLevel(args);
29
+ }
30
+
31
+ 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
+ });
41
+ }
42
+
43
+ function getLogLevel() {
44
+ return new Promise((resolve) => {
45
+ resolve(defaultLogLevel);
46
+ });
47
+ }
48
+
49
+ function getLogFileURL(args) {
50
+ const userPath = getLogDirectory(args);
51
+ return path.join(userPath, LOG_FILE_NAME);
52
+ }
53
+
54
+ function getLogFileContent(args) {
55
+ return new Promise(async (resolve, reject) => {
56
+ try {
57
+ const logPath = getLogFileURL(args);
58
+ if (fs.existsSync(logPath)) {
59
+ const content = await fsPromises.readFile(logPath, 'utf8');
60
+ resolve(content);
61
+ } else {
62
+ resolve('');
63
+ }
64
+ } catch (err) {
65
+ reject(new Error(`Failed to read log file: ${err.message}`));
66
+ }
67
+ });
68
+ }
69
+
70
+ 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
+ }
79
+ });
80
+ }
81
+
82
+ function getBackupLogFileURL(args) {
83
+ const userPath = getLogDirectory(args);
84
+ return path.join(userPath, BACKUP_LOG_FILE_NAME);
85
+ }
86
+
87
+ function getBackupLogFileContent(args) {
88
+ return new Promise(async (resolve, reject) => {
89
+ try {
90
+ const backupPath = getBackupLogFileURL(args);
91
+ if (fs.existsSync(backupPath)) {
92
+ const content = await fsPromises.readFile(backupPath, 'utf8');
93
+ resolve(content);
94
+ } else {
95
+ resolve('');
96
+ }
97
+ } catch (err) {
98
+ reject(new Error(`Failed to read backup log file: ${err.message}`));
99
+ }
100
+ });
101
+ }
102
+
103
+ 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
+ }
113
+ });
114
+ }
115
+
116
+ 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);
141
+
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}`));
166
+ }
167
+ });
168
+ }
169
+
170
+ function getLogDirectory(args) {
171
+ if (!args || !args[0] || !args[0].userId) {
172
+ throw new Error("userId is required");
173
+ }
174
+ const userId = args[0].userId;
175
+ const userDataPath = app.getPath('userData');
176
+ const userPath = path.join(userDataPath, userId, LOG_FOLDER_NAME);
177
+ if (!fs.existsSync(userPath)) {
178
+ fs.mkdirSync(userPath, { recursive: true });
179
+ }
180
+ return userPath;
181
+ }
182
+
183
+ function getStringFromLevel(level) {
184
+ switch (level) {
185
+ case LogLevel.Info: return 'IMPORTANT';
186
+ case LogLevel.Error: return 'ERROR';
187
+ case LogLevel.Debug: return 'DEBUG';
188
+ default: return '';
189
+ }
190
+ }
191
+
192
+ 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
+ }
204
+ resolve();
205
+ } catch (err) {
206
+ reject(new Error(`Failed to rotate log file: ${err.message}`));
207
+ }
208
+ });
209
+ }
210
+
211
+ module.exports = {
212
+ logDebug,
213
+ logError,
214
+ logInfo,
215
+ setLogLevel,
216
+ getLogLevel,
217
+ getLogFileContent,
218
+ clearLogFile,
219
+ getBackupLogFileContent,
220
+ LogLevel,
221
+ copyLogToBackup,
222
+ getLogFileURL,
223
+ getBackupLogFileURL,
224
+ };
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "cordova-plugin-unvired-logger",
3
+ "version": "@PACKAGE_NUMBER@",
4
+ "description": "Electron platform package for cordova-plugin-unvired-logger",
5
+ "main": "Logger.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [
10
+ "electron",
11
+ "cordova",
12
+ "plugin",
13
+ "logger"
14
+ ],
15
+ "cordova": {
16
+ "serviceName": "UnviredLogger"
17
+ },
18
+ "author": "Unvired Inc",
19
+ "license": "MIT",
20
+ "dependencies": {
21
+ "electron": ">=20.0.0"
22
+ },
23
+ "devDependencies": {},
24
+ "engines": {
25
+ "node": ">=14.0.0",
26
+ "electron": ">=20.0.0"
27
+ },
28
+ "peerDependencies": {
29
+ "electron": ">=20.0.0"
30
+ }
31
+ }