@unvired/react-native-unvired-sdk 0.0.4
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 -0
- package/README.md +331 -0
- package/build.xml +103 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/logger/BaseLogger.d.ts +18 -0
- package/dist/logger/BaseLogger.js +74 -0
- package/dist/logger/Logger.d.ts +6 -0
- package/dist/logger/Logger.js +7 -0
- package/dist/logger/LoggerNative.d.ts +15 -0
- package/dist/logger/LoggerNative.js +84 -0
- package/dist/logger/LoggerWeb.d.ts +8 -0
- package/dist/logger/LoggerWeb.js +11 -0
- package/dist/logger/LoggerWindows.d.ts +10 -0
- package/dist/logger/LoggerWindows.js +44 -0
- package/example/PlatformInterface.ts +11 -0
- package/example/ReactNativePlatformAdapter.ts +40 -0
- package/package.json +57 -0
package/BuildNo.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
R-0.000.0004
|
package/README.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# React Native Unvired SDK
|
|
2
|
+
|
|
3
|
+
A comprehensive SDK for React Native applications with support for logging, database operations, notifications, and file system management.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install react-native-unvired-sdk
|
|
9
|
+
# or
|
|
10
|
+
yarn add react-native-unvired-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Optional Dependencies
|
|
14
|
+
|
|
15
|
+
The **logger works out of the box** with zero dependencies. For additional features, install the packages you need:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# For file operations
|
|
19
|
+
npm install react-native-fs
|
|
20
|
+
|
|
21
|
+
# For database (choose one)
|
|
22
|
+
npm install react-native-sqlite-storage # SQL database
|
|
23
|
+
npm install @react-native-async-storage/async-storage # Simple key-value
|
|
24
|
+
|
|
25
|
+
# For notifications
|
|
26
|
+
npm install @notifee/react-native
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> **See [NPM_PACKAGES.md](./NPM_PACKAGES.md) for detailed package information and implementation guide.**
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- 📝 **Logger** - Comprehensive logging with multiple log levels ✅ **No dependencies**
|
|
34
|
+
- 💾 **Database** - Database operations and data persistence ⚠️ *Requires optional package*
|
|
35
|
+
- 🔔 **Notifications** - Push and local notification management ⚠️ *Requires optional package*
|
|
36
|
+
- 📁 **File System** - File read/write and management operations ⚠️ *Requires optional package*
|
|
37
|
+
- 🔌 **PlatformInterface** - Compatible with PlatformInterface pattern for cross-platform logging
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Basic Initialization
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
import UnviredSDK, { LogLevel } from 'react-native-unvired-sdk';
|
|
45
|
+
|
|
46
|
+
// Initialize the SDK with all modules
|
|
47
|
+
await UnviredSDK.initialize({
|
|
48
|
+
logLevel: LogLevel.DEBUG,
|
|
49
|
+
tag: 'MyApp',
|
|
50
|
+
database: {
|
|
51
|
+
// Database configuration
|
|
52
|
+
},
|
|
53
|
+
notifications: {
|
|
54
|
+
// Notification configuration
|
|
55
|
+
},
|
|
56
|
+
fileSystem: {
|
|
57
|
+
basePath: '/path/to/files'
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Using the Logger
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
import { logger, LogLevel } from 'react-native-unvired-sdk';
|
|
66
|
+
|
|
67
|
+
// Set log level
|
|
68
|
+
logger.setLogLevel(LogLevel.DEBUG);
|
|
69
|
+
|
|
70
|
+
// Log messages
|
|
71
|
+
logger.debug('Debug message');
|
|
72
|
+
logger.info('Info message');
|
|
73
|
+
logger.warn('Warning message');
|
|
74
|
+
logger.error('Error message');
|
|
75
|
+
|
|
76
|
+
// Create child logger for specific modules
|
|
77
|
+
const childLogger = logger.createChild('FeatureModule');
|
|
78
|
+
childLogger.info('This is from a child logger');
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Using PlatformInterface Pattern
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import { logger } from 'react-native-unvired-sdk';
|
|
85
|
+
|
|
86
|
+
// Use with className and methodName (PlatformInterface compatible)
|
|
87
|
+
logger.logInfo('UserService', 'login', 'User login attempt');
|
|
88
|
+
logger.logError('UserService', 'login', 'Login failed');
|
|
89
|
+
logger.logDebug('UserService', 'fetchProfile', 'Fetching user profile');
|
|
90
|
+
|
|
91
|
+
// Set log level (accepts string)
|
|
92
|
+
logger.setLogLevel('DEBUG');
|
|
93
|
+
|
|
94
|
+
// File-based logging
|
|
95
|
+
const logs = await logger.getLogFileContent();
|
|
96
|
+
const backupLogs = await logger.getBackupLogFileContent();
|
|
97
|
+
await logger.clearLogFile();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Database Operations
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
import { database } from 'react-native-unvired-sdk';
|
|
104
|
+
|
|
105
|
+
// Initialize database (if not done in SDK initialization)
|
|
106
|
+
await database.initialize({ /* config */ });
|
|
107
|
+
|
|
108
|
+
// Insert or update data
|
|
109
|
+
await database.upsert('users', {
|
|
110
|
+
id: 1,
|
|
111
|
+
name: 'John Doe',
|
|
112
|
+
email: 'john@example.com'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Query data
|
|
116
|
+
const users = await database.query('users', {
|
|
117
|
+
where: { active: true }
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Delete data
|
|
121
|
+
await database.delete('users', { id: 1 });
|
|
122
|
+
|
|
123
|
+
// Execute transaction
|
|
124
|
+
await database.transaction(async (db) => {
|
|
125
|
+
await db.upsert('users', userData);
|
|
126
|
+
await db.upsert('profiles', profileData);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Clear all data
|
|
130
|
+
await database.clear();
|
|
131
|
+
|
|
132
|
+
// Close database
|
|
133
|
+
await database.close();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Notifications
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
import { notificationManager } from 'react-native-unvired-sdk';
|
|
140
|
+
|
|
141
|
+
// Initialize notifications (if not done in SDK initialization)
|
|
142
|
+
await notificationManager.initialize({ /* config */ });
|
|
143
|
+
|
|
144
|
+
// Request permissions
|
|
145
|
+
const granted = await notificationManager.requestPermissions();
|
|
146
|
+
|
|
147
|
+
// Show a notification
|
|
148
|
+
await notificationManager.showNotification({
|
|
149
|
+
title: 'Hello',
|
|
150
|
+
body: 'This is a notification',
|
|
151
|
+
data: { customData: 'value' }
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Schedule a notification
|
|
155
|
+
const notificationId = await notificationManager.scheduleNotification(
|
|
156
|
+
{
|
|
157
|
+
title: 'Reminder',
|
|
158
|
+
body: 'Don\'t forget!'
|
|
159
|
+
},
|
|
160
|
+
new Date(Date.now() + 3600000) // 1 hour from now
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Cancel a notification
|
|
164
|
+
await notificationManager.cancelNotification(notificationId);
|
|
165
|
+
|
|
166
|
+
// Listen for notification events
|
|
167
|
+
const unsubscribe = notificationManager.on('onNotificationReceived', (notification) => {
|
|
168
|
+
console.log('Notification received:', notification);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Set badge count
|
|
172
|
+
await notificationManager.setBadgeCount(5);
|
|
173
|
+
|
|
174
|
+
// Get badge count
|
|
175
|
+
const count = await notificationManager.getBadgeCount();
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### File System Operations
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import { fileManager } from 'react-native-unvired-sdk';
|
|
182
|
+
|
|
183
|
+
// Initialize file manager (if not done in SDK initialization)
|
|
184
|
+
await fileManager.initialize({ basePath: '/path/to/files' });
|
|
185
|
+
|
|
186
|
+
// Read a file
|
|
187
|
+
const content = await fileManager.readFile('data.txt');
|
|
188
|
+
|
|
189
|
+
// Write to a file
|
|
190
|
+
await fileManager.writeFile('data.txt', 'Hello World');
|
|
191
|
+
|
|
192
|
+
// Append to a file
|
|
193
|
+
await fileManager.appendFile('log.txt', 'New log entry\n');
|
|
194
|
+
|
|
195
|
+
// Check if file exists
|
|
196
|
+
const exists = await fileManager.exists('data.txt');
|
|
197
|
+
|
|
198
|
+
// Delete a file
|
|
199
|
+
await fileManager.deleteFile('old-file.txt');
|
|
200
|
+
|
|
201
|
+
// Create directory
|
|
202
|
+
await fileManager.createDirectory('my-folder');
|
|
203
|
+
|
|
204
|
+
// List files in directory
|
|
205
|
+
const files = await fileManager.listFiles('my-folder');
|
|
206
|
+
|
|
207
|
+
// Copy file
|
|
208
|
+
await fileManager.copyFile('source.txt', 'destination.txt');
|
|
209
|
+
|
|
210
|
+
// Move file
|
|
211
|
+
await fileManager.moveFile('old-location.txt', 'new-location.txt');
|
|
212
|
+
|
|
213
|
+
// Download file
|
|
214
|
+
await fileManager.downloadFile(
|
|
215
|
+
'https://example.com/file.pdf',
|
|
216
|
+
'downloads/file.pdf',
|
|
217
|
+
(progress) => console.log(`Downloaded: ${progress}%`)
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Upload file
|
|
221
|
+
await fileManager.uploadFile(
|
|
222
|
+
'local-file.jpg',
|
|
223
|
+
'https://example.com/upload',
|
|
224
|
+
{ headers: { 'Authorization': 'Bearer token' } },
|
|
225
|
+
(progress) => console.log(`Uploaded: ${progress}%`)
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Get file info
|
|
229
|
+
const info = await fileManager.getFileInfo('data.txt');
|
|
230
|
+
console.log(info.size, info.modifiedTime);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### SDK Shutdown
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
// Properly shutdown SDK and cleanup resources
|
|
237
|
+
await UnviredSDK.shutdown();
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## API Reference
|
|
241
|
+
|
|
242
|
+
### Log Levels
|
|
243
|
+
|
|
244
|
+
- `LogLevel.DEBUG` - Detailed debugging information
|
|
245
|
+
- `LogLevel.INFO` - General informational messages
|
|
246
|
+
- `LogLevel.WARN` - Warning messages
|
|
247
|
+
- `LogLevel.ERROR` - Error messages
|
|
248
|
+
- `LogLevel.NONE` - Disable all logging
|
|
249
|
+
|
|
250
|
+
### Logger Methods
|
|
251
|
+
|
|
252
|
+
- `logger.debug(message, ...args)` - Log debug message
|
|
253
|
+
- `logger.info(message, ...args)` - Log info message
|
|
254
|
+
- `logger.warn(message, ...args)` - Log warning message
|
|
255
|
+
- `logger.error(message, ...args)` - Log error message
|
|
256
|
+
- `logger.setLogLevel(level)` - Set minimum log level
|
|
257
|
+
- `logger.setTag(tag)` - Set custom tag
|
|
258
|
+
- `logger.createChild(childTag)` - Create child logger with custom tag
|
|
259
|
+
|
|
260
|
+
### Database Methods
|
|
261
|
+
|
|
262
|
+
- `database.initialize(config)` - Initialize database
|
|
263
|
+
- `database.upsert(table, data)` - Insert or update data
|
|
264
|
+
- `database.query(table, query)` - Query data
|
|
265
|
+
- `database.delete(table, query)` - Delete data
|
|
266
|
+
- `database.transaction(callback)` - Execute transaction
|
|
267
|
+
- `database.clear()` - Clear all data
|
|
268
|
+
- `database.close()` - Close database connection
|
|
269
|
+
|
|
270
|
+
### Notification Methods
|
|
271
|
+
|
|
272
|
+
- `notificationManager.initialize(config)` - Initialize notifications
|
|
273
|
+
- `notificationManager.requestPermissions()` - Request notification permissions
|
|
274
|
+
- `notificationManager.showNotification(notification)` - Show notification
|
|
275
|
+
- `notificationManager.scheduleNotification(notification, time)` - Schedule notification
|
|
276
|
+
- `notificationManager.cancelNotification(id)` - Cancel notification
|
|
277
|
+
- `notificationManager.cancelAllNotifications()` - Cancel all notifications
|
|
278
|
+
- `notificationManager.on(event, handler)` - Register event handler
|
|
279
|
+
- `notificationManager.setBadgeCount(count)` - Set badge count
|
|
280
|
+
- `notificationManager.getBadgeCount()` - Get badge count
|
|
281
|
+
|
|
282
|
+
### File System Methods
|
|
283
|
+
|
|
284
|
+
- `fileManager.initialize(config)` - Initialize file manager
|
|
285
|
+
- `fileManager.readFile(path, encoding)` - Read file
|
|
286
|
+
- `fileManager.writeFile(path, content, encoding)` - Write file
|
|
287
|
+
- `fileManager.appendFile(path, content, encoding)` - Append to file
|
|
288
|
+
- `fileManager.deleteFile(path)` - Delete file
|
|
289
|
+
- `fileManager.exists(path)` - Check if file exists
|
|
290
|
+
- `fileManager.createDirectory(path)` - Create directory
|
|
291
|
+
- `fileManager.listFiles(path)` - List files in directory
|
|
292
|
+
- `fileManager.copyFile(source, dest)` - Copy file
|
|
293
|
+
- `fileManager.moveFile(source, dest)` - Move file
|
|
294
|
+
- `fileManager.downloadFile(url, path, onProgress)` - Download file
|
|
295
|
+
- `fileManager.uploadFile(path, url, options, onProgress)` - Upload file
|
|
296
|
+
- `fileManager.getFileInfo(path)` - Get file information
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Install dependencies
|
|
302
|
+
npm install
|
|
303
|
+
|
|
304
|
+
# Run tests
|
|
305
|
+
npm test
|
|
306
|
+
|
|
307
|
+
# Lint code
|
|
308
|
+
npm run lint
|
|
309
|
+
|
|
310
|
+
# Format code
|
|
311
|
+
npm run format
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Architecture
|
|
315
|
+
|
|
316
|
+
The SDK is organized into modular components:
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
src/
|
|
320
|
+
├── logger/ # Logging utilities
|
|
321
|
+
├── database/ # Database operations
|
|
322
|
+
├── notifications/ # Notification management
|
|
323
|
+
├── fileSystem/ # File system operations
|
|
324
|
+
└── index.js # Main SDK entry point
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Each module can be initialized independently or as part of the main SDK initialization.
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
MIT
|
package/build.xml
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<project name="react-native-unvired-sdk" default="npmpublish" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
|
|
2
|
+
<property name="dist.dir" value="${basedir}/dist"/>
|
|
3
|
+
<property name="build.dir" value="${basedir}/build/react-native-unvired-sdk"/>
|
|
4
|
+
|
|
5
|
+
<scriptdef name="substring" language="javascript">
|
|
6
|
+
<attribute name="text" />
|
|
7
|
+
<attribute name="start" />
|
|
8
|
+
<attribute name="end" />
|
|
9
|
+
<attribute name="property" />
|
|
10
|
+
<![CDATA[
|
|
11
|
+
var text = attributes.get("text");
|
|
12
|
+
var start = attributes.get("start");
|
|
13
|
+
var end = attributes.get("end") || text.length();
|
|
14
|
+
project.setProperty(attributes.get("property"), text.substring(start, end));
|
|
15
|
+
]]>
|
|
16
|
+
</scriptdef>
|
|
17
|
+
|
|
18
|
+
<scriptdef name="packageversion" language="javascript">
|
|
19
|
+
<attribute name="text" />
|
|
20
|
+
<attribute name="start" />
|
|
21
|
+
<attribute name="end" />
|
|
22
|
+
<attribute name="property" />
|
|
23
|
+
<![CDATA[
|
|
24
|
+
var text = attributes.get("text");
|
|
25
|
+
var start = attributes.get("start");
|
|
26
|
+
var end = attributes.get("end") || text.length();
|
|
27
|
+
var newstring = text.substring(start, end);
|
|
28
|
+
newstring = newstring.replace(/\./g,'~');
|
|
29
|
+
var split = newstring.split("~");
|
|
30
|
+
var first = +split[0];
|
|
31
|
+
first = first.toString();
|
|
32
|
+
var middle = +split[1];
|
|
33
|
+
middle = middle.toString();
|
|
34
|
+
var last = +split[2];
|
|
35
|
+
last = last.toString();
|
|
36
|
+
|
|
37
|
+
newstring = first + '.' + middle + '.' + last;
|
|
38
|
+
project.setProperty(attributes.get("property"), newstring);
|
|
39
|
+
]]>
|
|
40
|
+
</scriptdef>
|
|
41
|
+
|
|
42
|
+
<!-- Get the release number -->
|
|
43
|
+
<target name="getbuildno">
|
|
44
|
+
<property environment="env" />
|
|
45
|
+
|
|
46
|
+
<java jar="/Users/server/Jenkins/BuildNo/BuildNo.jar" fork="true" failonerror="true" maxmemory="128m">
|
|
47
|
+
<arg value="REACT_NATIVE_UNVIRED_SDK"/>
|
|
48
|
+
<arg value="-r=true"/>
|
|
49
|
+
<arg value="-n=true"/>
|
|
50
|
+
</java>
|
|
51
|
+
|
|
52
|
+
<!-- Now read into the build numberfile into release.str property -->
|
|
53
|
+
<loadfile property="release.str"
|
|
54
|
+
srcFile="BuildNo.txt" failonerror="true">
|
|
55
|
+
</loadfile>
|
|
56
|
+
|
|
57
|
+
<echo message="Using release number : ${release.str}"/>
|
|
58
|
+
|
|
59
|
+
</target>
|
|
60
|
+
|
|
61
|
+
<target name="npminstall" depends="getbuildno">
|
|
62
|
+
<echo message="Doing npm install"/>
|
|
63
|
+
<exec executable="npm" failonerror="true">
|
|
64
|
+
<arg value="install"/>
|
|
65
|
+
<arg value="--force"/>
|
|
66
|
+
</exec>
|
|
67
|
+
</target>
|
|
68
|
+
|
|
69
|
+
<target name="updatebuildno" depends="npminstall">
|
|
70
|
+
<echo message="Updating build number in service constants file."/>
|
|
71
|
+
|
|
72
|
+
<!-- Release string to be written -->
|
|
73
|
+
<loadfile property="release.str"
|
|
74
|
+
srcFile="BuildNo.txt" failonerror="true">
|
|
75
|
+
</loadfile>
|
|
76
|
+
<packageversion text="${release.str}" start="2" property="release.num" />
|
|
77
|
+
</target>
|
|
78
|
+
|
|
79
|
+
<target name="updatesource" depends="updatebuildno">
|
|
80
|
+
|
|
81
|
+
<!-- Release string to be written -->
|
|
82
|
+
<loadfile property="release.str"
|
|
83
|
+
srcFile="BuildNo.txt" failonerror="true">
|
|
84
|
+
</loadfile>
|
|
85
|
+
|
|
86
|
+
<mkdir dir="${dist.dir}"/>
|
|
87
|
+
|
|
88
|
+
<property environment="env" />
|
|
89
|
+
|
|
90
|
+
<packageversion text="${release.str}" start="2" property="release.num" />
|
|
91
|
+
<echo message="Using package version number : ${release.num}"/>
|
|
92
|
+
<replace file="package.json" token="@PACKAGE_NUMBER@" value='${release.num}'/>
|
|
93
|
+
|
|
94
|
+
</target>
|
|
95
|
+
|
|
96
|
+
<target name="npmpublish" depends="updatesource" if="${env.PUBLISH}">
|
|
97
|
+
<echo message="Publishing to NPM Registry"/>
|
|
98
|
+
<exec executable="npm" failonerror="true">
|
|
99
|
+
<arg value="publish"/>
|
|
100
|
+
<arg value="."/>
|
|
101
|
+
</exec>
|
|
102
|
+
</target>
|
|
103
|
+
</project>
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'error' | 'none';
|
|
2
|
+
export declare const MAX_LOG_SIZE: number;
|
|
3
|
+
export declare class BaseLogger {
|
|
4
|
+
private impl;
|
|
5
|
+
private logLevel;
|
|
6
|
+
constructor();
|
|
7
|
+
private format;
|
|
8
|
+
setLogLevel(level: LogLevel): void;
|
|
9
|
+
private shouldLog;
|
|
10
|
+
log(level: LogLevel, className: string, methodName: string, message: string): Promise<void>;
|
|
11
|
+
logDebug(c: string, m: string, msg: string): void;
|
|
12
|
+
logInfo(c: string, m: string, msg: string): void;
|
|
13
|
+
logError(c: string, m: string, msg: string): void;
|
|
14
|
+
getLogFileURL(): any;
|
|
15
|
+
getLogFileContent(): any;
|
|
16
|
+
getBackupLogFileContent(): any;
|
|
17
|
+
clearLogFile(): any;
|
|
18
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// BaseLogger.ts
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { LoggerNative } from './LoggerNative';
|
|
4
|
+
// import { LoggerWindows } from './LoggerWindows';
|
|
5
|
+
import { LoggerWeb } from './LoggerWeb';
|
|
6
|
+
export const MAX_LOG_SIZE = 1 * 1024 * 1024;
|
|
7
|
+
export class BaseLogger {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.logLevel = 'info';
|
|
10
|
+
if (Platform.OS === 'web') {
|
|
11
|
+
this.impl = new LoggerWeb();
|
|
12
|
+
}
|
|
13
|
+
else if (Platform.OS === 'windows') {
|
|
14
|
+
// this.impl = new LoggerWindows();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
this.impl = new LoggerNative();
|
|
18
|
+
}
|
|
19
|
+
this.impl.init();
|
|
20
|
+
}
|
|
21
|
+
// -------------------------
|
|
22
|
+
// Common formatting logic
|
|
23
|
+
// -------------------------
|
|
24
|
+
format(className, methodName, message, level) {
|
|
25
|
+
const ts = new Date().toISOString();
|
|
26
|
+
return `--[${ts}] [${level.toUpperCase()}] [${className}] [${methodName}] ${message}`;
|
|
27
|
+
}
|
|
28
|
+
setLogLevel(level) {
|
|
29
|
+
this.logLevel = level;
|
|
30
|
+
}
|
|
31
|
+
shouldLog(level) {
|
|
32
|
+
const rank = {
|
|
33
|
+
debug: 1,
|
|
34
|
+
info: 2,
|
|
35
|
+
error: 3,
|
|
36
|
+
none: 4,
|
|
37
|
+
};
|
|
38
|
+
return rank[level] >= rank[this.logLevel];
|
|
39
|
+
}
|
|
40
|
+
// -------------------------
|
|
41
|
+
// Main log function
|
|
42
|
+
// -------------------------
|
|
43
|
+
async log(level, className, methodName, message) {
|
|
44
|
+
if (!this.shouldLog(level))
|
|
45
|
+
return;
|
|
46
|
+
const line = this.format(className, methodName, message, level);
|
|
47
|
+
// console always
|
|
48
|
+
switch (level) {
|
|
49
|
+
case 'debug':
|
|
50
|
+
console.debug(line);
|
|
51
|
+
break;
|
|
52
|
+
case 'info':
|
|
53
|
+
console.info(line);
|
|
54
|
+
break;
|
|
55
|
+
case 'error':
|
|
56
|
+
console.error(line);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
await this.impl.writeLine(line, MAX_LOG_SIZE);
|
|
60
|
+
}
|
|
61
|
+
// -------------------------
|
|
62
|
+
// Public wrappers
|
|
63
|
+
// -------------------------
|
|
64
|
+
logDebug(c, m, msg) { this.log('debug', c, m, msg); }
|
|
65
|
+
logInfo(c, m, msg) { this.log('info', c, m, msg); }
|
|
66
|
+
logError(c, m, msg) { this.log('error', c, m, msg); }
|
|
67
|
+
// -------------------------
|
|
68
|
+
// File access forwarding
|
|
69
|
+
// -------------------------
|
|
70
|
+
getLogFileURL() { return this.impl.getLogFileURL(); }
|
|
71
|
+
getLogFileContent() { return this.impl.getLogFileContent(); }
|
|
72
|
+
getBackupLogFileContent() { return this.impl.getBackupLogFileContent(); }
|
|
73
|
+
clearLogFile() { return this.impl.clear(); }
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// LoggerWeb.ts
|
|
2
|
+
export class LoggerWeb {
|
|
3
|
+
async init() { }
|
|
4
|
+
async writeLine(line) {
|
|
5
|
+
console.log(line);
|
|
6
|
+
}
|
|
7
|
+
async getLogFileURL() { return ''; }
|
|
8
|
+
async getLogFileContent() { return ''; }
|
|
9
|
+
async getBackupLogFileContent() { return ''; }
|
|
10
|
+
async clear() { }
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unvired/react-native-unvired-sdk",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "Unvired SDK for React Native with logging, database, notifications, and file system support",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc --project tsconfig.json",
|
|
9
|
+
"prepare": "npm run build",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"lint": "eslint src/",
|
|
12
|
+
"format": "prettier --write \"src/**/*.{js,ts,tsx}\""
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react-native",
|
|
16
|
+
"unvired",
|
|
17
|
+
"sdk",
|
|
18
|
+
"mobile",
|
|
19
|
+
"logger",
|
|
20
|
+
"database",
|
|
21
|
+
"notifications",
|
|
22
|
+
"file-system"
|
|
23
|
+
],
|
|
24
|
+
"author": "Unvired",
|
|
25
|
+
"license": "",
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react": ">=16.8.0",
|
|
28
|
+
"react-native": ">=0.60.0",
|
|
29
|
+
"react-native-fs": ">=2.0.0",
|
|
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
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/react": "^18.0.0",
|
|
40
|
+
"@types/react-native": "^0.72.0",
|
|
41
|
+
"eslint": "^8.0.0",
|
|
42
|
+
"jest": "^29.0.0",
|
|
43
|
+
"prettier": "^3.0.0",
|
|
44
|
+
"typescript": "^5.0.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"jszip": "^3.10.1"
|
|
48
|
+
},
|
|
49
|
+
"repository": {},
|
|
50
|
+
"bugs": {},
|
|
51
|
+
"volta": {
|
|
52
|
+
"node": "25.2.1"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|