Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/crud/__tests__/matryoshka.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { fromStream } from '@jsonjoy.com/util/lib/streams/fromStream';
import { bufferToUint8Array } from '@jsonjoy.com/util/lib/buffers/bufferToUint8Array';
import { memfs } from '../..';
import { onlyOnNode20 } from '../../__tests__/util';
import { NodeFileSystemDirectoryHandle } from '../../node-to-fsa';
Expand All @@ -6,6 +8,11 @@ import { NodeCrud } from '../../node-to-crud';
import { testCrudfs } from '../../crud/__tests__/testCrudfs';
import { FsaCrud } from '../../fsa-to-crud';

const b = (str: string) => {
const buf = Buffer.from(str);
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
};

onlyOnNode20('CRUD matryoshka', () => {
describe('crud(memfs)', () => {
testCrudfs(() => {
Expand Down Expand Up @@ -54,6 +61,17 @@ onlyOnNode20('CRUD matryoshka', () => {
expect(await fs2.promises.readFile('/file3.txt', 'utf8')).toBe('a.c');
});

test('can read as stream', async () => {
const { fs } = memfs();
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });
const fs2 = new FsaNodeFs(fsa);
await fs2.promises.writeFile('/foo', 'bar');
const handle = await fs2.promises.open('/foo', 'r+');
const stream = handle.readableWebStream();
const blob = bufferToUint8Array((await fromStream(stream)) as any);
expect(blob).toStrictEqual(b('bar'));
});

testCrudfs(() => {
const { fs } = memfs();
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });
Expand Down
27 changes: 27 additions & 0 deletions src/crud/__tests__/testCrudfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ export const testCrudfs = (setup: Setup) => {
});
});

test('truncates overwritten resource', async () => {
const { crud, snapshot } = setup();
await crud.put(['a', 'b'], 'bar', b('abc'));
await crud.put(['a', 'b'], 'bar', b('.'));
expect(snapshot()).toStrictEqual({
'/a/b/bar': '.',
});
});

test('can overwrite with empty file', async () => {
const { crud, snapshot } = setup();
await crud.put(['a', 'b'], 'bar', b('abc'));
await crud.put(['a', 'b'], 'bar', b(''));
expect(snapshot()).toStrictEqual({
'/a/b/bar': '',
});
});

test('overwrites existing data', async () => {
const { crud, snapshot } = setup();
await crud.put(['a', 'b'], 'bar', b('abc'));
await crud.put(['a', 'b'], 'bar', b('.'));
expect(snapshot()).toStrictEqual({
'/a/b/bar': '.',
});
});

test('can choose to throw if item already exists', async () => {
const { crud } = setup();
await crud.put(['a', 'b'], 'bar', b('abc'), { throwIf: 'exists' });
Expand Down
7 changes: 6 additions & 1 deletion src/fsa-to-node/FsaNodeFs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,12 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono
const openFile = await this.getFileByFd(fd, 'read');
const file = await openFile.file.getFile();
const src = await file.arrayBuffer();
const slice = new Uint8Array(src, Number(position), Number(length));
position = Number(position);
length = Number(length);
const slice =
position > src.byteLength
? new Uint8Array(0)
: new Uint8Array(src, position, Math.min(length, src.byteLength - position));
const dest = new Uint8Array(buffer.buffer, buffer.byteOffset + offset, slice.length);
dest.set(slice, 0);
return slice.length;
Expand Down
Loading