@unvired/react-native-unvired-sdk 0.0.32 → 0.0.34
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/dist/database/DatabaseManager.d.ts +1 -1
- package/dist/database/DatabaseManager.js +4 -2
- package/dist/database/services/DatabaseWeb.d.ts +12 -0
- package/dist/database/services/DatabaseWeb.js +237 -0
- package/dist/device-info/BaseDeviceInfo.d.ts +2 -3
- package/dist/device-info/BaseDeviceInfo.js +13 -68
- package/dist/device-info/DeviceInfo.types.d.ts +11 -0
- package/dist/device-info/services/DeviceInfoNative.d.ts +9 -0
- package/dist/device-info/services/DeviceInfoNative.js +83 -0
- package/dist/device-info/services/DeviceInfoWeb.d.ts +12 -0
- package/dist/device-info/services/DeviceInfoWeb.js +54 -0
- package/dist/file-system/services/FileSystemWeb.d.ts +5 -1
- package/dist/file-system/services/FileSystemWeb.js +247 -14
- package/dist/local-storage/services/StorageWeb.js +39 -8
- package/dist/logger/services/LoggerNative.d.ts +1 -1
- package/dist/logger/services/LoggerNative.js +45 -84
- package/dist/logger/services/LoggerWeb.d.ts +5 -2
- package/dist/logger/services/LoggerWeb.js +14 -5
- package/dist/main.js +12 -0
- package/dist/push-notification/BasePushNotification.d.ts +2 -35
- package/dist/push-notification/BasePushNotification.js +18 -150
- package/dist/push-notification/PushNotification.types.d.ts +5 -0
- package/dist/push-notification/services/PushNotificationNative.d.ts +18 -0
- package/dist/push-notification/services/PushNotificationNative.js +130 -0
- package/dist/push-notification/services/PushNotificationWeb.d.ts +21 -0
- package/dist/push-notification/services/PushNotificationWeb.js +69 -0
- package/package.json +7 -5
|
@@ -1,41 +1,274 @@
|
|
|
1
|
+
class WebDirectoryReader {
|
|
2
|
+
constructor(fullPath) {
|
|
3
|
+
this.fullPath = fullPath;
|
|
4
|
+
}
|
|
5
|
+
readEntries(successCallback, errorCallback) {
|
|
6
|
+
try {
|
|
7
|
+
const entries = [];
|
|
8
|
+
const prefix = `__vfs_${this.fullPath}/`;
|
|
9
|
+
if (typeof localStorage !== "undefined") {
|
|
10
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
11
|
+
const key = localStorage.key(i);
|
|
12
|
+
if (key && key.startsWith(prefix)) {
|
|
13
|
+
const relPath = key.substring(prefix.length);
|
|
14
|
+
const segment = relPath.split("/")[0];
|
|
15
|
+
const entryFullPath = `${this.fullPath}/${segment}`;
|
|
16
|
+
const isDir = relPath.includes("/");
|
|
17
|
+
if (!entries.find((e) => e.fullPath === entryFullPath)) {
|
|
18
|
+
entries.push(new WebFileEntry(entryFullPath, isDir));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
successCallback(entries);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
errorCallback(e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class WebFileEntry {
|
|
31
|
+
constructor(fullPath, isDirectory) {
|
|
32
|
+
this.fullPath = fullPath.replace(/\/+/g, "/");
|
|
33
|
+
this.name = this.fullPath.split("/").filter(Boolean).pop() || "root";
|
|
34
|
+
this.isFile = !isDirectory;
|
|
35
|
+
this.isDirectory = isDirectory;
|
|
36
|
+
this.nativeURL = `file://${this.fullPath}`;
|
|
37
|
+
}
|
|
38
|
+
remove(callback, errorCallback) {
|
|
39
|
+
try {
|
|
40
|
+
if (typeof localStorage !== "undefined") {
|
|
41
|
+
localStorage.removeItem(`__vfs_${this.fullPath}`);
|
|
42
|
+
}
|
|
43
|
+
callback();
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
errorCallback(e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
removeRecursively(callback, errorCallback) {
|
|
50
|
+
try {
|
|
51
|
+
if (typeof localStorage !== "undefined") {
|
|
52
|
+
const prefix = `__vfs_${this.fullPath}`;
|
|
53
|
+
const keysToRemove = [];
|
|
54
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
55
|
+
const key = localStorage.key(i);
|
|
56
|
+
if (key && (key === prefix || key.startsWith(`${prefix}/`))) {
|
|
57
|
+
keysToRemove.push(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
keysToRemove.forEach((k) => localStorage.removeItem(k));
|
|
61
|
+
}
|
|
62
|
+
callback();
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
errorCallback(e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
createReader() {
|
|
69
|
+
return new WebDirectoryReader(this.fullPath);
|
|
70
|
+
}
|
|
71
|
+
getDirectory(path, options, callback, errorCallback) {
|
|
72
|
+
const dirPath = `${this.fullPath}/${path}`.replace(/\/+/g, "/");
|
|
73
|
+
const entry = new WebFileEntry(dirPath, true);
|
|
74
|
+
if ((options === null || options === void 0 ? void 0 : options.create) && typeof localStorage !== "undefined") {
|
|
75
|
+
localStorage.setItem(`__vfs_${dirPath}`, JSON.stringify({ isDir: true }));
|
|
76
|
+
}
|
|
77
|
+
callback(entry);
|
|
78
|
+
}
|
|
79
|
+
getFile(path, options, callback, errorCallback) {
|
|
80
|
+
const filePath = `${this.fullPath}/${path}`.replace(/\/+/g, "/");
|
|
81
|
+
const key = `__vfs_${filePath}`;
|
|
82
|
+
if ((options === null || options === void 0 ? void 0 : options.create) && typeof localStorage !== "undefined") {
|
|
83
|
+
if (localStorage.getItem(key) === null) {
|
|
84
|
+
localStorage.setItem(key, "");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const entry = new WebFileEntry(filePath, false);
|
|
88
|
+
callback(entry);
|
|
89
|
+
}
|
|
90
|
+
file(callback, errorCallback) {
|
|
91
|
+
try {
|
|
92
|
+
let content = "";
|
|
93
|
+
if (typeof localStorage !== "undefined") {
|
|
94
|
+
content = localStorage.getItem(`__vfs_${this.fullPath}`) || "";
|
|
95
|
+
}
|
|
96
|
+
const fileObj = {
|
|
97
|
+
name: this.name,
|
|
98
|
+
size: content.length,
|
|
99
|
+
type: "text/plain",
|
|
100
|
+
lastModified: Date.now(),
|
|
101
|
+
lastModifiedDate: new Date(),
|
|
102
|
+
path: this.fullPath,
|
|
103
|
+
};
|
|
104
|
+
callback(fileObj);
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
errorCallback(e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
createWriter(callback, errorCallback) {
|
|
111
|
+
const filePath = this.fullPath;
|
|
112
|
+
const writer = {
|
|
113
|
+
filePath,
|
|
114
|
+
write: (data) => {
|
|
115
|
+
try {
|
|
116
|
+
if (typeof localStorage !== "undefined") {
|
|
117
|
+
localStorage.setItem(`__vfs_${filePath}`, data);
|
|
118
|
+
}
|
|
119
|
+
if (writer.onwriteend)
|
|
120
|
+
writer.onwriteend();
|
|
121
|
+
return Promise.resolve();
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
if (writer.onerror)
|
|
125
|
+
writer.onerror(err);
|
|
126
|
+
return Promise.reject(err);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
append: (data) => {
|
|
130
|
+
try {
|
|
131
|
+
if (typeof localStorage !== "undefined") {
|
|
132
|
+
const existing = localStorage.getItem(`__vfs_${filePath}`) || "";
|
|
133
|
+
localStorage.setItem(`__vfs_${filePath}`, existing + data);
|
|
134
|
+
}
|
|
135
|
+
if (writer.onwriteend)
|
|
136
|
+
writer.onwriteend();
|
|
137
|
+
return Promise.resolve();
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
if (writer.onerror)
|
|
141
|
+
writer.onerror(err);
|
|
142
|
+
return Promise.reject(err);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
truncate: (size) => {
|
|
146
|
+
try {
|
|
147
|
+
if (typeof localStorage !== "undefined") {
|
|
148
|
+
const existing = localStorage.getItem(`__vfs_${filePath}`) || "";
|
|
149
|
+
localStorage.setItem(`__vfs_${filePath}`, existing.substring(0, size));
|
|
150
|
+
}
|
|
151
|
+
if (writer.onwriteend)
|
|
152
|
+
writer.onwriteend();
|
|
153
|
+
return Promise.resolve();
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
if (writer.onerror)
|
|
157
|
+
writer.onerror(err);
|
|
158
|
+
return Promise.reject(err);
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
seek: () => Promise.resolve(),
|
|
162
|
+
onwriteend: null,
|
|
163
|
+
onerror: null,
|
|
164
|
+
};
|
|
165
|
+
callback(writer);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* FileSystemWeb - Virtual browser-backed file system with localStorage persistence
|
|
170
|
+
*/
|
|
1
171
|
export class FileSystemWeb {
|
|
172
|
+
constructor() {
|
|
173
|
+
this.baseDir = "/virtual-fs";
|
|
174
|
+
}
|
|
2
175
|
getDocumentDirectory() {
|
|
3
|
-
return
|
|
176
|
+
return this.baseDir;
|
|
4
177
|
}
|
|
5
178
|
async resolveLocalFileSystemURL(url) {
|
|
6
|
-
|
|
179
|
+
const path = url.replace(/^file:\/\//, "");
|
|
180
|
+
return new WebFileEntry(path, false);
|
|
7
181
|
}
|
|
8
182
|
async getFolderBasedOnUserId(userId) {
|
|
9
|
-
|
|
183
|
+
const folder = `${this.baseDir}/users/${userId}`;
|
|
184
|
+
await this.createDirectory(folder);
|
|
185
|
+
return `file://${folder}`;
|
|
10
186
|
}
|
|
11
187
|
async deleteUserFolder(userId) {
|
|
12
|
-
|
|
188
|
+
const prefix = `__vfs_${this.baseDir}/users/${userId}`;
|
|
189
|
+
if (typeof localStorage !== "undefined") {
|
|
190
|
+
const keysToRemove = [];
|
|
191
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
192
|
+
const key = localStorage.key(i);
|
|
193
|
+
if (key && (key === prefix || key.startsWith(`${prefix}/`))) {
|
|
194
|
+
keysToRemove.push(key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
keysToRemove.forEach((k) => localStorage.removeItem(k));
|
|
198
|
+
}
|
|
13
199
|
}
|
|
14
200
|
async createDirectory(path) {
|
|
15
|
-
|
|
201
|
+
if (typeof localStorage !== "undefined") {
|
|
202
|
+
localStorage.setItem(`__vfs_${path}`, JSON.stringify({ isDir: true }));
|
|
203
|
+
}
|
|
16
204
|
}
|
|
17
|
-
async readFile(path, encoding) {
|
|
18
|
-
|
|
205
|
+
async readFile(path, encoding = "utf8") {
|
|
206
|
+
if (typeof localStorage !== "undefined") {
|
|
207
|
+
const val = localStorage.getItem(`__vfs_${path}`);
|
|
208
|
+
if (val !== null)
|
|
209
|
+
return val;
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`File not found: ${path}`);
|
|
19
212
|
}
|
|
20
|
-
async writeFile(path, content, encoding) {
|
|
21
|
-
|
|
213
|
+
async writeFile(path, content, encoding = "utf8") {
|
|
214
|
+
if (typeof localStorage !== "undefined") {
|
|
215
|
+
localStorage.setItem(`__vfs_${path}`, content);
|
|
216
|
+
}
|
|
22
217
|
}
|
|
23
218
|
async deleteFile(path) {
|
|
24
|
-
|
|
219
|
+
if (typeof localStorage !== "undefined") {
|
|
220
|
+
localStorage.removeItem(`__vfs_${path}`);
|
|
221
|
+
}
|
|
25
222
|
}
|
|
26
223
|
async exists(path) {
|
|
224
|
+
if (typeof localStorage !== "undefined") {
|
|
225
|
+
return localStorage.getItem(`__vfs_${path}`) !== null;
|
|
226
|
+
}
|
|
27
227
|
return false;
|
|
28
228
|
}
|
|
29
229
|
async stat(path) {
|
|
30
|
-
|
|
230
|
+
let size = 0;
|
|
231
|
+
if (typeof localStorage !== "undefined") {
|
|
232
|
+
const val = localStorage.getItem(`__vfs_${path}`);
|
|
233
|
+
if (val !== null)
|
|
234
|
+
size = val.length;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
size,
|
|
238
|
+
isFile: () => true,
|
|
239
|
+
isDirectory: () => false,
|
|
240
|
+
mtime: new Date(),
|
|
241
|
+
ctime: new Date(),
|
|
242
|
+
};
|
|
31
243
|
}
|
|
32
244
|
async readDir(path) {
|
|
33
|
-
|
|
245
|
+
const prefix = `__vfs_${path}/`;
|
|
246
|
+
const results = [];
|
|
247
|
+
if (typeof localStorage !== "undefined") {
|
|
248
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
249
|
+
const key = localStorage.key(i);
|
|
250
|
+
if (key && key.startsWith(prefix)) {
|
|
251
|
+
const name = key.substring(prefix.length).split("/")[0];
|
|
252
|
+
if (!results.find((r) => r.name === name)) {
|
|
253
|
+
results.push({
|
|
254
|
+
name,
|
|
255
|
+
path: `${path}/${name}`,
|
|
256
|
+
size: (localStorage.getItem(key) || "").length,
|
|
257
|
+
isFile: () => true,
|
|
258
|
+
isDirectory: () => false,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return results;
|
|
34
265
|
}
|
|
35
266
|
async copyFile(source, destination) {
|
|
36
|
-
|
|
267
|
+
const content = await this.readFile(source);
|
|
268
|
+
await this.writeFile(destination, content);
|
|
37
269
|
}
|
|
38
270
|
async moveFile(source, destination) {
|
|
39
|
-
|
|
271
|
+
await this.copyFile(source, destination);
|
|
272
|
+
await this.deleteFile(source);
|
|
40
273
|
}
|
|
41
274
|
}
|
|
@@ -1,26 +1,57 @@
|
|
|
1
1
|
export class StorageWeb {
|
|
2
2
|
getItem(key) {
|
|
3
|
-
|
|
3
|
+
try {
|
|
4
|
+
return typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
|
|
5
|
+
}
|
|
6
|
+
catch (e) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
4
9
|
}
|
|
5
10
|
setItem(key, value) {
|
|
6
|
-
|
|
11
|
+
try {
|
|
12
|
+
if (typeof localStorage !== "undefined") {
|
|
13
|
+
localStorage.setItem(key, value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
console.warn("[StorageWeb] Failed to set item:", key, e);
|
|
18
|
+
}
|
|
7
19
|
}
|
|
8
20
|
removeItem(key) {
|
|
9
|
-
|
|
21
|
+
try {
|
|
22
|
+
if (typeof localStorage !== "undefined") {
|
|
23
|
+
localStorage.removeItem(key);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.warn("[StorageWeb] Failed to remove item:", key, e);
|
|
28
|
+
}
|
|
10
29
|
}
|
|
11
30
|
clear() {
|
|
12
|
-
|
|
31
|
+
try {
|
|
32
|
+
if (typeof localStorage !== "undefined") {
|
|
33
|
+
localStorage.clear();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.warn("[StorageWeb] Failed to clear storage:", e);
|
|
38
|
+
}
|
|
13
39
|
}
|
|
14
40
|
getAllKeys() {
|
|
15
|
-
|
|
41
|
+
try {
|
|
42
|
+
return typeof localStorage !== "undefined" ? Object.keys(localStorage) : [];
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
16
47
|
}
|
|
17
48
|
multiGet(keys) {
|
|
18
|
-
return keys.map(key => [key,
|
|
49
|
+
return keys.map((key) => [key, this.getItem(key)]);
|
|
19
50
|
}
|
|
20
51
|
multiSet(keyValuePairs) {
|
|
21
|
-
keyValuePairs.forEach(([key, value]) =>
|
|
52
|
+
keyValuePairs.forEach(([key, value]) => this.setItem(key, value));
|
|
22
53
|
}
|
|
23
54
|
multiRemove(keys) {
|
|
24
|
-
keys.forEach(key =>
|
|
55
|
+
keys.forEach((key) => this.removeItem(key));
|
|
25
56
|
}
|
|
26
57
|
}
|
|
@@ -1,50 +1,48 @@
|
|
|
1
1
|
// LoggerNative.ts
|
|
2
|
-
import { Platform } from
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
3
|
// Import with null safety
|
|
4
4
|
let RNFS = null;
|
|
5
5
|
let zip = null;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
if (Platform.OS !== "web") {
|
|
7
|
+
try {
|
|
8
|
+
RNFS = require("react-native-fs");
|
|
9
|
+
if (!RNFS || !RNFS.DocumentDirectoryPath) {
|
|
10
|
+
console.warn("react-native-fs is not properly linked. Please run: cd ios && pod install (iOS) or rebuild your Android app.");
|
|
11
|
+
RNFS = null;
|
|
12
|
+
}
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
console.
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.warn("react-native-fs module not found.");
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const zipModule = require("react-native-zip-archive");
|
|
19
|
+
zip = zipModule.zip;
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
console.warn("react-native-zip-archive module not found.");
|
|
21
23
|
}
|
|
22
|
-
}
|
|
23
|
-
catch (e) {
|
|
24
|
-
console.error('❌ react-native-zip-archive module not found. Please install: npm install react-native-zip-archive');
|
|
25
24
|
}
|
|
26
25
|
export class LoggerNative {
|
|
27
26
|
constructor() {
|
|
28
|
-
this.isRotating = false;
|
|
27
|
+
this.isRotating = false;
|
|
29
28
|
this.isAvailable = false;
|
|
30
|
-
const dir =
|
|
31
|
-
const file =
|
|
29
|
+
const dir = "unvired_logs";
|
|
30
|
+
const file = "applog.txt";
|
|
32
31
|
if (!RNFS) {
|
|
33
|
-
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
36
|
-
this.backupZip = '';
|
|
32
|
+
this.logDir = "";
|
|
33
|
+
this.logFile = "";
|
|
34
|
+
this.backupZip = "";
|
|
37
35
|
return;
|
|
38
36
|
}
|
|
39
37
|
this.isAvailable = true;
|
|
40
|
-
if (Platform.OS ===
|
|
38
|
+
if (Platform.OS === "android") {
|
|
41
39
|
this.logDir = `${RNFS.DocumentDirectoryPath}/${dir}`;
|
|
42
40
|
}
|
|
43
|
-
else if (Platform.OS ===
|
|
41
|
+
else if (Platform.OS === "ios") {
|
|
44
42
|
this.logDir = `${RNFS.LibraryDirectoryPath}/${dir}`;
|
|
45
43
|
}
|
|
46
44
|
else {
|
|
47
|
-
this.logDir =
|
|
45
|
+
this.logDir = "";
|
|
48
46
|
}
|
|
49
47
|
this.logFile = `${this.logDir}/${file}`;
|
|
50
48
|
this.backupZip = `${this.logDir}/backuplog.zip`;
|
|
@@ -56,10 +54,10 @@ export class LoggerNative {
|
|
|
56
54
|
if (!(await RNFS.exists(this.logDir)))
|
|
57
55
|
await RNFS.mkdir(this.logDir);
|
|
58
56
|
if (!(await RNFS.exists(this.logFile)))
|
|
59
|
-
await RNFS.writeFile(this.logFile,
|
|
57
|
+
await RNFS.writeFile(this.logFile, "", "utf8");
|
|
60
58
|
}
|
|
61
59
|
catch (e) {
|
|
62
|
-
console.error(
|
|
60
|
+
console.error("LoggerNative init error:", e);
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
async writeLine(line, maxSize) {
|
|
@@ -67,18 +65,16 @@ export class LoggerNative {
|
|
|
67
65
|
return;
|
|
68
66
|
try {
|
|
69
67
|
await this.ensureDir();
|
|
70
|
-
await RNFS.appendFile(this.logFile, line +
|
|
71
|
-
// Only check for rotation if not already rotating
|
|
68
|
+
await RNFS.appendFile(this.logFile, line + "\n", "utf8");
|
|
72
69
|
if (!this.isRotating) {
|
|
73
70
|
const stat = await RNFS.stat(this.logFile);
|
|
74
71
|
if (Number(stat.size) >= maxSize) {
|
|
75
|
-
// Don't await - let rotation happen in background
|
|
76
72
|
this.rotateLog();
|
|
77
73
|
}
|
|
78
74
|
}
|
|
79
75
|
}
|
|
80
76
|
catch (e) {
|
|
81
|
-
console.error(
|
|
77
|
+
console.error("LoggerNative writeLine error:", e);
|
|
82
78
|
}
|
|
83
79
|
}
|
|
84
80
|
async ensureDir() {
|
|
@@ -89,115 +85,80 @@ export class LoggerNative {
|
|
|
89
85
|
await RNFS.mkdir(this.logDir);
|
|
90
86
|
}
|
|
91
87
|
catch (e) {
|
|
92
|
-
console.error(
|
|
88
|
+
console.error("LoggerNative ensureDir error:", e);
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
async rotateLog() {
|
|
96
92
|
if (!this.isAvailable || !RNFS || !zip) {
|
|
97
|
-
console.warn('⚠️ LoggerNative: Cannot rotate log, RNFS or zip not available');
|
|
98
93
|
return;
|
|
99
94
|
}
|
|
100
|
-
// Prevent concurrent rotations
|
|
101
95
|
if (this.isRotating) {
|
|
102
|
-
console.log('⏭️ Rotation already in progress, skipping...');
|
|
103
96
|
return;
|
|
104
97
|
}
|
|
105
98
|
this.isRotating = true;
|
|
106
99
|
try {
|
|
107
|
-
console.log('🔄 Starting log rotation...');
|
|
108
|
-
// Check if log file exists and get its size
|
|
109
100
|
if (!(await RNFS.exists(this.logFile))) {
|
|
110
|
-
console.log('⚠️ Log file does not exist, skipping rotation');
|
|
111
101
|
return;
|
|
112
102
|
}
|
|
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
103
|
if (await RNFS.exists(this.backupZip)) {
|
|
117
|
-
console.log('🗑️ Removing old backup.zip');
|
|
118
104
|
await RNFS.unlink(this.backupZip);
|
|
119
105
|
}
|
|
120
|
-
// Step 2: Create a temporary directory for zipping
|
|
121
|
-
// react-native-zip-archive requires a directory, not a single file
|
|
122
106
|
const tempZipDir = `${this.logDir}/temp_zip`;
|
|
123
107
|
if (await RNFS.exists(tempZipDir)) {
|
|
124
108
|
await RNFS.unlink(tempZipDir);
|
|
125
109
|
}
|
|
126
110
|
await RNFS.mkdir(tempZipDir);
|
|
127
|
-
// Step 3: Copy current log file into the temp directory
|
|
128
111
|
const tempFileInDir = `${tempZipDir}/applog.txt`;
|
|
129
|
-
console.log('📦 Copying log file to temp directory for zipping');
|
|
130
112
|
await RNFS.copyFile(this.logFile, tempFileInDir);
|
|
131
|
-
// Step 4: Zip the directory → backup.zip
|
|
132
|
-
console.log('🗜️ Creating backup.zip from current log');
|
|
133
113
|
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
114
|
if (await RNFS.exists(tempZipDir)) {
|
|
139
115
|
await RNFS.unlink(tempZipDir);
|
|
140
116
|
}
|
|
141
|
-
|
|
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)');
|
|
117
|
+
await RNFS.writeFile(this.logFile, "", "utf8");
|
|
146
118
|
}
|
|
147
119
|
catch (e) {
|
|
148
|
-
console.error(
|
|
149
|
-
// Try to recover by creating a fresh log file if it doesn't exist
|
|
120
|
+
console.error("Logger rotation error:", e);
|
|
150
121
|
try {
|
|
151
122
|
if (!(await RNFS.exists(this.logFile))) {
|
|
152
|
-
await RNFS.writeFile(this.logFile,
|
|
153
|
-
console.log('🔧 Recovery: Created fresh log file');
|
|
123
|
+
await RNFS.writeFile(this.logFile, "", "utf8");
|
|
154
124
|
}
|
|
155
125
|
}
|
|
156
|
-
catch (recoveryError) {
|
|
157
|
-
console.error('❌ Recovery failed:', recoveryError);
|
|
158
|
-
}
|
|
126
|
+
catch (recoveryError) { }
|
|
159
127
|
}
|
|
160
128
|
finally {
|
|
161
|
-
// Always release the lock
|
|
162
129
|
this.isRotating = false;
|
|
163
130
|
}
|
|
164
131
|
}
|
|
165
|
-
// ------------------------
|
|
166
|
-
// Public accessors
|
|
167
|
-
// ------------------------
|
|
168
132
|
async getLogFileURL() {
|
|
169
133
|
if (!this.isAvailable)
|
|
170
|
-
return
|
|
134
|
+
return "";
|
|
171
135
|
return this.logFile;
|
|
172
136
|
}
|
|
173
137
|
async getLogFileContent() {
|
|
174
138
|
if (!this.isAvailable || !RNFS)
|
|
175
|
-
return
|
|
139
|
+
return "";
|
|
176
140
|
try {
|
|
177
141
|
if (await RNFS.exists(this.logFile)) {
|
|
178
|
-
return await RNFS.readFile(this.logFile,
|
|
142
|
+
return await RNFS.readFile(this.logFile, "utf8");
|
|
179
143
|
}
|
|
180
|
-
return
|
|
144
|
+
return "";
|
|
181
145
|
}
|
|
182
146
|
catch (e) {
|
|
183
|
-
console.error(
|
|
184
|
-
return
|
|
147
|
+
console.error("LoggerNative getLogFileContent error:", e);
|
|
148
|
+
return "";
|
|
185
149
|
}
|
|
186
150
|
}
|
|
187
151
|
async getBackupLogFileContent() {
|
|
188
152
|
if (!this.isAvailable || !RNFS)
|
|
189
153
|
return "";
|
|
190
154
|
try {
|
|
191
|
-
// Do NOT force rotation. Only return existing backup if present.
|
|
192
|
-
// await this.rotateLog();
|
|
193
155
|
if (await RNFS.exists(this.backupZip)) {
|
|
194
|
-
|
|
195
|
-
return await RNFS.readFile(this.backupZip, 'base64');
|
|
156
|
+
return await RNFS.readFile(this.backupZip, "base64");
|
|
196
157
|
}
|
|
197
158
|
return "";
|
|
198
159
|
}
|
|
199
160
|
catch (e) {
|
|
200
|
-
console.error(
|
|
161
|
+
console.error("LoggerNative getBackupLogFileContent error:", e);
|
|
201
162
|
return "";
|
|
202
163
|
}
|
|
203
164
|
}
|
|
@@ -206,12 +167,12 @@ export class LoggerNative {
|
|
|
206
167
|
return;
|
|
207
168
|
try {
|
|
208
169
|
if (await RNFS.exists(this.logFile))
|
|
209
|
-
await RNFS.writeFile(this.logFile,
|
|
170
|
+
await RNFS.writeFile(this.logFile, "", "utf8");
|
|
210
171
|
if (await RNFS.exists(this.backupZip))
|
|
211
172
|
await RNFS.unlink(this.backupZip);
|
|
212
173
|
}
|
|
213
174
|
catch (e) {
|
|
214
|
-
console.error(
|
|
175
|
+
console.error("LoggerNative clear error:", e);
|
|
215
176
|
}
|
|
216
177
|
}
|
|
217
178
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import type { ILoggerImplementation } from
|
|
1
|
+
import type { ILoggerImplementation } from "../Logger.types";
|
|
2
|
+
/**
|
|
3
|
+
* LoggerWeb - Web implementation using console logging only
|
|
4
|
+
*/
|
|
2
5
|
export declare class LoggerWeb implements ILoggerImplementation {
|
|
3
6
|
logFile: string;
|
|
4
7
|
init(): Promise<void>;
|
|
5
|
-
writeLine(line: string,
|
|
8
|
+
writeLine(line: string, _maxSize: number): Promise<void>;
|
|
6
9
|
getLogFileURL(): Promise<string>;
|
|
7
10
|
getLogFileContent(): Promise<string>;
|
|
8
11
|
getBackupLogFileContent(): Promise<string>;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoggerWeb - Web implementation using console logging only
|
|
3
|
+
*/
|
|
1
4
|
export class LoggerWeb {
|
|
2
5
|
constructor() {
|
|
3
|
-
this.logFile =
|
|
6
|
+
this.logFile = "";
|
|
4
7
|
}
|
|
5
8
|
async init() { }
|
|
6
|
-
async writeLine(line,
|
|
9
|
+
async writeLine(line, _maxSize) {
|
|
7
10
|
console.log(line);
|
|
8
11
|
}
|
|
9
|
-
async getLogFileURL() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
async getLogFileURL() {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
async getLogFileContent() {
|
|
16
|
+
return "";
|
|
17
|
+
}
|
|
18
|
+
async getBackupLogFileContent() {
|
|
19
|
+
return "";
|
|
20
|
+
}
|
|
12
21
|
async clear() { }
|
|
13
22
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
// ============================================
|
|
2
|
+
// Polyfills
|
|
3
|
+
// ============================================
|
|
4
|
+
const _global = typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : {};
|
|
5
|
+
if (typeof _global.window !== 'undefined') {
|
|
6
|
+
if (typeof _global.window.addEventListener === 'undefined') {
|
|
7
|
+
_global.window.addEventListener = () => { };
|
|
8
|
+
}
|
|
9
|
+
if (typeof _global.window.removeEventListener === 'undefined') {
|
|
10
|
+
_global.window.removeEventListener = () => { };
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
// ============================================
|
|
2
14
|
// Logger Module
|
|
3
15
|
// ============================================
|
|
4
16
|
export { Logger, logger } from './logger';
|