"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FsaNodeSyncWorker = void 0; const SyncMessenger_1 = require("./SyncMessenger"); const FsaNodeFs_1 = require("../FsaNodeFs"); const json_1 = require("../json"); class FsaNodeSyncWorker { constructor() { this.sab = new SharedArrayBuffer(1024 * 1024); this.messenger = new SyncMessenger_1.SyncMessenger(this.sab); this.onPostMessage = (msg) => { switch (msg[0]) { case 1 /* FsaNodeWorkerMessageCode.SetRoot */: { const [, id, dir] = msg; this.root = dir; this.fs = new FsaNodeFs_1.FsaNodeFs(this.root); const response = [2 /* FsaNodeWorkerMessageCode.RootSet */, id]; postMessage(response); this.messenger.serveAsync(this.onRequest); break; } } }; this.onRequest = async (request) => { try { const message = json_1.decoder.decode(request); if (!Array.isArray(message)) throw new Error('Invalid message format'); const code = message[0]; if (code !== 3 /* FsaNodeWorkerMessageCode.Request */) throw new Error('Invalid message code'); const [, method, payload] = message; const handler = this.handlers[method]; if (!handler) throw new Error(`Unknown method ${method}`); const response = await handler(payload); return json_1.encoder.encode([4 /* FsaNodeWorkerMessageCode.Response */, response]); } catch (err) { const message = err && typeof err === 'object' && err.message ? err.message : 'Unknown error'; const error = { message }; if (err && typeof err === 'object' && (err.code || err.name)) error.code = err.code || err.name; return json_1.encoder.encode([5 /* FsaNodeWorkerMessageCode.ResponseError */, error]); } }; this.handlers = { stat: async (location) => { const handle = await this.getFileOrDir(location[0], location[1], 'statSync'); return { kind: handle.kind, }; }, access: async ([filename, mode]) => { await this.fs.promises.access(filename, mode); }, readFile: async ([filename, opts]) => { const buf = (await this.fs.promises.readFile(filename, Object.assign(Object.assign({}, opts), { encoding: 'buffer' }))); const uint8 = new Uint8Array(buf, buf.byteOffset, buf.byteLength); return uint8; }, writeFile: async ([filename, data, opts]) => { await this.fs.promises.writeFile(filename, data, Object.assign(Object.assign({}, opts), { encoding: 'buffer' })); }, appendFile: async ([filename, data, opts]) => { await this.fs.promises.appendFile(filename, data, Object.assign(Object.assign({}, opts), { encoding: 'buffer' })); }, copy: async ([src, dst, flags]) => { await this.fs.promises.copyFile(src, dst, flags); }, move: async ([src, dst]) => { await this.fs.promises.rename(src, dst); }, rmdir: async ([filename, options]) => { await this.fs.promises.rmdir(filename, options); }, rm: async ([filename, options]) => { await this.fs.promises.rm(filename, options); }, mkdir: async ([filename, options]) => { return await this.fs.promises.mkdir(filename, options); }, mkdtemp: async ([filename]) => { return (await this.fs.promises.mkdtemp(filename, { encoding: 'utf8' })); }, trunc: async ([filename, len]) => { await this.fs.promises.truncate(filename, len); }, unlink: async ([filename]) => { await this.fs.promises.unlink(filename); }, readdir: async ([filename]) => { const list = (await this.fs.promises.readdir(filename, { withFileTypes: true, encoding: 'utf8' })); const res = list.map(entry => ({ kind: entry.isDirectory() ? 'directory' : 'file', name: entry.name, })); return res; }, read: async ([filename, position, length]) => { let uint8 = new Uint8Array(length); const handle = await this.fs.promises.open(filename, 'r'); const bytesRead = await new Promise((resolve, reject) => { this.fs.read(handle.fd, uint8, 0, length, position, (err, bytesRead) => { if (err) return reject(err); resolve(bytesRead || length); }); }); if (bytesRead < length) uint8 = uint8.slice(0, bytesRead); return uint8; }, write: async ([filename, data, position]) => { const handle = await this.fs.promises.open(filename, 'a'); const { bytesWritten } = await handle.write(data, 0, data.length, position || undefined); return bytesWritten; }, open: async ([filename, flags, mode]) => { const handle = await this.fs.promises.open(filename, flags, mode); const file = await this.fs.__getFileById(handle.fd); await handle.close(); return file; }, }; } start() { onmessage = e => { if (!Array.isArray(e.data)) return; this.onPostMessage(e.data); }; const initMsg = [0 /* FsaNodeWorkerMessageCode.Init */, this.sab]; postMessage(initMsg); } async getDir(path, create, funcName) { let curr = this.root; const options = { create }; try { for (const name of path) { curr = await curr.getDirectoryHandle(name, options); } } catch (error) { // if (error && typeof error === 'object' && error.name === 'TypeMismatchError') // throw createError('ENOTDIR', funcName, path.join(FsaToNodeConstants.Separator)); throw error; } return curr; } async getFile(path, name, funcName, create) { const dir = await this.getDir(path, false, funcName); const file = await dir.getFileHandle(name, { create }); return file; } async getFileOrDir(path, name, funcName, create) { const dir = await this.getDir(path, false, funcName); try { const file = await dir.getFileHandle(name); return file; } catch (error) { if (error && typeof error === 'object') { switch (error.name) { case 'TypeMismatchError': return await dir.getDirectoryHandle(name); // case 'NotFoundError': // throw createError('ENOENT', funcName, path.join(FsaToNodeConstants.Separator)); } } throw error; } } } exports.FsaNodeSyncWorker = FsaNodeSyncWorker; //# sourceMappingURL=FsaNodeSyncWorker.js.map