@flighthq/filesystem 0.4.0-next.1903.50bfa67 → 0.4.0-next.1908.751021c

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/filesystem",
3
- "version": "0.4.0-next.1903.50bfa67",
3
+ "version": "0.4.0-next.1908.751021c",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,8 +38,8 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/dialog": "0.4.0-next.1903.50bfa67",
42
- "@flighthq/types": "0.4.0-next.1903.50bfa67"
41
+ "@flighthq/dialog": "0.4.0-next.1908.751021c",
42
+ "@flighthq/types": "0.4.0-next.1908.751021c"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.3.0"
@@ -52,6 +52,10 @@ import {
52
52
  writeDialogHandleTextFile,
53
53
  writeFileAtomic,
54
54
  writeTextFile,
55
+ explainFileSystemBackend,
56
+ installFileSystemHostBackend,
57
+ observeFileSystemHostResult,
58
+ resetFileSystemBackendForTest,
55
59
  } from './filesystem';
56
60
 
57
61
  function fakeBackend(): FileSystemBackend {
@@ -360,6 +364,34 @@ describe('directoryExists', () => {
360
364
  });
361
365
  });
362
366
 
367
+ describe('explainFileSystemBackend', () => {
368
+ afterEach(() => resetFileSystemBackendForTest());
369
+
370
+ it('reports host-not-enabled when no backend is installed', () => {
371
+ resetFileSystemBackendForTest();
372
+ const explanation = explainFileSystemBackend();
373
+ expect(explanation.layer).toBe('host-not-enabled');
374
+ expect(explanation.conflict).toBe(false);
375
+ expect(explanation.viability).toBe('unobserved');
376
+ });
377
+
378
+ it('reports custom layer when a custom backend is set', () => {
379
+ setFileSystemBackend(fakeBackend());
380
+ expect(explainFileSystemBackend().layer).toBe('custom');
381
+ });
382
+
383
+ it('reports host layer when a host backend is installed', () => {
384
+ installFileSystemHostBackend(fakeBackend());
385
+ expect(explainFileSystemBackend().layer).toBe('host');
386
+ });
387
+
388
+ it('reports conflict when two different host backends are installed', () => {
389
+ installFileSystemHostBackend(fakeBackend());
390
+ installFileSystemHostBackend(fakeBackend());
391
+ expect(explainFileSystemBackend().conflict).toBe(true);
392
+ });
393
+ });
394
+
363
395
  describe('fileExists', () => {
364
396
  it('reflects backend state', async () => {
365
397
  setFileSystemBackend(fakeBackend());
@@ -495,6 +527,25 @@ describe('getFileSystemUsage', () => {
495
527
  });
496
528
  });
497
529
 
530
+ describe('installFileSystemHostBackend', () => {
531
+ afterEach(() => resetFileSystemBackendForTest());
532
+
533
+ it('installs a host backend that getFileSystemBackend returns', () => {
534
+ const backend = fakeBackend();
535
+ installFileSystemHostBackend(backend);
536
+ expect(getFileSystemBackend()).toBe(backend);
537
+ });
538
+
539
+ it('is first-host-wins: a second different backend sets conflict', () => {
540
+ const first = fakeBackend();
541
+ const second = fakeBackend();
542
+ installFileSystemHostBackend(first);
543
+ installFileSystemHostBackend(second);
544
+ expect(getFileSystemBackend()).toBe(first);
545
+ expect(explainFileSystemBackend().conflict).toBe(true);
546
+ });
547
+ });
548
+
498
549
  describe('isAbsoluteFilePath', () => {
499
550
  it('returns true for Unix absolute paths', () => {
500
551
  expect(isAbsoluteFilePath('/foo/bar')).toBe(true);
@@ -554,6 +605,24 @@ describe('normalizeFilePath', () => {
554
605
  });
555
606
  });
556
607
 
608
+ describe('observeFileSystemHostResult', () => {
609
+ afterEach(() => resetFileSystemBackendForTest());
610
+
611
+ it('records a successful observation', () => {
612
+ installFileSystemHostBackend(fakeBackend());
613
+ observeFileSystemHostResult('readTextFile', true);
614
+ const explanation = explainFileSystemBackend();
615
+ expect(explanation.operation).toBe('readTextFile');
616
+ expect(explanation.viability).toBe('available');
617
+ });
618
+
619
+ it('records a failed observation', () => {
620
+ installFileSystemHostBackend(fakeBackend());
621
+ observeFileSystemHostResult('readTextFile', false);
622
+ expect(explainFileSystemBackend().viability).toBe('runtime-api-unavailable');
623
+ });
624
+ });
625
+
557
626
  describe('openFileReadStream', () => {
558
627
  it('returns a ReadableStream for existing binary files', async () => {
559
628
  const backend = fakeBackend();
@@ -781,6 +850,18 @@ describe('renameFile', () => {
781
850
  });
782
851
  });
783
852
 
853
+ describe('resetFileSystemBackendForTest', () => {
854
+ it('clears all backend slots', () => {
855
+ setFileSystemBackend(fakeBackend());
856
+ installFileSystemHostBackend(fakeBackend());
857
+ observeFileSystemHostResult('readTextFile', true);
858
+ resetFileSystemBackendForTest();
859
+ expect(explainFileSystemBackend().layer).toBe('host-not-enabled');
860
+ expect(explainFileSystemBackend().conflict).toBe(false);
861
+ expect(explainFileSystemBackend().viability).toBe('unobserved');
862
+ });
863
+ });
864
+
784
865
  describe('setFilePermissions', () => {
785
866
  it('delegates to the backend', async () => {
786
867
  setFileSystemBackend(fakeBackend());