diff --git a/src/fsa-to-node/FsaNodeFs.ts b/src/fsa-to-node/FsaNodeFs.ts index d72962a53..0a02a66c1 100644 --- a/src/fsa-to-node/FsaNodeFs.ts +++ b/src/fsa-to-node/FsaNodeFs.ts @@ -251,11 +251,34 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects { throw new Error('Not implemented'); } - copyFile(src: misc.PathLike, dest: misc.PathLike, callback: misc.TCallback); - copyFile(src: misc.PathLike, dest: misc.PathLike, flags: misc.TFlagsCopy, callback: misc.TCallback); - copyFile(src: misc.PathLike, dest: misc.PathLike, a, b?) { - throw new Error('Not implemented'); - } + public readonly copyFile: FsCallbackApi['copyFile'] = (src: misc.PathLike, dest: misc.PathLike, a, b?): void => { + const srcFilename = pathToFilename(src); + const destFilename = pathToFilename(dest); + let flags: misc.TFlagsCopy; + let callback: misc.TCallback; + if (typeof a === 'function') { + flags = 0; + callback = a; + } else { + flags = a; + callback = b; + } + validateCallback(callback); + const [oldFolder, oldName] = pathToLocation(srcFilename); + const [newFolder, newName] = pathToLocation(destFilename); + (async () => { + const oldFile = await this.getFile(oldFolder, oldName, 'copyFile'); + const newDir = await this.getDir(newFolder, false, 'copyFile'); + const newFile = await newDir.getFileHandle(newName, { create: true }); + const writable = await newFile.createWritable({ keepExistingData: false }); + const oldData = await oldFile.getFile(); + await writable.write(await oldData.arrayBuffer()); + await writable.close(); + })().then( + () => callback(null), + error => callback(error), + ); + }; public readonly unlink: FsCallbackApi['unlink'] = (path: misc.PathLike, callback: misc.TCallback): void => { const filename = pathToFilename(path); diff --git a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts index d5be9f47f..295a45762 100644 --- a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts +++ b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts @@ -547,3 +547,16 @@ describe('.realpath()', () => { expect(path).toBe('/folder/file'); }); }); + +describe('.copyFile()', () => { + test('can copy a file', async () => { + const { fs, mfs } = setup({ folder: { file: 'test' }, 'empty-folder': null, 'f.html': 'test' }); + await fs.promises.copyFile('/folder/file', '/folder/file2'); + expect(mfs.__vol.toJSON()).toStrictEqual({ + '/mountpoint/folder/file': 'test', + '/mountpoint/folder/file2': 'test', + '/mountpoint/empty-folder': null, + '/mountpoint/f.html': 'test', + }); + }); +});