@unvired/react-native-unvired-sdk 0.0.28 → 0.0.30
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/services/DatabaseNative.js +7 -4
- package/dist/logger/BaseLogger.js +9 -5
- package/package.json +1 -1
- package/test-app/filepath.ts +0 -107
- package/ts-core/PlatformInterface.ts +0 -109
- package/ts-core/ReactNativePlatformAdapter.ts +0 -143
- package/wrapper/fileService.ts +0 -313
package/BuildNo.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
R-0.000.
|
|
1
|
+
R-0.000.0030
|
|
@@ -20,8 +20,9 @@ export class DatabaseNative {
|
|
|
20
20
|
return {
|
|
21
21
|
create: async (options, successCallback, errorCallback) => {
|
|
22
22
|
try {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const dbName = options.name || options.userId;
|
|
24
|
+
this.getDatabase(dbName, options.location);
|
|
25
|
+
successCallback({ success: true, database: dbName });
|
|
25
26
|
}
|
|
26
27
|
catch (error) {
|
|
27
28
|
errorCallback(error instanceof Error ? error.message : String(error));
|
|
@@ -29,9 +30,11 @@ export class DatabaseNative {
|
|
|
29
30
|
},
|
|
30
31
|
execute: async (options, successCallback, errorCallback) => {
|
|
31
32
|
try {
|
|
32
|
-
const
|
|
33
|
+
const dbName = options.dbName || options.userId;
|
|
34
|
+
const params = options.params || options.args || [];
|
|
35
|
+
const db = this.getDatabase(dbName);
|
|
33
36
|
// FIX: Await the result properly
|
|
34
|
-
const res = await db.execute(options.query,
|
|
37
|
+
const res = await db.execute(options.query, params);
|
|
35
38
|
let resultToReturn = [];
|
|
36
39
|
// Cast to any to avoid TS error "Property '_array' does not exist on type 'never'"
|
|
37
40
|
const rawRes = res;
|
|
@@ -45,13 +45,17 @@ export class BaseLogger {
|
|
|
45
45
|
return;
|
|
46
46
|
const line = this.format(className, methodName, message, level);
|
|
47
47
|
// console always
|
|
48
|
-
/*
|
|
49
48
|
switch (level) {
|
|
50
|
-
case 'debug':
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
53
58
|
}
|
|
54
|
-
*/
|
|
55
59
|
await this.impl.writeLine(line, MAX_LOG_SIZE);
|
|
56
60
|
}
|
|
57
61
|
// -------------------------
|
package/package.json
CHANGED
package/test-app/filepath.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import UnviredWrapper from '@unvired/react-native-wrapper-sdk';
|
|
2
|
-
|
|
3
|
-
const wrapper = new UnviredWrapper();
|
|
4
|
-
const fileServiceRaw = wrapper.file();
|
|
5
|
-
|
|
6
|
-
// Helper to convert ArrayBuffer to string (Native JS - No Buffer Dependency)
|
|
7
|
-
function arrayBufferToString(buffer: ArrayBuffer): string {
|
|
8
|
-
// Handling small to medium files. For very large files, chunking is needed to avoid stack overflow.
|
|
9
|
-
return String.fromCharCode.apply(null, new Uint8Array(buffer) as any);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
class SDKFileService {
|
|
13
|
-
|
|
14
|
-
// Delegate standard methods
|
|
15
|
-
getDocumentDirectoryPath() {
|
|
16
|
-
return fileServiceRaw.getDocumentDirectory();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async createFile(fileName: string, content: string): Promise<string> {
|
|
20
|
-
const dir = fileServiceRaw.getDocumentDirectory();
|
|
21
|
-
|
|
22
|
-
// Ensure dir ends with slash
|
|
23
|
-
const path = (dir.endsWith('/') ? dir : dir + '/') + fileName;
|
|
24
|
-
|
|
25
|
-
// FIX: React Native Blob implementation has issues with direct ArrayBuffer views in some versions.
|
|
26
|
-
// Passing string directly to writeExternalFile allows the underlying Blob([content]) to work
|
|
27
|
-
// because Blob([string]) is supported.
|
|
28
|
-
const data = content;
|
|
29
|
-
|
|
30
|
-
console.log(`[SDKFileService] Creating file ${fileName} at ${path}`);
|
|
31
|
-
await fileServiceRaw.writeExternalFile(dir, fileName, data as any);
|
|
32
|
-
return path;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async readFile(fileName: string): Promise<string> {
|
|
36
|
-
let path = fileName;
|
|
37
|
-
// If not absolute path, prepend doc dir
|
|
38
|
-
if (!fileName.startsWith('/') && !fileName.startsWith('file://')) {
|
|
39
|
-
const dir = fileServiceRaw.getDocumentDirectory();
|
|
40
|
-
path = (dir.endsWith('/') ? dir : dir + '/') + fileName;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Cleaning file:// prefix if present
|
|
44
|
-
if (path.startsWith('file://')) {
|
|
45
|
-
path = path.replace('file://', '');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
console.log(`[SDKFileService] Reading file: ${path}`);
|
|
49
|
-
const data = await fileServiceRaw.readExternalFile(path);
|
|
50
|
-
return arrayBufferToString(data);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async deleteFile(fileName: string): Promise<void> {
|
|
54
|
-
let path = fileName;
|
|
55
|
-
if (!fileName.startsWith('/') && !fileName.startsWith('file://')) {
|
|
56
|
-
const dir = fileServiceRaw.getDocumentDirectory();
|
|
57
|
-
path = (dir.endsWith('/') ? dir : dir + '/') + fileName;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Cleaning file:// prefix if present
|
|
61
|
-
if (path.startsWith('file://')) {
|
|
62
|
-
path = path.replace('file://', '');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
console.log(`[SDKFileService] Deleting file: ${path}`);
|
|
66
|
-
await fileServiceRaw.deleteExternalFile(path);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async listFiles(): Promise<any[]> {
|
|
70
|
-
const dir = fileServiceRaw.getDocumentDirectory();
|
|
71
|
-
console.log(`[SDKFileService] Listing files in: ${dir}`);
|
|
72
|
-
|
|
73
|
-
// Use resolveLocalFileSystemURL to get DirectoryEntry
|
|
74
|
-
let dirEntry;
|
|
75
|
-
try {
|
|
76
|
-
dirEntry = await fileServiceRaw.resolveLocalFileSystemURL(dir);
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.error('[SDKFileService] Failed to resolve directory:', e);
|
|
79
|
-
return [];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return new Promise((resolve, reject) => {
|
|
83
|
-
try {
|
|
84
|
-
const reader = dirEntry.createReader();
|
|
85
|
-
reader.readEntries((entries: any[]) => {
|
|
86
|
-
console.log(`[SDKFileService] Found ${entries.length} entries`);
|
|
87
|
-
const mapped = entries.map(e => ({
|
|
88
|
-
uri: e.nativeURL || e.fullPath,
|
|
89
|
-
name: e.name,
|
|
90
|
-
isDirectory: e.isDirectory,
|
|
91
|
-
size: 0,
|
|
92
|
-
modificationTime: Date.now() / 1000
|
|
93
|
-
}));
|
|
94
|
-
resolve(mapped);
|
|
95
|
-
}, (err: any) => {
|
|
96
|
-
console.error('[SDKFileService] Failed to list files (readEntries):', err);
|
|
97
|
-
resolve([]); // Don't crash UI
|
|
98
|
-
});
|
|
99
|
-
} catch (e) {
|
|
100
|
-
console.error('[SDKFileService] Exception in listFiles:', e);
|
|
101
|
-
resolve([]);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export default new SDKFileService();
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform Adapter Interface
|
|
3
|
-
*
|
|
4
|
-
* This interface abstracts platform-specific functionality so that the core SDK
|
|
5
|
-
* can work with both Cordova and React Native platforms.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export enum DatabaseType {
|
|
9
|
-
FrameworkDb = 'FrameworkDb',
|
|
10
|
-
AppDb = 'AppDb'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface IDeviceInfo {
|
|
14
|
-
platform: string;
|
|
15
|
-
model: string;
|
|
16
|
-
version: string;
|
|
17
|
-
isMobile: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface IFileEntry {
|
|
21
|
-
fullPath: string;
|
|
22
|
-
nativeURL: string;
|
|
23
|
-
isDirectory?: boolean;
|
|
24
|
-
remove(callback: () => void, errorCallback: (error: any) => void): void;
|
|
25
|
-
removeRecursively(callback: () => void, errorCallback: (error: any) => void): void;
|
|
26
|
-
createReader(): IDirectoryReader;
|
|
27
|
-
getDirectory?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
|
|
28
|
-
getFile?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
|
|
29
|
-
file?(callback: (file: File) => void, errorCallback: (error: any) => void): void;
|
|
30
|
-
createWriter?(callback: (writer: any) => void, errorCallback: (error: any) => void): void;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface IDirectoryReader {
|
|
34
|
-
readEntries(callback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface IDatabaseAdapter {
|
|
38
|
-
create(options: { userId: string }, successCallback: (result: any) => void, errorCallback: (error: any) => void): void;
|
|
39
|
-
execute(options: any, successCallback: (result: any) => void, errorCallback: (error: any) => void): void;
|
|
40
|
-
executeStatementOnPath(dbPath: string, sqlQuery: string, callback: (result: any) => void): void;
|
|
41
|
-
selectFromPath(dbPath: string, sqlQuery: string, callback: (result: any) => void): void;
|
|
42
|
-
createDatabase(dbPath: string, callback: () => void): void;
|
|
43
|
-
getDBFilePath(options: { dbType: string }, callback: (path: string) => void): void;
|
|
44
|
-
saveWebDB(options: { userId: string }, callback: (result: any) => void, errorCallback: (error: any) => void): void;
|
|
45
|
-
exportWebDB(options: { userId: string }, callback: (result: any) => void, errorCallback: (error: any) => void): void;
|
|
46
|
-
deleteUserData(options: { userId: string }, callback: () => void, errorCallback: (error: any) => void): void;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface IPushNotificationAdapter {
|
|
50
|
-
requestPermission(options?: { forceShow: boolean }): Promise<void>;
|
|
51
|
-
getToken(): Promise<string>;
|
|
52
|
-
onTokenRefresh(callback: (token: string) => void): void;
|
|
53
|
-
onMessage(callback: (payload: any) => void): void;
|
|
54
|
-
onBackgroundMessage(callback: (payload: any) => void): void;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface ILoggerAdapter {
|
|
58
|
-
logDebug(sourceClass: string, method: string, message: string): void;
|
|
59
|
-
logError(sourceClass: string, method: string, message: string): void;
|
|
60
|
-
logInfo(sourceClass: string, method: string, message: string): void;
|
|
61
|
-
setLogLevel(logLevel: string): void;
|
|
62
|
-
getLogFileURL(): Promise<string>;
|
|
63
|
-
getLogFileContent(): Promise<string>;
|
|
64
|
-
getBackupLogFileContent(): Promise<string>;
|
|
65
|
-
clearLogFile(): void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface IStorageAdapter {
|
|
69
|
-
getItem(key: string): void;
|
|
70
|
-
setItem(key: string, value: string): void;
|
|
71
|
-
removeItem(key: string): void;
|
|
72
|
-
clear(): void;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
export interface ILocalStorageAdapter {
|
|
78
|
-
getItem(key: string): void;
|
|
79
|
-
setItem(key: string, value: string): void;
|
|
80
|
-
removeItem(key: string): void;
|
|
81
|
-
clear(): void;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Main Platform Adapter Interface
|
|
85
|
-
*/
|
|
86
|
-
export interface PlatformInterface {
|
|
87
|
-
// Device Information
|
|
88
|
-
getDeviceInfo(): IDeviceInfo;
|
|
89
|
-
getPlatform(): string;
|
|
90
|
-
getFrontendType(): string;
|
|
91
|
-
getDocumentDirectory(): string;
|
|
92
|
-
|
|
93
|
-
// File System Operations
|
|
94
|
-
resolveLocalFileSystemURL(url: string): Promise<IFileEntry>;
|
|
95
|
-
getFolderBasedOnUserId(userId: string): Promise<string>;
|
|
96
|
-
deleteUserFolder(userId: string): Promise<void>;
|
|
97
|
-
|
|
98
|
-
// Database Operations
|
|
99
|
-
getDatabaseAdapter(): IDatabaseAdapter;
|
|
100
|
-
|
|
101
|
-
// Push Notifications
|
|
102
|
-
getPushNotificationAdapter(): IPushNotificationAdapter | null;
|
|
103
|
-
|
|
104
|
-
// Logging
|
|
105
|
-
getLoggerAdapter(): ILoggerAdapter;
|
|
106
|
-
|
|
107
|
-
// Storage
|
|
108
|
-
getStorageAdapter(): IStorageAdapter;
|
|
109
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { DeviceInfo, DatabaseManager, LocalStorage, logger, LogLevel, PushNotification, FileSystem } from '@unvired/react-native-unvired-sdk';
|
|
2
|
-
import { PlatformInterface, IDeviceInfo, IFileEntry, IDatabaseAdapter, IPushNotificationAdapter, ILoggerAdapter, IStorageAdapter } from './PlatformInterface';
|
|
3
|
-
|
|
4
|
-
export class ReactNativePlatformAdapter implements PlatformInterface {
|
|
5
|
-
|
|
6
|
-
getDeviceInfo(): IDeviceInfo {
|
|
7
|
-
return DeviceInfo.getDeviceInfo();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
getPlatform(): string {
|
|
11
|
-
return DeviceInfo.getPlatform();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
getFrontendType(): string {
|
|
15
|
-
return DeviceInfo.getFrontendType();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
getDocumentDirectory(): string {
|
|
19
|
-
return FileSystem.getDocumentDirectory();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
resolveLocalFileSystemURL(url: string): Promise<IFileEntry> {
|
|
23
|
-
return FileSystem.resolveLocalFileSystemURL(url);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async getFolderBasedOnUserId(userId: string): Promise<string> {
|
|
27
|
-
return await FileSystem.getFolderBasedOnUserId(userId);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async deleteUserFolder(userId: string): Promise<void> {
|
|
31
|
-
await FileSystem.deleteUserFolder(userId);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
getDatabaseAdapter(): IDatabaseAdapter {
|
|
35
|
-
return {
|
|
36
|
-
create: (options: { userId: string }, successCallback, errorCallback) => {
|
|
37
|
-
// Map userId to dbName or pass appropriate options
|
|
38
|
-
DatabaseManager.getDatabaseAdapter().create({ name: options.userId }, successCallback, errorCallback);
|
|
39
|
-
},
|
|
40
|
-
execute: (options: any, successCallback, errorCallback) => {
|
|
41
|
-
DatabaseManager.getDatabaseAdapter().execute({
|
|
42
|
-
dbName: options.userId,
|
|
43
|
-
query: options.query,
|
|
44
|
-
params: options.params
|
|
45
|
-
}, successCallback, errorCallback);
|
|
46
|
-
},
|
|
47
|
-
executeStatementOnPath: (dbPath, sqlQuery, callback) => {
|
|
48
|
-
DatabaseManager.getDatabaseAdapter().executeStatementOnPath(dbPath, sqlQuery, callback);
|
|
49
|
-
},
|
|
50
|
-
selectFromPath: (dbPath, sqlQuery, callback) => {
|
|
51
|
-
DatabaseManager.getDatabaseAdapter().selectFromPath(dbPath, sqlQuery, callback);
|
|
52
|
-
},
|
|
53
|
-
createDatabase: (dbPath, callback) => {
|
|
54
|
-
DatabaseManager.getDatabaseAdapter().createDatabase(dbPath, callback);
|
|
55
|
-
},
|
|
56
|
-
getDBFilePath: (options: { dbType: string }, callback) => {
|
|
57
|
-
DatabaseManager.getDatabaseAdapter().getDBFilePath({ name: options.dbType }, callback);
|
|
58
|
-
},
|
|
59
|
-
saveWebDB: (options: { userId: string }, callback, errorCallback) => {
|
|
60
|
-
const dbName = options.userId;
|
|
61
|
-
const data = (options as any).data || {};
|
|
62
|
-
DatabaseManager.getDatabaseAdapter().saveWebDB({ dbName, data }, callback, errorCallback);
|
|
63
|
-
},
|
|
64
|
-
exportWebDB: (options: { userId: string }, callback, errorCallback) => {
|
|
65
|
-
DatabaseManager.getDatabaseAdapter().exportWebDB({ dbName: options.userId }, callback, errorCallback);
|
|
66
|
-
},
|
|
67
|
-
deleteUserData: (options: { userId: string }, callback, errorCallback) => {
|
|
68
|
-
DatabaseManager.getDatabaseAdapter().deleteUserData({ dbName: options.userId, userId: options.userId }, callback, errorCallback);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getPushNotificationAdapter(): IPushNotificationAdapter | null {
|
|
74
|
-
try {
|
|
75
|
-
const pushNotification = new PushNotification();
|
|
76
|
-
return {
|
|
77
|
-
requestPermission: async (options = { forceShow: false }) => {
|
|
78
|
-
await pushNotification.requestPermission(options);
|
|
79
|
-
},
|
|
80
|
-
getToken: async () => {
|
|
81
|
-
return await pushNotification.getToken();
|
|
82
|
-
},
|
|
83
|
-
onTokenRefresh: (callback) => {
|
|
84
|
-
pushNotification.onTokenRefresh(callback);
|
|
85
|
-
},
|
|
86
|
-
onMessage: (callback) => {
|
|
87
|
-
pushNotification.onMessage(callback);
|
|
88
|
-
},
|
|
89
|
-
onBackgroundMessage: (callback) => {
|
|
90
|
-
pushNotification.onBackgroundMessage(callback);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
} catch (error) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
getLoggerAdapter(): ILoggerAdapter {
|
|
99
|
-
return {
|
|
100
|
-
logDebug: (sourceClass, method, message) => {
|
|
101
|
-
logger.logDebug(sourceClass, method, message);
|
|
102
|
-
},
|
|
103
|
-
logError: (sourceClass, method, message) => {
|
|
104
|
-
logger.logError(sourceClass, method, message);
|
|
105
|
-
},
|
|
106
|
-
logInfo: (sourceClass, method, message) => {
|
|
107
|
-
logger.logInfo(sourceClass, method, message);
|
|
108
|
-
},
|
|
109
|
-
setLogLevel: (logLevel: LogLevel) => {
|
|
110
|
-
logger.setLogLevel(logLevel);
|
|
111
|
-
},
|
|
112
|
-
getLogFileURL: async () => {
|
|
113
|
-
return logger.getLogFileURL();
|
|
114
|
-
},
|
|
115
|
-
getLogFileContent: async () => {
|
|
116
|
-
return logger.getLogFileContent();
|
|
117
|
-
},
|
|
118
|
-
getBackupLogFileContent: async () => {
|
|
119
|
-
return logger.getBackupLogFileContent();
|
|
120
|
-
},
|
|
121
|
-
clearLogFile: async () => {
|
|
122
|
-
logger.clearLogFile();
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
getStorageAdapter(): IStorageAdapter {
|
|
128
|
-
return {
|
|
129
|
-
getItem: (key: string) => {
|
|
130
|
-
return LocalStorage.getItem(key);
|
|
131
|
-
},
|
|
132
|
-
setItem: (key: string, value: string) => {
|
|
133
|
-
return LocalStorage.setItem(key, value);
|
|
134
|
-
},
|
|
135
|
-
removeItem: (key: string) => {
|
|
136
|
-
return LocalStorage.removeItem(key);
|
|
137
|
-
},
|
|
138
|
-
clear: () => {
|
|
139
|
-
return LocalStorage.clear();
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
}
|
package/wrapper/fileService.ts
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import { PlatformManager } from '@unvired/unvired-ts-core-sdk';
|
|
2
|
-
|
|
3
|
-
export interface IDirectoryReader {
|
|
4
|
-
readEntries(successCallback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface IFileEntry {
|
|
8
|
-
fullPath: string;
|
|
9
|
-
nativeURL: string;
|
|
10
|
-
isDirectory?: boolean;
|
|
11
|
-
remove(callback: () => void, errorCallback: (error: any) => void): void;
|
|
12
|
-
removeRecursively(callback: () => void, errorCallback: (error: any) => void): void;
|
|
13
|
-
createReader(): IDirectoryReader;
|
|
14
|
-
getDirectory?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
|
|
15
|
-
getFile?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
|
|
16
|
-
file?(callback: (file: File) => void, errorCallback: (error: any) => void): void;
|
|
17
|
-
createWriter?(callback: (writer: any) => void, errorCallback: (error: any) => void): void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class FileService {
|
|
21
|
-
|
|
22
|
-
getDocumentDirectory(): string {
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
return PlatformManager.getInstance().getPlatformAdapter().getDocumentDirectory();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
resolveLocalFileSystemURL(url: string): Promise<IFileEntry> {
|
|
28
|
-
// @ts-ignore
|
|
29
|
-
return PlatformManager.getInstance().getPlatformAdapter().resolveLocalFileSystemURL(url);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async getFolderBasedOnUserId(userId: string): Promise<string> {
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
return await PlatformManager.getInstance().getPlatformAdapter().getFolderBasedOnUserId(userId);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async deleteUserFolder(userId: string): Promise<void> {
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
await PlatformManager.getInstance().getPlatformAdapter().deleteUserFolder(userId);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Reads an external file as ArrayBuffer using IFileEntry API
|
|
44
|
-
* @param filePath Absolute path to the file
|
|
45
|
-
*/
|
|
46
|
-
async readExternalFile(filePath: string): Promise<ArrayBuffer> {
|
|
47
|
-
// Get the file entry
|
|
48
|
-
const fileEntry = await this.resolveLocalFileSystemURL(filePath);
|
|
49
|
-
|
|
50
|
-
return new Promise((resolve, reject) => {
|
|
51
|
-
// Use the file() method to read the file
|
|
52
|
-
if (!fileEntry.file) {
|
|
53
|
-
reject(new Error('file() method not available on entry'));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
fileEntry.file(
|
|
58
|
-
async (fileMetadata: any) => {
|
|
59
|
-
try {
|
|
60
|
-
// Read the file using react-native-fs
|
|
61
|
-
const RNFS = await import('react-native-fs');
|
|
62
|
-
const content = await RNFS.readFile(fileMetadata.path, 'utf8');
|
|
63
|
-
|
|
64
|
-
// Convert string to ArrayBuffer
|
|
65
|
-
const encoder = new TextEncoder();
|
|
66
|
-
resolve(encoder.encode(content).buffer);
|
|
67
|
-
} catch (error) {
|
|
68
|
-
reject(error);
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
(error: any) => {
|
|
72
|
-
reject(error);
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Writes data to an external file using IFileEntry API
|
|
80
|
-
* @param filePath Parent directory path
|
|
81
|
-
* @param fileName File name
|
|
82
|
-
* @param data Data to write (ArrayBuffer or string)
|
|
83
|
-
*/
|
|
84
|
-
async writeExternalFile(filePath: string, fileName: string, data: ArrayBuffer | string): Promise<void> {
|
|
85
|
-
// Convert data to string if it's ArrayBuffer
|
|
86
|
-
let content: string;
|
|
87
|
-
if (data instanceof ArrayBuffer) {
|
|
88
|
-
const decoder = new TextDecoder();
|
|
89
|
-
content = decoder.decode(data);
|
|
90
|
-
} else {
|
|
91
|
-
content = data;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Get the directory entry
|
|
95
|
-
const dirEntry = await this.resolveLocalFileSystemURL(filePath);
|
|
96
|
-
|
|
97
|
-
return new Promise((resolve, reject) => {
|
|
98
|
-
// Get or create the file
|
|
99
|
-
if (!dirEntry.getFile) {
|
|
100
|
-
reject(new Error('getFile() method not available on directory entry'));
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
dirEntry.getFile(
|
|
105
|
-
fileName,
|
|
106
|
-
{ create: true },
|
|
107
|
-
(fileEntry: IFileEntry) => {
|
|
108
|
-
// Create a writer
|
|
109
|
-
if (!fileEntry.createWriter) {
|
|
110
|
-
reject(new Error('createWriter() method not available on file entry'));
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
fileEntry.createWriter(
|
|
115
|
-
(writer: any) => {
|
|
116
|
-
writer.onwriteend = () => {
|
|
117
|
-
resolve();
|
|
118
|
-
};
|
|
119
|
-
writer.onerror = (error: any) => {
|
|
120
|
-
reject(error);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// Write the content
|
|
124
|
-
writer.write(content);
|
|
125
|
-
},
|
|
126
|
-
(error: any) => {
|
|
127
|
-
reject(error);
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
},
|
|
131
|
-
(error: any) => {
|
|
132
|
-
reject(error);
|
|
133
|
-
}
|
|
134
|
-
);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Deletes an external file using IFileEntry API
|
|
140
|
-
* @param filePath Absolute path to the file
|
|
141
|
-
*/
|
|
142
|
-
async deleteExternalFile(filePath: string): Promise<void> {
|
|
143
|
-
const fileEntry = await this.resolveLocalFileSystemURL(filePath);
|
|
144
|
-
|
|
145
|
-
return new Promise((resolve, reject) => {
|
|
146
|
-
fileEntry.remove(
|
|
147
|
-
() => resolve(),
|
|
148
|
-
(error: any) => reject(error)
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Checks if a file exists using IFileEntry API
|
|
155
|
-
* @param filePath Absolute path to the file
|
|
156
|
-
*/
|
|
157
|
-
async fileExists(filePath: string): Promise<boolean> {
|
|
158
|
-
try {
|
|
159
|
-
await this.resolveLocalFileSystemURL(filePath);
|
|
160
|
-
return true;
|
|
161
|
-
} catch (error) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Creates a directory
|
|
168
|
-
* @param dirPath Parent directory path
|
|
169
|
-
* @param dirName Directory name to create
|
|
170
|
-
*/
|
|
171
|
-
async createDirectory(dirPath: string, dirName: string): Promise<IFileEntry> {
|
|
172
|
-
const parentEntry = await this.resolveLocalFileSystemURL(dirPath);
|
|
173
|
-
|
|
174
|
-
return new Promise((resolve, reject) => {
|
|
175
|
-
if (!parentEntry.getDirectory) {
|
|
176
|
-
reject(new Error('getDirectory() method not available on entry'));
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
parentEntry.getDirectory(
|
|
181
|
-
dirName,
|
|
182
|
-
{ create: true },
|
|
183
|
-
(dirEntry: IFileEntry) => resolve(dirEntry),
|
|
184
|
-
(error: any) => reject(error)
|
|
185
|
-
);
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Lists files and directories in a directory
|
|
191
|
-
* @param dirPath Directory path to list
|
|
192
|
-
*/
|
|
193
|
-
async listDirectory(dirPath: string): Promise<IFileEntry[]> {
|
|
194
|
-
const dirEntry = await this.resolveLocalFileSystemURL(dirPath);
|
|
195
|
-
|
|
196
|
-
return new Promise((resolve, reject) => {
|
|
197
|
-
const reader = dirEntry.createReader();
|
|
198
|
-
reader.readEntries(
|
|
199
|
-
(entries: IFileEntry[]) => resolve(entries),
|
|
200
|
-
(error: any) => reject(error)
|
|
201
|
-
);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Deletes a directory and all its contents
|
|
207
|
-
* @param dirPath Directory path to delete
|
|
208
|
-
*/
|
|
209
|
-
async deleteDirectory(dirPath: string): Promise<void> {
|
|
210
|
-
const dirEntry = await this.resolveLocalFileSystemURL(dirPath);
|
|
211
|
-
|
|
212
|
-
return new Promise((resolve, reject) => {
|
|
213
|
-
dirEntry.removeRecursively(
|
|
214
|
-
() => resolve(),
|
|
215
|
-
(error: any) => reject(error)
|
|
216
|
-
);
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Copies a file
|
|
222
|
-
* @param sourcePath Source file path
|
|
223
|
-
* @param destDir Destination directory path
|
|
224
|
-
* @param newName New file name (optional, keeps original name if not provided)
|
|
225
|
-
*/
|
|
226
|
-
async copyFile(sourcePath: string, destDir: string, newName?: string): Promise<void> {
|
|
227
|
-
// Read source file
|
|
228
|
-
const content = await this.readExternalFile(sourcePath);
|
|
229
|
-
|
|
230
|
-
// Get source file name if newName not provided
|
|
231
|
-
const fileName = newName || sourcePath.split('/').pop() || 'file';
|
|
232
|
-
|
|
233
|
-
// Write to destination
|
|
234
|
-
await this.writeExternalFile(destDir, fileName, content);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Moves/renames a file
|
|
239
|
-
* @param sourcePath Source file path
|
|
240
|
-
* @param destDir Destination directory path
|
|
241
|
-
* @param newName New file name (optional, keeps original name if not provided)
|
|
242
|
-
*/
|
|
243
|
-
async moveFile(sourcePath: string, destDir: string, newName?: string): Promise<void> {
|
|
244
|
-
// Copy file to destination
|
|
245
|
-
await this.copyFile(sourcePath, destDir, newName);
|
|
246
|
-
|
|
247
|
-
// Delete source file
|
|
248
|
-
await this.deleteExternalFile(sourcePath);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Gets file information (size, modification date, etc.)
|
|
253
|
-
* @param filePath File path
|
|
254
|
-
*/
|
|
255
|
-
async getFileInfo(filePath: string): Promise<any> {
|
|
256
|
-
const fileEntry = await this.resolveLocalFileSystemURL(filePath);
|
|
257
|
-
|
|
258
|
-
return new Promise((resolve, reject) => {
|
|
259
|
-
if (!fileEntry.file) {
|
|
260
|
-
reject(new Error('file() method not available on entry'));
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
fileEntry.file(
|
|
265
|
-
(fileMetadata: any) => resolve(fileMetadata),
|
|
266
|
-
(error: any) => reject(error)
|
|
267
|
-
);
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Appends data to an existing file
|
|
273
|
-
* @param filePath File path
|
|
274
|
-
* @param data Data to append
|
|
275
|
-
*/
|
|
276
|
-
async appendToFile(filePath: string, data: ArrayBuffer | string): Promise<void> {
|
|
277
|
-
// Convert data to string if it's ArrayBuffer
|
|
278
|
-
let content: string;
|
|
279
|
-
if (data instanceof ArrayBuffer) {
|
|
280
|
-
const decoder = new TextDecoder();
|
|
281
|
-
content = decoder.decode(data);
|
|
282
|
-
} else {
|
|
283
|
-
content = data;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const fileEntry = await this.resolveLocalFileSystemURL(filePath);
|
|
287
|
-
|
|
288
|
-
return new Promise((resolve, reject) => {
|
|
289
|
-
if (!fileEntry.createWriter) {
|
|
290
|
-
reject(new Error('createWriter() method not available on file entry'));
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
fileEntry.createWriter(
|
|
295
|
-
(writer: any) => {
|
|
296
|
-
writer.onwriteend = () => {
|
|
297
|
-
resolve();
|
|
298
|
-
};
|
|
299
|
-
writer.onerror = (error: any) => {
|
|
300
|
-
reject(error);
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
// Append the content
|
|
304
|
-
writer.append(content);
|
|
305
|
-
},
|
|
306
|
-
(error: any) => {
|
|
307
|
-
reject(error);
|
|
308
|
-
}
|
|
309
|
-
);
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
}
|