Skip to content

Commit

Permalink
feat: 🎸 implement sync write method
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 20, 2023
1 parent 6ab0edc commit 3017ecd
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/node-to-fsa/NodeFileSystemSyncAccessHandle.ts
Expand Up @@ -63,6 +63,31 @@ export class NodeFileSystemSyncAccessHandle {
public async truncate(newSize: number): Promise<void> {
this.fs.truncateSync(this.fd, newSize);
}

/**
* Writes the content of a specified buffer to the file associated with the
* handle, optionally at a given offset.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/write
* @param buffer
* @param options
*/
public async write(buffer: ArrayBuffer | ArrayBufferView | DataView, options: FileSystemReadWriteOptions = {}): Promise<number> {
const buf: Buffer | ArrayBufferView = buffer instanceof ArrayBuffer ? Buffer.from(buffer) : buffer;
try {
return this.fs.writeSync(this.fd, buf, 0, buffer.byteLength, options.at || 0);
} catch (error) {
if (error instanceof DOMException) throw error;
if (error && typeof error === 'object') {
switch (error.code) {
case 'EBADF': {
throw new DOMException('File handle already closed.', 'InvalidStateError');
}
}
}
throw error;
}
}
}

export interface FileSystemReadWriteOptions {
Expand Down
56 changes: 56 additions & 0 deletions src/node-to-fsa/__tests__/NodeFileSystemSyncAccessHandle.test.ts
Expand Up @@ -124,4 +124,60 @@ maybe('NodeFileSystemSyncAccessHandle', () => {
expect(res).toBe(undefined);
});
});

describe('.write()', () => {
test('can write to the file', async () => {
const { dir, fs } = setup({
'file.txt': '0123456789',
});
const entry = await dir.getFileHandle('file.txt');
const sync = await entry.createSyncAccessHandle!();
const res = await sync.write(Buffer.from('Hello'));
expect(res).toBe(5);
expect(fs.readFileSync('/file.txt', 'utf8')).toBe('Hello56789');
});

test('can write at an offset', async () => {
const { dir, fs } = setup({
'file.txt': '0123456789',
});
const entry = await dir.getFileHandle('file.txt');
const sync = await entry.createSyncAccessHandle!();
const res = await sync.write(Buffer.from('Hello'), {at: 7});
expect(res).toBe(5);
expect(fs.readFileSync('/file.txt', 'utf8')).toBe('0123456Hello');
});

test('throws "InvalidStateError" DOMException if file descriptor is already closed', async () => {
const { dir, fs } = setup({
'file.txt': '0123456789',
});
const entry = await dir.getFileHandle('file.txt');
const sync = await entry.createSyncAccessHandle!();
await sync.write(Buffer.from('a'));
await sync.close();
try {
await sync.write(Buffer.from('b'));
throw new Error('No error was thrown');
} catch (error) {
expect(error).toBeInstanceOf(DOMException);
expect(error.name).toBe('InvalidStateError');
}
});

// TODO: Need to find out what is the correct behavior here.
xtest('writing at offset past file size', async () => {
const { dir, fs } = setup({
'file.txt': '0123456789',
});
const entry = await dir.getFileHandle('file.txt');
const sync = await entry.createSyncAccessHandle!();
try {
await sync.write(Buffer.from('a'), {at: 100});
// ?
} catch (error) {
// ?
}
});
});
});

0 comments on commit 3017ecd

Please sign in to comment.