BREAKING CHANGE(SmartFileFactory): Refactor to in-memory file API and introduce SmartFileFactory; delegate filesystem operations to @push.rocks/smartfs; bump to 12.0.0

This commit is contained in:
2025-11-22 13:18:32 +00:00
parent 16d47ea348
commit ad33cb6d73
24 changed files with 1552 additions and 1789 deletions

View File

@@ -1,18 +1,23 @@
import * as path from 'path';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as smartfile from '../ts/index.js'; // adjust the import path as needed
import * as smartfile from '../ts/index.js';
import { MockSmartFs } from './helpers/mock-smartfs.js';
// Create factory with MockSmartFs
const mockFs = new MockSmartFs();
const factory = new smartfile.SmartFileFactory(mockFs);
// Test assets path
const testAssetsPath = './test/testassets/';
// ---------------------------
// StreamFile tests
// StreamFile Factory Tests
// ---------------------------
tap.test(
'StreamFile.fromPath should create a StreamFile from a file path',
'SmartFileFactory.streamFromPath() -> should create a StreamFile from a file path',
async () => {
const streamFile = await smartfile.StreamFile.fromPath(
const streamFile = await factory.streamFromPath(
path.join(testAssetsPath, 'mytest.json'),
);
expect(streamFile).toBeInstanceOf(smartfile.StreamFile);
@@ -22,75 +27,128 @@ tap.test(
);
tap.test(
'StreamFile.fromUrl should create a StreamFile from a URL',
async () => {
const streamFile = await smartfile.StreamFile.fromUrl(
'http://example.com/somefile.json',
);
expect(streamFile).toBeInstanceOf(smartfile.StreamFile);
},
);
tap.test(
'StreamFile.fromBuffer should create a StreamFile from a Buffer',
'SmartFileFactory.streamFromBuffer() -> should create a StreamFile from a Buffer',
async () => {
const buffer = Buffer.from('Some content');
const streamFile = smartfile.StreamFile.fromBuffer(
const streamFile = factory.streamFromBuffer(
buffer,
'bufferfile.txt',
);
expect(streamFile).toBeInstanceOf(smartfile.StreamFile);
const content = await streamFile.getContentAsBuffer();
expect(content.toString()).toEqual('Some content');
},
);
tap.test('StreamFile should write the stream to disk', async () => {
const streamFile = await smartfile.StreamFile.fromPath(
tap.test(
'SmartFileFactory.streamFromStream() -> should create a StreamFile from a stream',
async () => {
const { Readable } = await import('stream');
const stream = new Readable();
stream.push('stream content');
stream.push(null);
const streamFile = factory.streamFromStream(stream, 'streamfile.txt', false);
expect(streamFile).toBeInstanceOf(smartfile.StreamFile);
},
);
// ---------------------------
// StreamFile Instance Tests
// ---------------------------
tap.test('StreamFile -> should write the stream to disk', async () => {
const streamFile = await factory.streamFromPath(
path.join(testAssetsPath, 'mytest.json'),
);
await streamFile.writeToDisk(
path.join(testAssetsPath, 'temp', 'mytest.json'),
);
// Verify the file was written
expect(
// We'll use the fileExists method from your smartfile library
// Replace with the actual method you use to check file existence
await smartfile.fs.fileExists(
path.join(testAssetsPath, 'temp', 'mytest.json'),
),
).toBeTrue();
const targetPath = path.join(testAssetsPath, 'temp', 'stream-mytest.json');
await streamFile.writeToDisk(targetPath);
// Verify the file was written by reading it back
const verifyFile = await factory.fromFilePath(targetPath);
expect(verifyFile.contentBuffer).toBeInstanceOf(Buffer);
});
tap.test('StreamFile should write to a directory', async () => {
const streamFile = await smartfile.StreamFile.fromPath(
tap.test('StreamFile -> should write to a directory', async () => {
const streamFile = await factory.streamFromPath(
path.join(testAssetsPath, 'mytest.json'),
);
// Set relative path so writeToDir knows where to put it
streamFile.relativeFilePath = 'mytest-fromdir.json';
await streamFile.writeToDir(path.join(testAssetsPath, 'temp'));
// Verify the file was written
expect(
await smartfile.fs.fileExists(
path.join(testAssetsPath, 'temp', 'mytest.json'),
),
).toBeTrue();
const targetPath = path.join(testAssetsPath, 'temp', 'mytest-fromdir.json');
const verifyFile = await factory.fromFilePath(targetPath);
expect(verifyFile.contentBuffer).toBeInstanceOf(Buffer);
});
tap.test('StreamFile should return content as a buffer', async () => {
const streamFile = await smartfile.StreamFile.fromPath(
tap.test('StreamFile -> should return content as a buffer', async () => {
const streamFile = await factory.streamFromPath(
path.join(testAssetsPath, 'mytest.json'),
);
const contentBuffer = await streamFile.getContentAsBuffer();
expect(contentBuffer).toBeInstanceOf(Buffer);
// Further checks on the content can be added here if necessary
});
tap.test('StreamFile should return content as a string', async () => {
const streamFile = await smartfile.StreamFile.fromPath(
tap.test('StreamFile -> should return content as a string', async () => {
const streamFile = await factory.streamFromPath(
path.join(testAssetsPath, 'mytest.json'),
);
const contentString = await streamFile.getContentAsString();
expect(contentString).toBeTypeofString();
// Verify the content matches what's expected
// This assumes the file contains a JSON object with a key 'key1' with value 'this works'
expect(JSON.parse(contentString).key1).toEqual('this works');
const parsed = JSON.parse(contentString);
expect(parsed.key1).toEqual('this works');
});
tap.test('StreamFile -> should get size', async () => {
const buffer = Buffer.from('test content for size');
const streamFile = factory.streamFromBuffer(buffer, 'sizefile.txt');
const size = await streamFile.getSize();
expect(size).toEqual(buffer.length);
});
tap.test('StreamFile -> should handle multi-use streams', async () => {
const buffer = Buffer.from('multi-use content');
const streamFile = factory.streamFromBuffer(buffer, 'multiuse.txt');
streamFile.multiUse = true;
// Read multiple times
const content1 = await streamFile.getContentAsString();
const content2 = await streamFile.getContentAsString();
expect(content1).toEqual('multi-use content');
expect(content2).toEqual('multi-use content');
});
tap.test('StreamFile -> should convert to SmartFile', async () => {
const buffer = Buffer.from('convert to smartfile');
const streamFile = factory.streamFromBuffer(buffer, 'convert.txt');
const smartFile = await streamFile.toSmartFile();
expect(smartFile).toBeInstanceOf(smartfile.SmartFile);
expect(smartFile.parseContentAsString()).toEqual('convert to smartfile');
});
tap.test('StreamFile -> should create readable stream', async () => {
const buffer = Buffer.from('readable stream content');
const streamFile = factory.streamFromBuffer(buffer, 'readable.txt');
const stream = await streamFile.createReadStream();
expect(stream).toHaveProperty('pipe');
// Read from stream
const chunks: Buffer[] = [];
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
await new Promise((resolve) => {
stream.on('end', resolve);
});
const content = Buffer.concat(chunks).toString();
expect(content).toEqual('readable stream content');
});
// Start the test sequence