@unvired/react-native-unvired-sdk 0.0.9 → 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/BuildNo.txt +1 -1
- package/README.md +18 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -0
- package/dist/logger/BaseLogger.d.ts +6 -5
- package/dist/logger/BaseLogger.js +6 -5
- package/dist/logger/Logger.d.ts +2 -1
- package/dist/logger/Logger.js +5 -0
- package/dist/logger/Logger.types.d.ts +34 -0
- package/dist/logger/Logger.types.js +3 -0
- package/dist/logger/services/LoggerNative.d.ts +17 -0
- package/dist/logger/services/LoggerNative.js +217 -0
- package/dist/logger/services/LoggerWeb.d.ts +10 -0
- package/dist/logger/{LoggerWeb.js → services/LoggerWeb.js} +5 -3
- package/package.json +6 -13
- package/dist/logger/LoggerNative.d.ts +0 -15
- package/dist/logger/LoggerNative.js +0 -84
- package/dist/logger/LoggerWeb.d.ts +0 -8
- package/dist/logger/LoggerWindows.d.ts +0 -10
- package/dist/logger/LoggerWindows.js +0 -44
- package/example/PlatformInterface.ts +0 -11
- package/example/ReactNativePlatformAdapter.ts +0 -40
package/BuildNo.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
R-0.000.
|
|
1
|
+
R-0.000.0011
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ The **logger works out of the box** with zero dependencies. For additional featu
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
# For file operations
|
|
19
|
-
npm install react-native-fs
|
|
19
|
+
npm install @dr.pogodin/react-native-fs
|
|
20
20
|
|
|
21
21
|
# For database (choose one)
|
|
22
22
|
npm install react-native-sqlite-storage # SQL database
|
|
@@ -28,6 +28,23 @@ npm install @notifee/react-native
|
|
|
28
28
|
|
|
29
29
|
> **See [NPM_PACKAGES.md](./NPM_PACKAGES.md) for detailed package information and implementation guide.**
|
|
30
30
|
|
|
31
|
+
### Troubleshooting
|
|
32
|
+
|
|
33
|
+
If you encounter errors like:
|
|
34
|
+
- `Cannot read property 'RNFSFileTypeRegular' of null`
|
|
35
|
+
- `Cannot read property 'PlatformManager' of undefined`
|
|
36
|
+
- Native module linking issues
|
|
37
|
+
|
|
38
|
+
**See [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) for detailed solutions.**
|
|
39
|
+
|
|
40
|
+
The SDK now includes defensive checks and will gracefully handle missing native modules with helpful error messages in the console.
|
|
41
|
+
|
|
42
|
+
### Migration from react-native-fs
|
|
43
|
+
|
|
44
|
+
> **Note:** We now use `@dr.pogodin/react-native-fs` (actively maintained fork) instead of the deprecated `react-native-fs`.
|
|
45
|
+
>
|
|
46
|
+
> If you're upgrading from an older version, see [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md) for step-by-step instructions.
|
|
47
|
+
|
|
31
48
|
## Features
|
|
32
49
|
|
|
33
50
|
- 📝 **Logger** - Comprehensive logging with multiple log levels ✅ **No dependencies**
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { LogLevel } from './Logger.types';
|
|
2
|
+
export type { LogLevel };
|
|
2
3
|
export declare const MAX_LOG_SIZE: number;
|
|
3
4
|
export declare class BaseLogger {
|
|
4
5
|
private impl;
|
|
@@ -11,8 +12,8 @@ export declare class BaseLogger {
|
|
|
11
12
|
logDebug(c: string, m: string, msg: string): void;
|
|
12
13
|
logInfo(c: string, m: string, msg: string): void;
|
|
13
14
|
logError(c: string, m: string, msg: string): void;
|
|
14
|
-
getLogFileURL():
|
|
15
|
-
getLogFileContent():
|
|
16
|
-
getBackupLogFileContent():
|
|
17
|
-
clearLogFile():
|
|
15
|
+
getLogFileURL(): Promise<string>;
|
|
16
|
+
getLogFileContent(): Promise<string>;
|
|
17
|
+
getBackupLogFileContent(): Promise<string | null>;
|
|
18
|
+
clearLogFile(): Promise<void>;
|
|
18
19
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// BaseLogger.ts
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
|
-
import { LoggerNative } from './LoggerNative';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const MAX_LOG_SIZE = 1 * 1024 * 1024;
|
|
3
|
+
import { LoggerNative } from './services/LoggerNative';
|
|
4
|
+
import { LoggerWeb } from './services/LoggerWeb';
|
|
5
|
+
export const MAX_LOG_SIZE = 100 * 1024 * 1024;
|
|
7
6
|
export class BaseLogger {
|
|
8
7
|
constructor() {
|
|
9
8
|
this.logLevel = 'info';
|
|
@@ -11,7 +10,9 @@ export class BaseLogger {
|
|
|
11
10
|
this.impl = new LoggerWeb();
|
|
12
11
|
}
|
|
13
12
|
else if (Platform.OS === 'windows') {
|
|
14
|
-
//
|
|
13
|
+
// TODO: Implement LoggerWindows
|
|
14
|
+
console.warn('Windows logger not implemented yet, using web logger');
|
|
15
|
+
this.impl = new LoggerWeb();
|
|
15
16
|
}
|
|
16
17
|
else {
|
|
17
18
|
this.impl = new LoggerNative();
|
package/dist/logger/Logger.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ import { BaseLogger, LogLevel } from './BaseLogger';
|
|
|
2
2
|
export declare class Logger extends BaseLogger {
|
|
3
3
|
}
|
|
4
4
|
export declare const logger: Logger;
|
|
5
|
-
export {
|
|
5
|
+
export type { ILogger, ILoggerImplementation, } from './Logger.types';
|
|
6
|
+
export type { LogLevel };
|
|
6
7
|
export default logger;
|
package/dist/logger/Logger.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
// Logger.ts
|
|
2
2
|
import { BaseLogger } from './BaseLogger';
|
|
3
|
+
// Export the Logger class
|
|
3
4
|
export class Logger extends BaseLogger {
|
|
4
5
|
}
|
|
6
|
+
// Export the singleton logger instance
|
|
5
7
|
export const logger = new Logger();
|
|
6
8
|
// Default export (logger instance)
|
|
7
9
|
export default logger;
|
|
10
|
+
// adb shell
|
|
11
|
+
// run-as com.rnturboapp
|
|
12
|
+
// ls -lh files/localLogs
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log levels supported by the logger
|
|
3
|
+
*/
|
|
4
|
+
export type LogLevel = 'debug' | 'info' | 'error' | 'none';
|
|
5
|
+
/**
|
|
6
|
+
* Interface for platform-specific logger implementations
|
|
7
|
+
* This interface must be implemented by LoggerNative, LoggerWindows, and LoggerWeb
|
|
8
|
+
*/
|
|
9
|
+
export interface ILoggerImplementation {
|
|
10
|
+
logDir?: string;
|
|
11
|
+
logFile: string;
|
|
12
|
+
tempFile?: string;
|
|
13
|
+
backupZip?: string;
|
|
14
|
+
init(): Promise<void>;
|
|
15
|
+
writeLine(line: string, maxSize: number): Promise<void>;
|
|
16
|
+
getLogFileURL(): Promise<string>;
|
|
17
|
+
getLogFileContent(): Promise<string>;
|
|
18
|
+
getBackupLogFileContent(): Promise<string | null>;
|
|
19
|
+
clear(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Public API interface for the logger
|
|
23
|
+
* This is what consumers of the logger package should use
|
|
24
|
+
*/
|
|
25
|
+
export interface ILogger {
|
|
26
|
+
setLogLevel(level: LogLevel): void;
|
|
27
|
+
logDebug(className: string, methodName: string, message: string): void;
|
|
28
|
+
logInfo(className: string, methodName: string, message: string): void;
|
|
29
|
+
logError(className: string, methodName: string, message: string): void;
|
|
30
|
+
getLogFileURL(): Promise<string>;
|
|
31
|
+
getLogFileContent(): Promise<string>;
|
|
32
|
+
getBackupLogFileContent(): Promise<string | null>;
|
|
33
|
+
clearLogFile(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ILoggerImplementation } from '../Logger.types';
|
|
2
|
+
export declare class LoggerNative implements ILoggerImplementation {
|
|
3
|
+
logDir: string;
|
|
4
|
+
logFile: string;
|
|
5
|
+
backupZip: string;
|
|
6
|
+
private isRotating;
|
|
7
|
+
private isAvailable;
|
|
8
|
+
constructor();
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
writeLine(line: string, maxSize: number): Promise<void>;
|
|
11
|
+
private ensureDir;
|
|
12
|
+
private rotateLog;
|
|
13
|
+
getLogFileURL(): Promise<string>;
|
|
14
|
+
getLogFileContent(): Promise<any>;
|
|
15
|
+
getBackupLogFileContent(): Promise<any>;
|
|
16
|
+
clear(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// LoggerNative.ts
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
// Import with null safety
|
|
4
|
+
let RNFS = null;
|
|
5
|
+
let zip = null;
|
|
6
|
+
try {
|
|
7
|
+
RNFS = require('@dr.pogodin/react-native-fs');
|
|
8
|
+
if (!RNFS || !RNFS.DocumentDirectoryPath) {
|
|
9
|
+
console.error('❌ @dr.pogodin/react-native-fs is not properly linked. Please run: cd ios && pod install (iOS) or rebuild your Android app.');
|
|
10
|
+
RNFS = null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
console.error('❌ @dr.pogodin/react-native-fs module not found. Please install: npm install @dr.pogodin/react-native-fs');
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const zipModule = require('react-native-zip-archive');
|
|
18
|
+
zip = zipModule.zip;
|
|
19
|
+
if (!zip) {
|
|
20
|
+
console.error('❌ react-native-zip-archive is not properly linked. Please run: cd ios && pod install (iOS) or rebuild your Android app.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
console.error('❌ react-native-zip-archive module not found. Please install: npm install react-native-zip-archive');
|
|
25
|
+
}
|
|
26
|
+
export class LoggerNative {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.isRotating = false; // Rotation lock to prevent concurrent rotations
|
|
29
|
+
this.isAvailable = false;
|
|
30
|
+
const dir = 'unvired_logs_local';
|
|
31
|
+
const file = 'applog_local.txt'; // main log file
|
|
32
|
+
if (!RNFS) {
|
|
33
|
+
console.warn('⚠️ LoggerNative: RNFS not available, logging to file system disabled');
|
|
34
|
+
this.logDir = '';
|
|
35
|
+
this.logFile = '';
|
|
36
|
+
this.backupZip = '';
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.isAvailable = true;
|
|
40
|
+
if (Platform.OS === 'android') {
|
|
41
|
+
this.logDir = `${RNFS.DocumentDirectoryPath}/${dir}`;
|
|
42
|
+
}
|
|
43
|
+
else if (Platform.OS === 'ios') {
|
|
44
|
+
this.logDir = `${RNFS.LibraryDirectoryPath}/${dir}`;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.logDir = '';
|
|
48
|
+
}
|
|
49
|
+
this.logFile = `${this.logDir}/${file}`;
|
|
50
|
+
this.backupZip = `${this.logDir}/backuplog_local.zip`;
|
|
51
|
+
}
|
|
52
|
+
async init() {
|
|
53
|
+
if (!this.isAvailable || !this.logDir || !RNFS)
|
|
54
|
+
return;
|
|
55
|
+
try {
|
|
56
|
+
if (!(await RNFS.exists(this.logDir)))
|
|
57
|
+
await RNFS.mkdir(this.logDir);
|
|
58
|
+
if (!(await RNFS.exists(this.logFile)))
|
|
59
|
+
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
console.error('❌ LoggerNative init error:', e);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async writeLine(line, maxSize) {
|
|
66
|
+
if (!this.isAvailable || !RNFS)
|
|
67
|
+
return;
|
|
68
|
+
try {
|
|
69
|
+
await this.ensureDir();
|
|
70
|
+
await RNFS.appendFile(this.logFile, line + '\n', 'utf8');
|
|
71
|
+
// Only check for rotation if not already rotating
|
|
72
|
+
if (!this.isRotating) {
|
|
73
|
+
const stat = await RNFS.stat(this.logFile);
|
|
74
|
+
if (Number(stat.size) >= maxSize) {
|
|
75
|
+
// Don't await - let rotation happen in background
|
|
76
|
+
this.rotateLog();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
console.error('❌ LoggerNative writeLine error:', e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async ensureDir() {
|
|
85
|
+
if (!this.isAvailable || !this.logDir || !RNFS)
|
|
86
|
+
return;
|
|
87
|
+
try {
|
|
88
|
+
if (!(await RNFS.exists(this.logDir)))
|
|
89
|
+
await RNFS.mkdir(this.logDir);
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
console.error('❌ LoggerNative ensureDir error:', e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async rotateLog() {
|
|
96
|
+
if (!this.isAvailable || !RNFS || !zip) {
|
|
97
|
+
console.warn('⚠️ LoggerNative: Cannot rotate log, RNFS or zip not available');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Prevent concurrent rotations
|
|
101
|
+
if (this.isRotating) {
|
|
102
|
+
console.log('⏭️ Rotation already in progress, skipping...');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.isRotating = true;
|
|
106
|
+
try {
|
|
107
|
+
console.log('🔄 Starting log rotation...');
|
|
108
|
+
// Check if log file exists and get its size
|
|
109
|
+
if (!(await RNFS.exists(this.logFile))) {
|
|
110
|
+
console.log('⚠️ Log file does not exist, skipping rotation');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const stat = await RNFS.stat(this.logFile);
|
|
114
|
+
console.log(`📊 Current log file size: ${stat.size} bytes`);
|
|
115
|
+
// Step 1: Remove old backup.zip if it exists
|
|
116
|
+
if (await RNFS.exists(this.backupZip)) {
|
|
117
|
+
console.log('🗑️ Removing old backup.zip');
|
|
118
|
+
await RNFS.unlink(this.backupZip);
|
|
119
|
+
}
|
|
120
|
+
// Step 2: Create a temporary directory for zipping
|
|
121
|
+
// react-native-zip-archive requires a directory, not a single file
|
|
122
|
+
const tempZipDir = `${this.logDir}/temp_zip`;
|
|
123
|
+
if (await RNFS.exists(tempZipDir)) {
|
|
124
|
+
await RNFS.unlink(tempZipDir);
|
|
125
|
+
}
|
|
126
|
+
await RNFS.mkdir(tempZipDir);
|
|
127
|
+
// Step 3: Copy current log file into the temp directory
|
|
128
|
+
const tempFileInDir = `${tempZipDir}/applog.txt`;
|
|
129
|
+
console.log('📦 Copying log file to temp directory for zipping');
|
|
130
|
+
await RNFS.copyFile(this.logFile, tempFileInDir);
|
|
131
|
+
// Step 4: Zip the directory → backup.zip
|
|
132
|
+
console.log('🗜️ Creating backup.zip from current log');
|
|
133
|
+
await zip(tempZipDir, this.backupZip);
|
|
134
|
+
const zipStat = await RNFS.stat(this.backupZip);
|
|
135
|
+
console.log(`✅ Backup.zip created successfully (${zipStat.size} bytes)`);
|
|
136
|
+
// Step 5: Clean up temp directory
|
|
137
|
+
console.log('🧹 Cleaning up temp directory');
|
|
138
|
+
if (await RNFS.exists(tempZipDir)) {
|
|
139
|
+
await RNFS.unlink(tempZipDir);
|
|
140
|
+
}
|
|
141
|
+
// Step 6: Clear the current log file (make it fresh/empty)
|
|
142
|
+
console.log('📝 Clearing current log file');
|
|
143
|
+
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
144
|
+
console.log('✔ Log rotation completed successfully');
|
|
145
|
+
console.log('📂 Files: applog.txt (fresh) + backuplog.zip (old logs)');
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
console.error('❌ Logger rotation error:', e);
|
|
149
|
+
// Try to recover by creating a fresh log file if it doesn't exist
|
|
150
|
+
try {
|
|
151
|
+
if (!(await RNFS.exists(this.logFile))) {
|
|
152
|
+
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
153
|
+
console.log('🔧 Recovery: Created fresh log file');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (recoveryError) {
|
|
157
|
+
console.error('❌ Recovery failed:', recoveryError);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
// Always release the lock
|
|
162
|
+
this.isRotating = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// ------------------------
|
|
166
|
+
// Public accessors
|
|
167
|
+
// ------------------------
|
|
168
|
+
async getLogFileURL() {
|
|
169
|
+
if (!this.isAvailable)
|
|
170
|
+
return '';
|
|
171
|
+
return this.logFile;
|
|
172
|
+
}
|
|
173
|
+
async getLogFileContent() {
|
|
174
|
+
if (!this.isAvailable || !RNFS)
|
|
175
|
+
return '';
|
|
176
|
+
try {
|
|
177
|
+
if (await RNFS.exists(this.logFile)) {
|
|
178
|
+
return await RNFS.readFile(this.logFile, 'utf8');
|
|
179
|
+
}
|
|
180
|
+
return '';
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
console.error('❌ LoggerNative getLogFileContent error:', e);
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async getBackupLogFileContent() {
|
|
188
|
+
if (!this.isAvailable || !RNFS)
|
|
189
|
+
return null;
|
|
190
|
+
try {
|
|
191
|
+
// Force rotation to ensure current logs are zipped
|
|
192
|
+
await this.rotateLog();
|
|
193
|
+
if (await RNFS.exists(this.backupZip)) {
|
|
194
|
+
// Return base64 content for download/upload
|
|
195
|
+
return await RNFS.readFile(this.backupZip, 'base64');
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
console.error('❌ LoggerNative getBackupLogFileContent error:', e);
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async clear() {
|
|
205
|
+
if (!this.isAvailable || !RNFS)
|
|
206
|
+
return;
|
|
207
|
+
try {
|
|
208
|
+
if (await RNFS.exists(this.logFile))
|
|
209
|
+
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
210
|
+
if (await RNFS.exists(this.backupZip))
|
|
211
|
+
await RNFS.unlink(this.backupZip);
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
console.error('❌ LoggerNative clear error:', e);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ILoggerImplementation } from '../Logger.types';
|
|
2
|
+
export declare class LoggerWeb implements ILoggerImplementation {
|
|
3
|
+
logFile: string;
|
|
4
|
+
init(): Promise<void>;
|
|
5
|
+
writeLine(line: string, maxSize: number): Promise<void>;
|
|
6
|
+
getLogFileURL(): Promise<string>;
|
|
7
|
+
getLogFileContent(): Promise<string>;
|
|
8
|
+
getBackupLogFileContent(): Promise<null>;
|
|
9
|
+
clear(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
// LoggerWeb.ts
|
|
2
1
|
export class LoggerWeb {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.logFile = '';
|
|
4
|
+
}
|
|
3
5
|
async init() { }
|
|
4
|
-
async writeLine(line) {
|
|
6
|
+
async writeLine(line, maxSize) {
|
|
5
7
|
console.log(line);
|
|
6
8
|
}
|
|
7
9
|
async getLogFileURL() { return ''; }
|
|
8
10
|
async getLogFileContent() { return ''; }
|
|
9
|
-
async getBackupLogFileContent() { return
|
|
11
|
+
async getBackupLogFileContent() { return null; }
|
|
10
12
|
async clear() { }
|
|
11
13
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unvired/react-native-unvired-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "Unvired SDK for React Native with logging, database, notifications, and file system support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,17 +24,12 @@
|
|
|
24
24
|
"author": "Unvired",
|
|
25
25
|
"license": "UNLICENSED",
|
|
26
26
|
"peerDependencies": {
|
|
27
|
+
"@dr.pogodin/react-native-fs": "^2.36.2",
|
|
27
28
|
"react": ">=16.8.0",
|
|
28
29
|
"react-native": ">=0.60.0",
|
|
29
|
-
"react-native-
|
|
30
|
-
"react-native-zip-archive": "^7.0.2",
|
|
31
|
-
"@react-native-windows/fs": "^1.0.2"
|
|
32
|
-
},
|
|
33
|
-
"peerDependenciesMeta": {
|
|
34
|
-
"@react-native-windows/fs": {
|
|
35
|
-
"optional": true
|
|
36
|
-
}
|
|
30
|
+
"react-native-zip-archive": "^7.0.2"
|
|
37
31
|
},
|
|
32
|
+
"peerDependenciesMeta": {},
|
|
38
33
|
"devDependencies": {
|
|
39
34
|
"@types/react": "^18.0.0",
|
|
40
35
|
"@types/react-native": "^0.72.0",
|
|
@@ -43,9 +38,7 @@
|
|
|
43
38
|
"prettier": "^3.0.0",
|
|
44
39
|
"typescript": "^5.0.0"
|
|
45
40
|
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"jszip": "^3.10.1"
|
|
48
|
-
},
|
|
41
|
+
"dependencies": {},
|
|
49
42
|
"repository": {},
|
|
50
43
|
"bugs": {},
|
|
51
44
|
"volta": {
|
|
@@ -54,4 +47,4 @@
|
|
|
54
47
|
"publishConfig": {
|
|
55
48
|
"access": "public"
|
|
56
49
|
}
|
|
57
|
-
}
|
|
50
|
+
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export declare class LoggerNative {
|
|
2
|
-
logDir: string;
|
|
3
|
-
logFile: string;
|
|
4
|
-
tempFile: string;
|
|
5
|
-
backupZip: string;
|
|
6
|
-
constructor();
|
|
7
|
-
init(): Promise<void>;
|
|
8
|
-
writeLine(line: string, maxSize: number): Promise<void>;
|
|
9
|
-
private ensureDir;
|
|
10
|
-
rotateLog(): Promise<void>;
|
|
11
|
-
getLogFileURL(): Promise<string>;
|
|
12
|
-
getLogFileContent(): Promise<string>;
|
|
13
|
-
getBackupLogFileContent(): Promise<string | null>;
|
|
14
|
-
clear(): Promise<void>;
|
|
15
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// LoggerNative.ts
|
|
2
|
-
import RNFS from 'react-native-fs';
|
|
3
|
-
import { zip } from 'react-native-zip-archive';
|
|
4
|
-
import { Platform } from 'react-native';
|
|
5
|
-
export class LoggerNative {
|
|
6
|
-
constructor() {
|
|
7
|
-
const dir = 'unvired_logs';
|
|
8
|
-
const file = 'applog.txt'; // main log file
|
|
9
|
-
if (Platform.OS === 'android') {
|
|
10
|
-
this.logDir = `${RNFS.DocumentDirectoryPath}/${dir}`;
|
|
11
|
-
}
|
|
12
|
-
else if (Platform.OS === 'ios') {
|
|
13
|
-
this.logDir = `${RNFS.LibraryDirectoryPath}/${dir}`;
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
this.logDir = '';
|
|
17
|
-
}
|
|
18
|
-
this.logFile = `${this.logDir}/${file}`;
|
|
19
|
-
this.tempFile = `${this.logDir}/templog.txt`;
|
|
20
|
-
this.backupZip = `${this.logDir}/backuplog.zip`;
|
|
21
|
-
}
|
|
22
|
-
async init() {
|
|
23
|
-
if (!this.logDir)
|
|
24
|
-
return;
|
|
25
|
-
if (!(await RNFS.exists(this.logDir)))
|
|
26
|
-
await RNFS.mkdir(this.logDir);
|
|
27
|
-
if (!(await RNFS.exists(this.logFile)))
|
|
28
|
-
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
29
|
-
}
|
|
30
|
-
async writeLine(line, maxSize) {
|
|
31
|
-
await this.ensureDir();
|
|
32
|
-
await RNFS.appendFile(this.logFile, line + '\n', 'utf8');
|
|
33
|
-
const stat = await RNFS.stat(this.logFile);
|
|
34
|
-
if (Number(stat.size) >= maxSize) {
|
|
35
|
-
await this.rotateLog();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
async ensureDir() {
|
|
39
|
-
if (!this.logDir)
|
|
40
|
-
return;
|
|
41
|
-
if (!(await RNFS.exists(this.logDir)))
|
|
42
|
-
await RNFS.mkdir(this.logDir);
|
|
43
|
-
}
|
|
44
|
-
async rotateLog() {
|
|
45
|
-
try {
|
|
46
|
-
// Step 1: Move current log → temp
|
|
47
|
-
if (await RNFS.exists(this.tempFile))
|
|
48
|
-
await RNFS.unlink(this.tempFile);
|
|
49
|
-
await RNFS.moveFile(this.logFile, this.tempFile);
|
|
50
|
-
// Step 2: Remove old backup.zip
|
|
51
|
-
if (await RNFS.exists(this.backupZip))
|
|
52
|
-
await RNFS.unlink(this.backupZip);
|
|
53
|
-
// Step 3: Zip temp → backup.zip
|
|
54
|
-
await zip(this.tempFile, this.backupZip);
|
|
55
|
-
// Step 4: Clear main log file
|
|
56
|
-
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
57
|
-
// Step 5: Remove temp
|
|
58
|
-
if (await RNFS.exists(this.tempFile))
|
|
59
|
-
await RNFS.unlink(this.tempFile);
|
|
60
|
-
console.log('✔ Log rotated to backup.zip successfully');
|
|
61
|
-
}
|
|
62
|
-
catch (e) {
|
|
63
|
-
console.error('❌ Logger rotation error:', e);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// ------------------------
|
|
67
|
-
// Public accessors
|
|
68
|
-
// ------------------------
|
|
69
|
-
async getLogFileURL() {
|
|
70
|
-
return this.logFile;
|
|
71
|
-
}
|
|
72
|
-
async getLogFileContent() {
|
|
73
|
-
return (await RNFS.exists(this.logFile)) ? RNFS.readFile(this.logFile, 'utf8') : '';
|
|
74
|
-
}
|
|
75
|
-
async getBackupLogFileContent() {
|
|
76
|
-
return (await RNFS.exists(this.backupZip)) ? RNFS.readFile(this.backupZip, 'base64') : null;
|
|
77
|
-
}
|
|
78
|
-
async clear() {
|
|
79
|
-
if (await RNFS.exists(this.logFile))
|
|
80
|
-
await RNFS.writeFile(this.logFile, '', 'utf8');
|
|
81
|
-
if (await RNFS.exists(this.backupZip))
|
|
82
|
-
await RNFS.unlink(this.backupZip);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare class LoggerWindows {
|
|
2
|
-
private logFilePath;
|
|
3
|
-
private backupZipPath;
|
|
4
|
-
init(): Promise<void>;
|
|
5
|
-
writeLine(line: string, maxSize: number): Promise<void>;
|
|
6
|
-
getLogFileURL(): Promise<string>;
|
|
7
|
-
getLogFileContent(): any;
|
|
8
|
-
getBackupLogFileContent(): any;
|
|
9
|
-
clear(): Promise<void>;
|
|
10
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// LoggerWindows.ts
|
|
2
|
-
import JSZip from 'jszip';
|
|
3
|
-
const WindowsFS = require('@react-native-windows/fs');
|
|
4
|
-
export class LoggerWindows {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.logFilePath = 'C:\\temp\\unvired-sdk.log';
|
|
7
|
-
this.backupZipPath = 'C:\\temp\\unvired-sdk-backup.zip';
|
|
8
|
-
}
|
|
9
|
-
async init() {
|
|
10
|
-
if (!(await WindowsFS.exists(this.logFilePath))) {
|
|
11
|
-
await WindowsFS.writeFile(this.logFilePath, '');
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
async writeLine(line, maxSize) {
|
|
15
|
-
const old = await WindowsFS.readFile(this.logFilePath, 'utf8');
|
|
16
|
-
await WindowsFS.writeFile(this.logFilePath, old + line + '\n');
|
|
17
|
-
const stat = await WindowsFS.stat(this.logFilePath);
|
|
18
|
-
if (stat.size < maxSize)
|
|
19
|
-
return;
|
|
20
|
-
if (await WindowsFS.exists(this.backupZipPath)) {
|
|
21
|
-
await WindowsFS.unlink(this.backupZipPath);
|
|
22
|
-
}
|
|
23
|
-
const zip = new JSZip();
|
|
24
|
-
zip.file('unvired-sdk.log', old);
|
|
25
|
-
const zipped = await zip.generateAsync({ type: 'uint8array' });
|
|
26
|
-
await WindowsFS.writeFile(this.backupZipPath, zipped);
|
|
27
|
-
await WindowsFS.writeFile(this.logFilePath, '');
|
|
28
|
-
}
|
|
29
|
-
async getLogFileURL() {
|
|
30
|
-
return this.logFilePath;
|
|
31
|
-
}
|
|
32
|
-
getLogFileContent() {
|
|
33
|
-
return WindowsFS.readFile(this.logFilePath, 'utf8');
|
|
34
|
-
}
|
|
35
|
-
getBackupLogFileContent() {
|
|
36
|
-
return WindowsFS.readFile(this.backupZipPath, 'base64');
|
|
37
|
-
}
|
|
38
|
-
async clear() {
|
|
39
|
-
await WindowsFS.writeFile(this.logFilePath, '');
|
|
40
|
-
if (await WindowsFS.exists(this.backupZipPath)) {
|
|
41
|
-
await WindowsFS.unlink(this.backupZipPath);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export interface PlatformInterface {
|
|
2
|
-
// Logger
|
|
3
|
-
logInfo(className: string, methodName: string, message: string): void;
|
|
4
|
-
logError(className: string, methodName: string, message: string): void;
|
|
5
|
-
logDebug(className: string, methodName: string, message: string): void;
|
|
6
|
-
setLogLevel(level: string): void;
|
|
7
|
-
getLogFileURL(): Promise<string>;
|
|
8
|
-
getLogFileContent(): Promise<string>;
|
|
9
|
-
getBackupLogFileContent(): Promise<string>;
|
|
10
|
-
clearLogFile(): Promise<void>;
|
|
11
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { PlatformInterface } from './PlatformInterface';
|
|
2
|
-
import { logger } from '../src/logger/Logger';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class ReactNativePlatformAdapter implements PlatformInterface {
|
|
6
|
-
|
|
7
|
-
// Logger
|
|
8
|
-
logInfo(className: string, methodName: string, message: string): void {
|
|
9
|
-
logger.logInfo(className, methodName, message);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
logError(className: string, methodName: string, message: string): void {
|
|
13
|
-
logger.logError(className, methodName, message);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
logDebug(className: string, methodName: string, message: string): void {
|
|
17
|
-
logger.logDebug(className, methodName, message);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
setLogLevel(level: string): void {
|
|
21
|
-
logger.setLogLevel(level);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async getLogFileURL(): Promise<string> {
|
|
25
|
-
return await logger.getLogFileURL();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async getLogFileContent(): Promise<string> {
|
|
29
|
-
return await logger.getLogFileContent();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async getBackupLogFileContent(): Promise<string> {
|
|
33
|
-
return await logger.getBackupLogFileContent();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async clearLogFile(): Promise<void> {
|
|
37
|
-
await logger.clearLogFile();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|