2323
2424const { Errors} = require ( "./errno" ) ;
2525const { Utils} = require ( "./utils" ) ;
26+ const { Constants} = require ( "./constants" ) ;
27+
28+ const IS_WINDOWS = navigator . userAgent . includes ( 'Windows' ) ;
2629
2730const WS_COMMAND = {
2831 PING : "ping" ,
2932 RESPONSE : "response" ,
30- LARGE_DATA_SOCKET_ANNOUNCE : "largeDataSock"
33+ LARGE_DATA_SOCKET_ANNOUNCE : "largeDataSock" ,
34+ CONTROL_SOCKET_ANNOUNCE : "controlSock" ,
35+ GET_WINDOWS_DRIVES : "getWinDrives"
3136} ;
3237
3338// each browser context belongs to a single socket group. So multiple websocket connections can be pooled
3439// to increase throughput. Note that socketGroupID will be different for each web workers/threads in the window as
3540// they are separate contexts.
3641const socketGroupID = Math . floor ( Math . random ( ) * 4294967296 ) ;
37- let commandIdCounter = 0 ;
42+ let commandIdCounter = 1 ; // should be greater than 0!
3843let wssEndpoint , controlSocket , dataSocket ;
3944const SOCKET_TYPE_DATA = "data" ,
4045 SOCKET_TYPE_CONTROL = "control" ;
4146const LARGE_DATA_THRESHOLD = 2 * 1024 * 1024 ; // 2MB
4247const MAX_RECONNECT_BACKOFF_TIME_MS = 1000 ;
4348
49+ function mapNodeTauriErrorMessage ( nodeErrorMessage , path , userMessage = '' ) {
50+ switch ( nodeErrorMessage ) {
51+ case '2' : return new Errors . ENOENT ( userMessage + ` No such File or Directory: ` + path + nodeErrorMessage , path ) ;
52+ case '3' : return new Errors . ENOENT ( userMessage + ` System cannot find the path specified: ` + path + nodeErrorMessage , path ) ; // windows
53+ case '17' : return new Errors . EEXIST ( userMessage + ` File exists: ` + path + nodeErrorMessage , path ) ;
54+ case '183' : return new Errors . EEXIST ( userMessage + ` File exists: ` + path + nodeErrorMessage , path ) ; // windows
55+ case '39' : return new Errors . ENOTEMPTY ( userMessage + ` Directory not empty: ` + path + nodeErrorMessage , path ) ;
56+ case '20' : return new Errors . ENOTDIR ( userMessage + ` Not a Directory: ` + path + nodeErrorMessage , path ) ;
57+ case '13' : return new Errors . EACCES ( userMessage + ` Permission denied: ` + path + nodeErrorMessage , path ) ;
58+ case '21' : return new Errors . EISDIR ( userMessage + ` Is a directory: ` + path + nodeErrorMessage , path ) ;
59+ case '9' : return new Errors . EBADF ( userMessage + ` Bad file number: ` + path + nodeErrorMessage , path ) ;
60+ case '30' : return new Errors . EROFS ( userMessage + ` Read-only file system: ` + path + nodeErrorMessage , path ) ;
61+ case '28' : return new Errors . ENOSPC ( userMessage + ` No space left on device: ` + path + nodeErrorMessage , path ) ;
62+ case '16' : return new Errors . EBUSY ( userMessage + ` Device or resource busy: ` + path + nodeErrorMessage , path ) ;
63+ case '22' : return new Errors . EINVAL ( userMessage + ` Invalid argument: ` + path + nodeErrorMessage , path ) ;
64+ default : return new Errors . EIO ( userMessage + ` IO error on path: ` + path + nodeErrorMessage , path ) ;
65+ }
66+ }
67+
68+
4469function _getCommand ( command , data ) {
4570 return {
4671 commandCode : command ,
@@ -84,6 +109,7 @@ function _execCommandInternal(command, commandData, binaryData, resolve, reject)
84109 * @param command {string}
85110 * @param commandData {Object}
86111 * @param binaryData {ArrayBuffer}
112+ * @returns {Promise<{metadata: Object, bufferData: ArrayBuffer}> } A promise that resolves with an object containing `metadata` and `bufferData` or rejects with error.
87113 */
88114function _execCommand ( command , commandData , binaryData ) {
89115 return new Promise ( ( resolve , reject ) => {
@@ -109,7 +135,7 @@ function _execPendingCommands() {
109135function _processMessage ( data ) {
110136 const { metadata, bufferData} = Utils . splitMetadataAndBuffer ( data ) ;
111137 if ( ! metadata . commandId || ! commandIdMap [ metadata . commandId ] ) {
112- throw new Error ( "CommandID not found in ws response! " + JSON . parse ( metadata ) ) ;
138+ throw new Error ( "CommandID not found in ws response! " + metadata ) ;
113139 }
114140 const { resolve, reject} = commandIdMap [ metadata . commandId ] ;
115141 if ( metadata . error ) {
@@ -148,6 +174,9 @@ async function _establishAndMaintainConnection(socketType, firstConnectCB) {
148174 if ( ws . isLargeDataWS ) {
149175 _execCommand ( WS_COMMAND . LARGE_DATA_SOCKET_ANNOUNCE )
150176 . catch ( console . error ) ;
177+ } else {
178+ _execCommand ( WS_COMMAND . CONTROL_SOCKET_ANNOUNCE )
179+ . catch ( console . error ) ;
151180 }
152181 _execPendingCommands ( ) ;
153182 } ) ;
@@ -164,10 +193,13 @@ async function _establishAndMaintainConnection(socketType, firstConnectCB) {
164193 wsClosePromiseResolve ( ) ;
165194 } ) ;
166195 await wsClosePromise ;
167- ws . backoffTime = Math . min ( ws . backoffTime * 2 , MAX_RECONNECT_BACKOFF_TIME_MS ) || 1 ;
168- await _wait ( ws . backoffTime ) ;
196+ const backoffTime = Math . min ( ws . backoffTime * 2 , MAX_RECONNECT_BACKOFF_TIME_MS ) || 1 ;
197+ ws . backoffTime = backoffTime ;
198+ await _wait ( backoffTime ) ;
169199 if ( ws . autoReconnect ) {
200+ console . log ( wssEndpoint ) ;
170201 ws = new WebSocket ( wssEndpoint ) ;
202+ ws . backoffTime = backoffTime ;
171203 ws . binaryType = 'arraybuffer' ;
172204 ws . autoReconnect = true ;
173205 }
@@ -202,6 +234,18 @@ async function setNodeWSEndpoint(websocketEndpoint) {
202234 } ) ;
203235}
204236
237+ function stopNodeWSEndpoint ( ) {
238+ _silentlyCloseSocket ( controlSocket ) ;
239+ controlSocket = null ;
240+ _silentlyCloseSocket ( dataSocket ) ;
241+ dataSocket = null ;
242+ wssEndpoint = null ;
243+ }
244+
245+ function getNodeWSEndpoint ( ) {
246+ return wssEndpoint ;
247+ }
248+
205249function testNodeWsEndpoint ( wsEndPoint , echoData , echoBuffer ) {
206250 return new Promise ( ( resolve , reject ) => {
207251 const ws = new WebSocket ( wsEndPoint ) ;
@@ -246,9 +290,31 @@ function testNodeWsEndpoint(wsEndPoint, echoData, echoBuffer) {
246290 } ) ;
247291}
248292
293+ function readdir ( path , options , callback ) {
294+ if ( IS_WINDOWS && path === Constants . TAURI_ROOT ) {
295+ _execCommand ( WS_COMMAND . GET_WINDOWS_DRIVES )
296+ . then ( drives => {
297+ console . log ( drives ) ;
298+ // let entries = [];
299+ // for(let drive of drives) {
300+ // entries.push({name: drive});
301+ // }
302+ //_readDirHelper(entries, path, options, callback, true);
303+ // console.log(entries);
304+ } )
305+ . catch ( ( err ) => {
306+ callback ( mapNodeTauriErrorMessage ( err , path , 'Failed to get drives: ' ) ) ;
307+ } ) ;
308+ return ;
309+ }
310+ }
311+
249312const NodeTauriFS = {
250313 testNodeWsEndpoint,
251- setNodeWSEndpoint
314+ setNodeWSEndpoint,
315+ stopNodeWSEndpoint,
316+ getNodeWSEndpoint,
317+ readdir
252318} ;
253319
254320module . exports = {
0 commit comments