From 044ba53760ca8d962f39bc35d294c51d5031a7c8 Mon Sep 17 00:00:00 2001 From: Wolfgang Rathgeb Date: Wed, 27 Mar 2024 13:51:30 +0100 Subject: [PATCH] Add function to write Buffer/String/JSON (#12) * Add function to write Buffer/String/JSON * test plugin and json functions * test error handling for missing plugins or file extension --- packages/core/src/core/file.spec.ts | 103 +++++++++++++++++++++++++++- packages/core/src/core/file.ts | 26 +++++++ packages/core/src/definitions.ts | 2 +- 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/packages/core/src/core/file.spec.ts b/packages/core/src/core/file.spec.ts index 7f146eb..dafadf0 100644 --- a/packages/core/src/core/file.spec.ts +++ b/packages/core/src/core/file.spec.ts @@ -5,7 +5,7 @@ import { InMemoryAdapterHelper } from '@loom-io/test-utils'; import { basename, dirname } from 'node:path'; import { Directory } from './dir.js'; -import { FILE_SIZE_UNIT, SourceAdapter } from '../definitions.js'; +import { FILE_SIZE_UNIT, LoomFileConverter, PLUGIN_TYPE, SourceAdapter } from '../definitions.js'; import { faker } from '@faker-js/faker'; import { Editor } from './editor.js'; @@ -139,9 +139,110 @@ describe('Test File Service', () => { expect(content.toString()).toBe(testContent); }); + test('Write file', async () => { + const testContent = '1234k2hk3jh1fasdasfc%'; + const testFile = await testHelper.createFile(undefined, testContent); + + const file = LoomFile.from( adapter, testFile); + const newContent = 'new content'; + await file.write(newContent); + const content = await file.text(); + expect(content).toBe(newContent); + }); + + test('Create file', async () => { + const testFile = await testHelper.createFile(undefined, 'test'); + const file = LoomFile.from( adapter, testFile); + await file.create(); + expect(await file.exists()).toBeTruthy(); + }); + + test('Delete file', async () => { + const testFile = await testHelper.createFile(undefined, 'test'); + const file = LoomFile.from( adapter, testFile); + await file.delete(); + expect(await file.exists()).toBeFalsy(); + }); + + + + }); + + + describe('File Plugin Tests', () => { + + afterEach(() => { + FileTest.emptyPlugins(); + }); + + test('Register a plugin', async () => { + const testContent = '1234k2hk3jh1fasdasfc%'; + const testFile = await testHelper.createFile(undefined, testContent); + + const file = LoomFile.from( adapter, testFile); + const plugin: LoomFileConverter = { + $type: PLUGIN_TYPE.FILE_CONVERTER, + extensions: ['test'], + parse: (text: string) => JSON.parse(text) as T, + stringify: (content: unknown) => JSON.stringify(content) + }; + LoomFile.register(plugin); + const content = await file.text(); + expect(content).toBe(testContent); + }); + + test('Read file with json plugin', async () => { + const testContent = {test: true}; + const testFile = await testHelper.createFile(faker.system.commonFileName('json'), JSON.stringify(testContent)); + + const file = LoomFile.from( adapter, testFile); + const plugin: LoomFileConverter = { + $type: PLUGIN_TYPE.FILE_CONVERTER, + extensions: ['json'], + parse: (text: string) => JSON.parse(text) as T, + stringify: (content: unknown) => JSON.stringify(content) + }; + LoomFile.register(plugin); + const content = await file.json(); + expect(content).toStrictEqual(testContent); + }); + + test('Write file with json plugin', async () => { + const testContent = {test: true}; + const testFile = await testHelper.createFile(faker.system.commonFileName('json'), JSON.stringify(testContent)); + + const file = LoomFile.from( adapter, testFile); + const plugin: LoomFileConverter = { + $type: PLUGIN_TYPE.FILE_CONVERTER, + extensions: ['json'], + parse: (text: string) => JSON.parse(text) as T, + stringify: (content: unknown) => JSON.stringify(content) + }; + LoomFile.register(plugin); + await file.stringify(testContent); + const content = await file.text(); + expect(content).toBe(JSON.stringify(testContent)); + }); + test('No plugin for file', async () => { + const testContent = {test: true}; + const testFile = await testHelper.createFile(faker.system.commonFileName('json'), JSON.stringify(testContent)); + const file = LoomFile.from( adapter, testFile); + await expect(file.json()).rejects.toThrow(PluginNotFoundException); + await expect(file.stringify(testContent)).rejects.toThrow(PluginNotFoundException); + }); + + test('No extension for file', async () => { + const testContent = {test: true}; + const testFile = await testHelper.createFile(faker.system.directoryPath(), JSON.stringify(testContent)); + + const file = LoomFile.from( adapter, testFile); + await expect(file.json()).rejects.toThrow(FileConvertException); + await expect(file.stringify(testContent)).rejects.toThrow(FileConvertException); + }); }); + }); diff --git a/packages/core/src/core/file.ts b/packages/core/src/core/file.ts index 25b6821..157965b 100644 --- a/packages/core/src/core/file.ts +++ b/packages/core/src/core/file.ts @@ -84,6 +84,10 @@ export class LoomFile { } + async delete() { + await this._adapter.deleteFile(this.path); + } + async exists() { const fullPath = joinPath(this.dir.path, this.name); return this._adapter.fileExists(fullPath); @@ -101,6 +105,28 @@ export class LoomFile { return await this._adapter.readFile(this.path, encoding); } + async write(data: string | Buffer) { + await this._adapter.writeFile(this.path, data); + } + + async create() { + await this._adapter.writeFile(this.path, Buffer.alloc(0)); + } + + async stringify(content: T) { + if(this.extension === undefined) { + throw new FileConvertException(this.path, 'File has no extension'); + } + + const plugin = LoomFile.converterPlugins.get(this.extension); + + if(plugin === undefined) { + throw new PluginNotFoundException(this.path); + } + + return plugin.stringify(content); + } + static register(plugin: LoomFileConverter) { if(plugin.$type === PLUGIN_TYPE.FILE_CONVERTER) { plugin.extensions.forEach(ext => { diff --git a/packages/core/src/definitions.ts b/packages/core/src/definitions.ts index 80573e2..eb9518d 100644 --- a/packages/core/src/definitions.ts +++ b/packages/core/src/definitions.ts @@ -72,7 +72,7 @@ export interface SourceAdapter { readFile(path: string): MaybePromise readFile(path: string, encoding: BufferEncoding): MaybePromise readFile(path: string, encoding?: BufferEncoding): MaybePromise - writeFile(path: string, content: string): MaybePromise + writeFile(path: string, content: string | Buffer): MaybePromise deleteFile(path: string): MaybePromise openFile(path: string): MaybePromise stat(path: string): MaybePromise