@lvce-editor/file-system-process 3.6.0 → 3.8.0

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.
Files changed (2) hide show
  1. package/dist/index.js +428 -454
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -216,16 +216,18 @@ const isEnoentError = error => {
216
216
  return isEnoentErrorLinux(error) || isEnoentErrorWindows(error);
217
217
  };
218
218
 
219
+ const FileSystemProcess = 210;
220
+ const MainProcess = -5;
221
+ const SharedProcess$1 = 1;
222
+
219
223
  const rpcs = Object.create(null);
220
- const set$g = (id, rpc) => {
224
+ const set$2 = (id, rpc) => {
221
225
  rpcs[id] = rpc;
222
226
  };
223
227
  const get$1 = id => {
224
228
  return rpcs[id];
225
229
  };
226
230
 
227
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
228
-
229
231
  const create$6 = rpcId => {
230
232
  return {
231
233
  // @ts-ignore
@@ -241,7 +243,7 @@ const create$6 = rpcId => {
241
243
  return rpc.invokeAndTransfer(method, ...params);
242
244
  },
243
245
  set(rpc) {
244
- set$g(rpcId, rpc);
246
+ set$2(rpcId, rpc);
245
247
  },
246
248
  async dispose() {
247
249
  const rpc = get$1(rpcId);
@@ -249,467 +251,118 @@ const create$6 = rpcId => {
249
251
  }
250
252
  };
251
253
  };
252
- const DebugWorker$1 = 55;
253
- const EditorWorker$1 = 99;
254
- const ExtensionHostWorker = 44;
255
- const MainProcess$1 = -5;
256
- const RendererWorker$1 = 1;
257
- const RendererProcess$1 = 1670;
258
- const SearchProcess$1 = 77;
259
- const SearchProcessElectron = 2;
260
- const SharedProcess$1 = 1;
261
- const SourceControlWorker = 66;
262
- const EmbedsProcess$1 = 207;
263
- const EmbedsWorker = 208;
264
- const FileSystemWorker$1 = 209;
265
- const FileSystemProcess$1 = 210;
266
- const MarkdownWorker$1 = 300;
267
- const CompletionWorker = 301;
268
- const ColorPickerWorker = 302;
269
- const SourceActionWorker = 303;
270
- const ErrorWorker$1 = 3308;
271
- const SyntaxHighlightingWorker$1 = 3309;
272
- const ClipBoardWorker$1 = 3400;
273
- const ClipBoardProcess$1 = 3401;
274
- const ExtensionDetailWorker = 3402;
275
- const ProblemsWorker = 3403;
276
- const RpcId = {
277
- __proto__: null,
278
- ClipBoardProcess: ClipBoardProcess$1,
279
- ClipBoardWorker: ClipBoardWorker$1,
280
- ColorPickerWorker,
281
- CompletionWorker,
282
- DebugWorker: DebugWorker$1,
283
- EditorWorker: EditorWorker$1,
284
- EmbedsProcess: EmbedsProcess$1,
285
- EmbedsWorker,
286
- ErrorWorker: ErrorWorker$1,
287
- ExtensionDetailWorker,
288
- ExtensionHostWorker,
289
- FileSystemProcess: FileSystemProcess$1,
290
- FileSystemWorker: FileSystemWorker$1,
291
- MainProcess: MainProcess$1,
292
- MarkdownWorker: MarkdownWorker$1,
293
- ProblemsWorker,
294
- RendererProcess: RendererProcess$1,
295
- RendererWorker: RendererWorker$1,
296
- SearchProcess: SearchProcess$1,
297
- SearchProcessElectron,
298
- SharedProcess: SharedProcess$1,
299
- SourceActionWorker,
300
- SourceControlWorker,
301
- SyntaxHighlightingWorker: SyntaxHighlightingWorker$1
302
- };
303
- const {
304
- invoke: invoke$1$1,
305
- invokeAndTransfer: invokeAndTransfer$1$1} = create$6(SharedProcess$1);
306
- const SharedProcess = {
307
- __proto__: null,
308
- invoke: invoke$1$1,
309
- invokeAndTransfer: invokeAndTransfer$1$1};
310
- const createLazyRpc = rpcId => {
311
- let rpcPromise;
312
- let factory;
313
- const createRpc = async () => {
314
- const rpc = await factory();
315
- set$g(rpcId, rpc);
316
- };
317
- const ensureRpc = async () => {
318
- if (!rpcPromise) {
319
- rpcPromise = createRpc();
320
- }
321
- await rpcPromise;
322
- };
323
- return {
324
- setFactory(value) {
325
- factory = value;
326
- },
327
- async invoke(method, ...params) {
328
- await ensureRpc();
329
- const rpc = get$1(rpcId);
330
- return rpc.invoke(method, ...params);
331
- }
332
- };
333
- };
334
254
 
335
- const {
336
- invoke: invoke$2,
337
- setFactory
338
- } = createLazyRpc(RpcId.MainProcess);
339
-
340
- const trash$2 = async path => {
341
- if (!existsSync(path)) {
342
- return;
343
- }
344
- // @ts-ignore
345
- await invoke$2('Trash.trash', path);
255
+ const isMessagePort = value => {
256
+ return value && value instanceof MessagePort;
346
257
  };
347
-
348
- // @ts-ignore
349
- const trash$1 = async path => {
350
- await _trash(path);
258
+ const isMessagePortMain = value => {
259
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
351
260
  };
352
-
353
- const getTrashFn = isElectron => {
354
- if (isElectron) {
355
- return trash$2;
356
- }
357
- return trash$1;
261
+ const isOffscreenCanvas = value => {
262
+ return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
358
263
  };
359
-
360
- const getElectronRunAsNode = () => {
361
- return process.env.ELECTRON_RUN_AS_NODE || '';
264
+ const isInstanceOf = (value, constructorName) => {
265
+ return value?.constructor?.name === constructorName;
362
266
  };
363
-
364
- const isElectron = Boolean(getElectronRunAsNode()) || 'electron' in process.versions;
365
-
366
- const trash = async path => {
367
- if (!path || path.trim() === '') {
368
- throw new Error('Path cannot be empty');
369
- }
370
- try {
371
- const fn = getTrashFn(isElectron);
372
- await fn(path);
373
- } catch (error) {
374
- throw new VError(error, 'Failed to move item to trash');
375
- }
267
+ const isSocket = value => {
268
+ return isInstanceOf(value, 'Socket');
376
269
  };
377
-
378
- const copy = async (sourceUri, targetUri) => {
379
- try {
380
- assertUri(sourceUri);
381
- assertUri(targetUri);
382
- const source = fileURLToPath(sourceUri);
383
- const target = fileURLToPath(targetUri);
384
- await fs.cp(source, target, {
385
- recursive: true
386
- });
387
- } catch (error) {
388
- if (error && error.message && error.message.startsWith('Invalid src or dest: cp returned EINVAL (src and dest cannot be the same)')) {
389
- throw new VError(`Failed to copy "${sourceUri}" to "${targetUri}": src and dest cannot be the same`);
270
+ const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
271
+ const isTransferrable = value => {
272
+ for (const fn of transferrables) {
273
+ if (fn(value)) {
274
+ return true;
390
275
  }
391
- throw new VError(error, `Failed to copy "${sourceUri}" to "${targetUri}"`);
392
276
  }
277
+ return false;
393
278
  };
394
- const readFile = async (uri, encoding = Utf8) => {
395
- try {
396
- string(uri);
397
- assertUri(uri);
398
- const path = fileURLToPath(uri);
399
- const content = await fs.readFile(path, encoding);
400
- return content;
401
- } catch (error) {
402
- if (isEnoentError(error)) {
403
- throw new FileNotFoundError(uri);
404
- }
405
- throw new VError(error, `Failed to read file "${uri}"`);
279
+ const walkValue = (value, transferrables, isTransferrable) => {
280
+ if (!value) {
281
+ return;
406
282
  }
407
- };
408
- const writeFile = async (uri, content, encoding = Utf8) => {
409
- try {
410
- assertUri(uri);
411
- string(uri);
412
- string(content);
413
- const path = fileURLToPath(uri);
414
- // queue would be more correct for concurrent writes but also slower
415
- // Queue.add(`writeFile/${path}`, () =>
416
- await fs.writeFile(path, content, encoding);
417
- } catch (error) {
418
- if (isEnoentError(error)) {
419
- throw new FileNotFoundError(uri);
283
+ if (isTransferrable(value)) {
284
+ transferrables.push(value);
285
+ return;
286
+ }
287
+ if (Array.isArray(value)) {
288
+ for (const item of value) {
289
+ walkValue(item, transferrables, isTransferrable);
420
290
  }
421
- throw new VError(error, `Failed to write to file "${uri}"`);
291
+ return;
422
292
  }
423
- };
424
- const appendFile = async (uri, content) => {
425
- try {
426
- assertUri(uri);
427
- string(uri);
428
- string(content);
429
- const path = fileURLToPath(uri);
430
- await fs.appendFile(path, content);
431
- } catch (error) {
432
- if (isEnoentError(error)) {
433
- throw new FileNotFoundError(uri);
293
+ if (typeof value === 'object') {
294
+ for (const property of Object.values(value)) {
295
+ walkValue(property, transferrables, isTransferrable);
434
296
  }
435
- throw new VError(error, `Failed to append to file "${uri}"`);
297
+ return;
436
298
  }
437
299
  };
438
- const isOkayToRemove = path => {
439
- if (path === '/') {
440
- return false;
300
+ const getTransferrables = value => {
301
+ const transferrables = [];
302
+ walkValue(value, transferrables, isTransferrable);
303
+ return transferrables;
304
+ };
305
+ const removeValues = (value, toRemove) => {
306
+ if (!value) {
307
+ return value;
441
308
  }
442
- if (path === '~') {
443
- return false;
309
+ if (Array.isArray(value)) {
310
+ const newItems = [];
311
+ for (const item of value) {
312
+ if (!toRemove.includes(item)) {
313
+ newItems.push(removeValues(item, toRemove));
314
+ }
315
+ }
316
+ return newItems;
444
317
  }
445
- if (path === os.homedir()) {
446
- return false;
318
+ if (typeof value === 'object') {
319
+ const newObject = Object.create(null);
320
+ for (const [key, property] of Object.entries(value)) {
321
+ if (!toRemove.includes(property)) {
322
+ newObject[key] = removeValues(property, toRemove);
323
+ }
324
+ }
325
+ return newObject;
447
326
  }
448
- return true;
327
+ return value;
449
328
  };
450
- const remove$1 = async uri => {
451
- assertUri(uri);
452
- const path = fileURLToPath(uri);
453
- if (!isOkayToRemove(path)) {
454
- console.warn('not removing path');
455
- return;
456
- }
457
329
 
458
- // TODO lazyload trash (doesn't work currently because of bug with jest)
459
- // const { trash } = await import('../../wrap/trash.js')
460
- try {
461
- await trash(path);
462
- } catch (error) {
463
- throw new VError(error, `Failed to remove "${uri}"`);
464
- }
465
- };
466
- const toPrettyDirent = dirent => {
330
+ // workaround for electron not supporting transferrable objects
331
+ // as parameters. If the transferrable object is a parameter, in electron
332
+ // only an empty objected is received in the main process
333
+ const fixElectronParameters = value => {
334
+ const transfer = getTransferrables(value);
335
+ const newValue = removeValues(value, transfer);
467
336
  return {
468
- name: dirent.name,
469
- type: getDirentType(dirent)
337
+ newValue,
338
+ transfer
470
339
  };
471
340
  };
472
- const readDirWithFileTypes = async uri => {
473
- try {
474
- assertUri(uri);
475
- const path = fileURLToPath(uri);
476
- const dirents = await fs.readdir(path, {
477
- withFileTypes: true
478
- });
479
- const prettyDirents = dirents.map(toPrettyDirent);
480
- return prettyDirents;
481
- } catch (error) {
482
- throw new VError(error, `Failed to read directory "${uri}"`);
341
+ const getActualDataElectron = event => {
342
+ const {
343
+ data,
344
+ ports
345
+ } = event;
346
+ if (ports.length === 0) {
347
+ return data;
483
348
  }
349
+ return {
350
+ ...data,
351
+ params: [...ports, ...data.params]
352
+ };
484
353
  };
485
- const mkdir = async uri => {
486
- try {
487
- assertUri(uri);
488
- const path = fileURLToPath(uri);
489
- await fs.mkdir(path, {
490
- recursive: true
491
- });
492
- } catch (error) {
493
- throw new VError(error, `Failed to create directory "${uri}"`);
494
- }
495
- };
496
- const exists = async uri => {
497
- assertUri(uri);
498
- const path = fileURLToPath(uri);
499
- return existsSync(path);
500
- };
501
- const fallbackRename = async (oldUri, newUri) => {
502
- try {
503
- const oldPath = fileURLToPath(oldUri);
504
- const newPath = fileURLToPath(newUri);
505
- await fs.cp(oldPath, newPath, {
506
- recursive: true
507
- });
508
- await fs.rm(oldPath, {
509
- recursive: true
510
- });
511
- } catch (error) {
512
- throw new VError(error, `Failed to rename "${oldUri}" to "${newUri}"`);
513
- }
514
- };
515
- const rename = async (oldUri, newUri) => {
516
- try {
517
- const oldPath = fileURLToPath(oldUri);
518
- const newPath = fileURLToPath(newUri);
519
- await fs.rename(oldPath, newPath);
520
- } catch (error) {
521
- if (error && error.code === EXDEV) {
522
- return fallbackRename(oldUri, newUri);
523
- }
524
- throw new VError(error, `Failed to rename "${oldUri}" to "${newUri}"`);
525
- }
526
- };
527
- const getPathSeparator = () => {
528
- return '/';
529
- };
530
- const stat = async uri => {
531
- const path = fileURLToPath(uri);
532
- const stats = await fs.stat(path);
533
- const type = getDirentType(stats);
534
- return type;
535
- };
536
- const chmod = async (uri, permissions) => {
537
- const path = fileURLToPath(uri);
538
- await fs.chmod(path, permissions);
539
- };
540
- const readJson = async uri => {
541
- try {
542
- string(uri);
543
- assertUri(uri);
544
- const path = fileURLToPath(uri);
545
- const content = await fs.readFile(path, 'utf8');
546
- const parsed = JSON.parse(content);
547
- return parsed;
548
- } catch (error) {
549
- if (isEnoentError(error)) {
550
- throw new FileNotFoundError(uri);
551
- }
552
- throw new VError(error, `Failed to read file as json "${uri}"`);
553
- }
554
- };
555
- const getFolderSize = async uri => {
556
- const path = fileURLToPath(uri);
557
- const total = await getFolderSizeInternal(path);
558
- return total;
559
- };
560
-
561
- const fileWacherEvents = Object.create(null);
562
- const setupWatcher = async (watcherId, uri, onChange) => {
563
- try {
564
- const path = fileURLToPath(uri);
565
- // TODO
566
- const watcher = fs.watch(path, {});
567
- const watcherEvents = [];
568
- fileWacherEvents[watcherId] = watcherEvents;
569
- for await (const event of watcher) {
570
- watcherEvents.push(event);
571
- onChange();
572
- }
573
- } catch (error) {
574
- if (error && error.code === 'ENOENT') {
575
- return;
576
- }
577
- console.error(error);
578
- }
579
- };
580
-
581
- // TODO when socket closes, dispose file watcher for this socket
582
- const watchFile = async (socket, watcherId, uri) => {
583
- assertUri(uri);
584
- fileWacherEvents[watcherId] = [];
585
- // TODO await promise?
586
- const onChange = () => {
587
- // TODO handle error
588
- socket.send({
589
- jsonrpc: '2.0',
590
- method: 'FileSystem.executeWatchCallback',
591
- params: [watcherId]
592
- });
593
- };
594
-
595
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
596
- setupWatcher(watcherId, uri, onChange);
597
- };
598
- const unwatchFile = uri => {
599
- // TODO
600
- };
601
-
602
- const isMessagePort = value => {
603
- return value && value instanceof MessagePort;
604
- };
605
- const isMessagePortMain = value => {
606
- return value && value.constructor && value.constructor.name === 'MessagePortMain';
607
- };
608
- const isOffscreenCanvas = value => {
609
- return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
610
- };
611
- const isInstanceOf = (value, constructorName) => {
612
- return value?.constructor?.name === constructorName;
613
- };
614
- const isSocket = value => {
615
- return isInstanceOf(value, 'Socket');
616
- };
617
- const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
618
- const isTransferrable = value => {
619
- for (const fn of transferrables) {
620
- if (fn(value)) {
621
- return true;
622
- }
623
- }
624
- return false;
625
- };
626
- const walkValue = (value, transferrables, isTransferrable) => {
627
- if (!value) {
628
- return;
629
- }
630
- if (isTransferrable(value)) {
631
- transferrables.push(value);
632
- return;
633
- }
634
- if (Array.isArray(value)) {
635
- for (const item of value) {
636
- walkValue(item, transferrables, isTransferrable);
637
- }
638
- return;
639
- }
640
- if (typeof value === 'object') {
641
- for (const property of Object.values(value)) {
642
- walkValue(property, transferrables, isTransferrable);
643
- }
644
- return;
645
- }
646
- };
647
- const getTransferrables = value => {
648
- const transferrables = [];
649
- walkValue(value, transferrables, isTransferrable);
650
- return transferrables;
651
- };
652
- const removeValues = (value, toRemove) => {
653
- if (!value) {
654
- return value;
655
- }
656
- if (Array.isArray(value)) {
657
- const newItems = [];
658
- for (const item of value) {
659
- if (!toRemove.includes(item)) {
660
- newItems.push(removeValues(item, toRemove));
661
- }
662
- }
663
- return newItems;
664
- }
665
- if (typeof value === 'object') {
666
- const newObject = Object.create(null);
667
- for (const [key, property] of Object.entries(value)) {
668
- if (!toRemove.includes(property)) {
669
- newObject[key] = removeValues(property, toRemove);
670
- }
671
- }
672
- return newObject;
673
- }
674
- return value;
675
- };
676
-
677
- // workaround for electron not supporting transferrable objects
678
- // as parameters. If the transferrable object is a parameter, in electron
679
- // only an empty objected is received in the main process
680
- const fixElectronParameters = value => {
681
- const transfer = getTransferrables(value);
682
- const newValue = removeValues(value, transfer);
683
- return {
684
- newValue,
685
- transfer
686
- };
687
- };
688
- const getActualDataElectron = event => {
689
- const {
690
- data,
691
- ports
692
- } = event;
693
- if (ports.length === 0) {
694
- return data;
695
- }
696
- return {
697
- ...data,
698
- params: [...ports, ...data.params]
699
- };
700
- };
701
- const attachEvents = that => {
702
- const handleMessage = (...args) => {
703
- const data = that.getData(...args);
704
- that.dispatchEvent(new MessageEvent('message', {
705
- data
706
- }));
707
- };
708
- that.onMessage(handleMessage);
709
- const handleClose = event => {
710
- that.dispatchEvent(new Event('close'));
711
- };
712
- that.onClose(handleClose);
354
+ const attachEvents = that => {
355
+ const handleMessage = (...args) => {
356
+ const data = that.getData(...args);
357
+ that.dispatchEvent(new MessageEvent('message', {
358
+ data
359
+ }));
360
+ };
361
+ that.onMessage(handleMessage);
362
+ const handleClose = event => {
363
+ that.dispatchEvent(new Event('close'));
364
+ };
365
+ that.onClose(handleClose);
713
366
  };
714
367
  class Ipc extends EventTarget {
715
368
  constructor(rawIpc) {
@@ -921,7 +574,7 @@ const listen$a = () => {
921
574
  parentPort
922
575
  } = process;
923
576
  if (!parentPort) {
924
- throw new Error('parent port must be defined');
577
+ throw new IpcError('parent port must be defined');
925
578
  }
926
579
  return parentPort;
927
580
  };
@@ -979,7 +632,7 @@ const getTransferrablesNode = value => {
979
632
  };
980
633
  const listen$5 = async () => {
981
634
  if (!process.send) {
982
- throw new Error('process.send must be defined');
635
+ throw new IpcError('process.send must be defined');
983
636
  }
984
637
  return process;
985
638
  };
@@ -1238,13 +891,13 @@ const create$4 = (method, params) => {
1238
891
  };
1239
892
  };
1240
893
  const callbacks = Object.create(null);
1241
- const set = (id, fn) => {
894
+ const set$1 = (id, fn) => {
1242
895
  callbacks[id] = fn;
1243
896
  };
1244
897
  const get = id => {
1245
898
  return callbacks[id];
1246
899
  };
1247
- const remove = id => {
900
+ const remove$1 = id => {
1248
901
  delete callbacks[id];
1249
902
  };
1250
903
  let id = 0;
@@ -1257,7 +910,7 @@ const registerPromise = () => {
1257
910
  resolve,
1258
911
  promise
1259
912
  } = Promise.withResolvers();
1260
- set(id, resolve);
913
+ set$1(id, resolve);
1261
914
  return {
1262
915
  id,
1263
916
  promise
@@ -1429,7 +1082,7 @@ const resolve = (id, response) => {
1429
1082
  return;
1430
1083
  }
1431
1084
  fn(response);
1432
- remove(id);
1085
+ remove$1(id);
1433
1086
  };
1434
1087
  const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
1435
1088
  const getErrorType = prettyError => {
@@ -1602,10 +1255,10 @@ const send = (transport, method, ...params) => {
1602
1255
  const message = create$4(method, params);
1603
1256
  transport.send(message);
1604
1257
  };
1605
- const invoke$1 = (ipc, method, ...params) => {
1258
+ const invoke$3 = (ipc, method, ...params) => {
1606
1259
  return invokeHelper(ipc, method, params, false);
1607
1260
  };
1608
- const invokeAndTransfer$1 = (ipc, method, ...params) => {
1261
+ const invokeAndTransfer$2 = (ipc, method, ...params) => {
1609
1262
  return invokeHelper(ipc, method, params, true);
1610
1263
  };
1611
1264
 
@@ -1641,10 +1294,10 @@ const createRpc = ipc => {
1641
1294
  send(ipc, method, ...params);
1642
1295
  },
1643
1296
  invoke(method, ...params) {
1644
- return invoke$1(ipc, method, ...params);
1297
+ return invoke$3(ipc, method, ...params);
1645
1298
  },
1646
1299
  invokeAndTransfer(method, ...params) {
1647
- return invokeAndTransfer$1(ipc, method, ...params);
1300
+ return invokeAndTransfer$2(ipc, method, ...params);
1648
1301
  },
1649
1302
  async dispose() {
1650
1303
  await ipc?.dispose();
@@ -1769,6 +1422,326 @@ const NodeWorkerRpcClient = {
1769
1422
  create: create$7
1770
1423
  };
1771
1424
 
1425
+ const {
1426
+ invoke: invoke$2,
1427
+ invokeAndTransfer: invokeAndTransfer$1,
1428
+ set,
1429
+ dispose
1430
+ } = create$6(SharedProcess$1);
1431
+
1432
+ const SharedProcess = {
1433
+ __proto__: null,
1434
+ dispose,
1435
+ invoke: invoke$2,
1436
+ invokeAndTransfer: invokeAndTransfer$1,
1437
+ set
1438
+ };
1439
+
1440
+ const createLazyRpc = rpcId => {
1441
+ let rpcPromise;
1442
+ let factory;
1443
+ const createRpc = async () => {
1444
+ const rpc = await factory();
1445
+ set$2(rpcId, rpc);
1446
+ };
1447
+ const ensureRpc = async () => {
1448
+ if (!rpcPromise) {
1449
+ rpcPromise = createRpc();
1450
+ }
1451
+ await rpcPromise;
1452
+ };
1453
+ return {
1454
+ setFactory(value) {
1455
+ factory = value;
1456
+ },
1457
+ async invoke(method, ...params) {
1458
+ await ensureRpc();
1459
+ const rpc = get$1(rpcId);
1460
+ return rpc.invoke(method, ...params);
1461
+ }
1462
+ };
1463
+ };
1464
+
1465
+ const {
1466
+ invoke: invoke$1,
1467
+ setFactory
1468
+ } = createLazyRpc(MainProcess);
1469
+
1470
+ const trash$2 = async path => {
1471
+ if (!existsSync(path)) {
1472
+ return;
1473
+ }
1474
+ // @ts-ignore
1475
+ await invoke$1('Trash.trash', path);
1476
+ };
1477
+
1478
+ // @ts-ignore
1479
+ const trash$1 = async path => {
1480
+ await _trash(path);
1481
+ };
1482
+
1483
+ const getTrashFn = isElectron => {
1484
+ if (isElectron) {
1485
+ return trash$2;
1486
+ }
1487
+ return trash$1;
1488
+ };
1489
+
1490
+ const getElectronRunAsNode = () => {
1491
+ return process.env.ELECTRON_RUN_AS_NODE || '';
1492
+ };
1493
+
1494
+ const isElectron = Boolean(getElectronRunAsNode()) || 'electron' in process.versions;
1495
+
1496
+ const trash = async path => {
1497
+ if (!path || path.trim() === '') {
1498
+ throw new Error('Path cannot be empty');
1499
+ }
1500
+ try {
1501
+ const fn = getTrashFn(isElectron);
1502
+ await fn(path);
1503
+ } catch (error) {
1504
+ throw new VError(error, 'Failed to move item to trash');
1505
+ }
1506
+ };
1507
+
1508
+ const copy = async (sourceUri, targetUri) => {
1509
+ try {
1510
+ assertUri(sourceUri);
1511
+ assertUri(targetUri);
1512
+ const source = fileURLToPath(sourceUri);
1513
+ const target = fileURLToPath(targetUri);
1514
+ await fs.cp(source, target, {
1515
+ recursive: true
1516
+ });
1517
+ } catch (error) {
1518
+ if (error && error.message && error.message.startsWith('Invalid src or dest: cp returned EINVAL (src and dest cannot be the same)')) {
1519
+ throw new VError(`Failed to copy "${sourceUri}" to "${targetUri}": src and dest cannot be the same`);
1520
+ }
1521
+ throw new VError(error, `Failed to copy "${sourceUri}" to "${targetUri}"`);
1522
+ }
1523
+ };
1524
+ const readFile = async (uri, encoding = Utf8) => {
1525
+ try {
1526
+ string(uri);
1527
+ assertUri(uri);
1528
+ const path = fileURLToPath(uri);
1529
+ const content = await fs.readFile(path, encoding);
1530
+ return content;
1531
+ } catch (error) {
1532
+ if (isEnoentError(error)) {
1533
+ throw new FileNotFoundError(uri);
1534
+ }
1535
+ throw new VError(error, `Failed to read file "${uri}"`);
1536
+ }
1537
+ };
1538
+ const writeFile = async (uri, content, encoding = Utf8) => {
1539
+ try {
1540
+ assertUri(uri);
1541
+ string(uri);
1542
+ string(content);
1543
+ const path = fileURLToPath(uri);
1544
+ // queue would be more correct for concurrent writes but also slower
1545
+ // Queue.add(`writeFile/${path}`, () =>
1546
+ await fs.writeFile(path, content, encoding);
1547
+ } catch (error) {
1548
+ if (isEnoentError(error)) {
1549
+ throw new FileNotFoundError(uri);
1550
+ }
1551
+ throw new VError(error, `Failed to write to file "${uri}"`);
1552
+ }
1553
+ };
1554
+ const writeBuffer = async (uri, buffer) => {
1555
+ try {
1556
+ assertUri(uri);
1557
+ string(uri);
1558
+ const path = fileURLToPath(uri);
1559
+ await fs.writeFile(path, buffer);
1560
+ } catch (error) {
1561
+ if (isEnoentError(error)) {
1562
+ throw new FileNotFoundError(uri);
1563
+ }
1564
+ throw new VError(error, `Failed to write to file "${uri}"`);
1565
+ }
1566
+ };
1567
+ const appendFile = async (uri, content) => {
1568
+ try {
1569
+ assertUri(uri);
1570
+ string(uri);
1571
+ string(content);
1572
+ const path = fileURLToPath(uri);
1573
+ await fs.appendFile(path, content);
1574
+ } catch (error) {
1575
+ if (isEnoentError(error)) {
1576
+ throw new FileNotFoundError(uri);
1577
+ }
1578
+ throw new VError(error, `Failed to append to file "${uri}"`);
1579
+ }
1580
+ };
1581
+ const isOkayToRemove = path => {
1582
+ if (path === '/') {
1583
+ return false;
1584
+ }
1585
+ if (path === '~') {
1586
+ return false;
1587
+ }
1588
+ if (path === os.homedir()) {
1589
+ return false;
1590
+ }
1591
+ return true;
1592
+ };
1593
+ const remove = async uri => {
1594
+ assertUri(uri);
1595
+ const path = fileURLToPath(uri);
1596
+ if (!isOkayToRemove(path)) {
1597
+ console.warn('not removing path');
1598
+ return;
1599
+ }
1600
+
1601
+ // TODO lazyload trash (doesn't work currently because of bug with jest)
1602
+ // const { trash } = await import('../../wrap/trash.js')
1603
+ try {
1604
+ await trash(path);
1605
+ } catch (error) {
1606
+ throw new VError(error, `Failed to remove "${uri}"`);
1607
+ }
1608
+ };
1609
+ const toPrettyDirent = dirent => {
1610
+ return {
1611
+ name: dirent.name,
1612
+ type: getDirentType(dirent)
1613
+ };
1614
+ };
1615
+ const readDirWithFileTypes = async uri => {
1616
+ try {
1617
+ assertUri(uri);
1618
+ const path = fileURLToPath(uri);
1619
+ const dirents = await fs.readdir(path, {
1620
+ withFileTypes: true
1621
+ });
1622
+ const prettyDirents = dirents.map(toPrettyDirent);
1623
+ return prettyDirents;
1624
+ } catch (error) {
1625
+ throw new VError(error, `Failed to read directory "${uri}"`);
1626
+ }
1627
+ };
1628
+ const mkdir = async uri => {
1629
+ try {
1630
+ assertUri(uri);
1631
+ const path = fileURLToPath(uri);
1632
+ await fs.mkdir(path, {
1633
+ recursive: true
1634
+ });
1635
+ } catch (error) {
1636
+ throw new VError(error, `Failed to create directory "${uri}"`);
1637
+ }
1638
+ };
1639
+ const exists = async uri => {
1640
+ assertUri(uri);
1641
+ const path = fileURLToPath(uri);
1642
+ return existsSync(path);
1643
+ };
1644
+ const fallbackRename = async (oldUri, newUri) => {
1645
+ try {
1646
+ const oldPath = fileURLToPath(oldUri);
1647
+ const newPath = fileURLToPath(newUri);
1648
+ await fs.cp(oldPath, newPath, {
1649
+ recursive: true
1650
+ });
1651
+ await fs.rm(oldPath, {
1652
+ recursive: true
1653
+ });
1654
+ } catch (error) {
1655
+ throw new VError(error, `Failed to rename "${oldUri}" to "${newUri}"`);
1656
+ }
1657
+ };
1658
+ const rename = async (oldUri, newUri) => {
1659
+ try {
1660
+ const oldPath = fileURLToPath(oldUri);
1661
+ const newPath = fileURLToPath(newUri);
1662
+ await fs.rename(oldPath, newPath);
1663
+ } catch (error) {
1664
+ if (error && error.code === EXDEV) {
1665
+ return fallbackRename(oldUri, newUri);
1666
+ }
1667
+ throw new VError(error, `Failed to rename "${oldUri}" to "${newUri}"`);
1668
+ }
1669
+ };
1670
+ const getPathSeparator = () => {
1671
+ return '/';
1672
+ };
1673
+ const stat = async uri => {
1674
+ const path = fileURLToPath(uri);
1675
+ const stats = await fs.stat(path);
1676
+ const type = getDirentType(stats);
1677
+ return type;
1678
+ };
1679
+ const chmod = async (uri, permissions) => {
1680
+ const path = fileURLToPath(uri);
1681
+ await fs.chmod(path, permissions);
1682
+ };
1683
+ const readJson = async uri => {
1684
+ try {
1685
+ string(uri);
1686
+ assertUri(uri);
1687
+ const path = fileURLToPath(uri);
1688
+ const content = await fs.readFile(path, 'utf8');
1689
+ const parsed = JSON.parse(content);
1690
+ return parsed;
1691
+ } catch (error) {
1692
+ if (isEnoentError(error)) {
1693
+ throw new FileNotFoundError(uri);
1694
+ }
1695
+ throw new VError(error, `Failed to read file as json "${uri}"`);
1696
+ }
1697
+ };
1698
+ const getFolderSize = async uri => {
1699
+ const path = fileURLToPath(uri);
1700
+ const total = await getFolderSizeInternal(path);
1701
+ return total;
1702
+ };
1703
+
1704
+ const fileWacherEvents = Object.create(null);
1705
+ const setupWatcher = async (watcherId, uri, onChange) => {
1706
+ try {
1707
+ const path = fileURLToPath(uri);
1708
+ // TODO
1709
+ const watcher = fs.watch(path, {});
1710
+ const watcherEvents = [];
1711
+ fileWacherEvents[watcherId] = watcherEvents;
1712
+ for await (const event of watcher) {
1713
+ watcherEvents.push(event);
1714
+ onChange();
1715
+ }
1716
+ } catch (error) {
1717
+ if (error && error.code === 'ENOENT') {
1718
+ return;
1719
+ }
1720
+ console.error(new VError(error, `Failed to setup watcher for ${uri}`));
1721
+ }
1722
+ };
1723
+
1724
+ // TODO when socket closes, dispose file watcher for this socket
1725
+ const watchFile = async (socket, watcherId, uri) => {
1726
+ assertUri(uri);
1727
+ fileWacherEvents[watcherId] = [];
1728
+ // TODO await promise?
1729
+ const onChange = () => {
1730
+ // TODO handle error
1731
+ socket.send({
1732
+ jsonrpc: '2.0',
1733
+ method: 'FileSystem.executeWatchCallback',
1734
+ params: [watcherId]
1735
+ });
1736
+ };
1737
+
1738
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1739
+ setupWatcher(watcherId, uri, onChange);
1740
+ };
1741
+ const unwatchFile = uri => {
1742
+ // TODO
1743
+ };
1744
+
1772
1745
  const NodeWorker = 1;
1773
1746
  const NodeForkedProcess = 2;
1774
1747
  const ElectronUtilityProcess = 3;
@@ -1820,7 +1793,7 @@ const handleElectronMessagePort = async (messagePort, rpcId) => {
1820
1793
  messagePort
1821
1794
  });
1822
1795
  if (rpcId) {
1823
- set$g(rpcId, rpc);
1796
+ set$2(rpcId, rpc);
1824
1797
  }
1825
1798
  };
1826
1799
 
@@ -1855,7 +1828,7 @@ const getPortTuple$1 = async () => {
1855
1828
  const id1 = create();
1856
1829
  const id2 = create();
1857
1830
  // @ts-ignore
1858
- await invoke('TemporaryMessagePort.getPortTuple3', id1, id2, RpcId.FileSystemProcess);
1831
+ await invoke('TemporaryMessagePort.getPortTuple3', id1, id2, FileSystemProcess);
1859
1832
  const port1 = ports[id1];
1860
1833
  const port2 = ports[id2];
1861
1834
  delete ports[id1];
@@ -1893,7 +1866,7 @@ const createMainProcessRpc = async () => {
1893
1866
  } = await getPortTuple();
1894
1867
  await invokeAndTransfer(
1895
1868
  // @ts-ignore
1896
- 'TemporaryMessagePort.sendToElectron', port1, RpcId.MainProcess, RpcId.FileSystemProcess);
1869
+ 'TemporaryMessagePort.sendToElectron', port1, MainProcess, FileSystemProcess);
1897
1870
  const rpc = await ElectronMessagePortRpcClient.create({
1898
1871
  commandMap: {},
1899
1872
  messagePort: port2
@@ -1919,12 +1892,13 @@ const commandMap = {
1919
1892
  'FileSystem.readDirWithFileTypes': readDirWithFileTypes,
1920
1893
  'FileSystem.readFile': readFile,
1921
1894
  'FileSystem.readJson': readJson,
1922
- 'FileSystem.remove': remove$1,
1895
+ 'FileSystem.remove': remove,
1923
1896
  'FileSystem.rename': rename,
1924
1897
  'FileSystem.stat': stat,
1925
1898
  'FileSystem.unwatchFile': unwatchFile,
1926
1899
  'FileSystem.watchFile': watchFile,
1927
1900
  'FileSystem.writeFile': writeFile,
1901
+ 'FileSystem.writeBuffer': writeBuffer,
1928
1902
  'HandleElectronMessagePort.handleElectronMessagePort': handleElectronMessagePort,
1929
1903
  'HandleWebSocket.handleWebSocket': handleWebSocket,
1930
1904
  'Initialize.initialize': initialize,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/file-system-process",
3
- "version": "3.6.0",
3
+ "version": "3.8.0",
4
4
  "description": "File System Process",
5
5
  "keywords": [
6
6
  "Lvce Editor",
@@ -18,7 +18,7 @@
18
18
  "file-system-process": "bin/fileSystemProcess.js"
19
19
  },
20
20
  "dependencies": {
21
- "trash": "^9.0.0",
21
+ "trash": "^10.0.0",
22
22
  "ws": "^8.18.3"
23
23
  },
24
24
  "engines": {