feat(tapbundle_serverside): add network port discovery utilities and migrate file I/O to smartfs; refactor runtimes to use Node fs and SmartFs, update server APIs and bump dependencies

This commit is contained in:
2026-03-03 20:15:59 +00:00
parent 4d1896bdf9
commit f23c902658
24 changed files with 2562 additions and 2094 deletions
+55
View File
@@ -0,0 +1,55 @@
import { tap, expect } from '../../ts_tapbundle/index.js';
import { tapNodeTools } from '../../ts_tapbundle_serverside/index.js';
tap.test('should find a single free port', async () => {
const port = await tapNodeTools.findFreePort();
expect(port).toBeTypeOf('number');
expect(port).toBeGreaterThanOrEqual(3000);
expect(port).toBeLessThanOrEqual(60000);
});
tap.test('should find a free port in a specific range', async () => {
const port = await tapNodeTools.findFreePort({
startPort: 8000,
endPort: 9000,
});
expect(port).toBeGreaterThanOrEqual(8000);
expect(port).toBeLessThanOrEqual(9000);
});
tap.test('should find a free port with exclusions', async () => {
const port = await tapNodeTools.findFreePort({
startPort: 10000,
endPort: 10100,
exclude: [10000, 10001, 10002],
});
expect(port).toBeGreaterThanOrEqual(10000);
expect(port).toBeLessThanOrEqual(10100);
expect(port).not.toEqual(10000);
expect(port).not.toEqual(10001);
expect(port).not.toEqual(10002);
});
tap.test('should find multiple free ports', async () => {
const ports = await tapNodeTools.findFreePorts(3);
expect(ports).toHaveLength(3);
// All ports should be distinct
const uniquePorts = new Set(ports);
expect(uniquePorts.size).toEqual(3);
for (const port of ports) {
expect(port).toBeGreaterThanOrEqual(3000);
expect(port).toBeLessThanOrEqual(60000);
}
});
tap.test('should find a consecutive port range', async () => {
const ports = await tapNodeTools.findFreePortRange(3, {
startPort: 20000,
endPort: 30000,
});
expect(ports).toHaveLength(3);
expect(ports[1]).toEqual(ports[0] + 1);
expect(ports[2]).toEqual(ports[0] + 2);
});
tap.start();
+14 -11
View File
@@ -37,10 +37,11 @@ tap.test('Migration - generateReport works', async () => {
tap.test('Migration - detects legacy files when they exist', async () => {
// Create a temporary legacy test file
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration');
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
try { await plugins.smartfsInstance.directory(tempDir).recursive().delete(); } catch (e) { /* may not exist */ }
await plugins.smartfsInstance.directory(tempDir).recursive().create();
const legacyFile = plugins.path.join(tempDir, 'test.browser.ts');
await plugins.smartfile.memory.toFs('// Legacy test file\nexport default Promise.resolve();', legacyFile);
await plugins.smartfsInstance.file(legacyFile).write('// Legacy test file\nexport default Promise.resolve();');
const migration = new Migration({
baseDir: tempDir,
@@ -53,18 +54,19 @@ tap.test('Migration - detects legacy files when they exist', async () => {
expect(legacyFiles[0]).toContain('test.browser.ts');
// Clean up
await plugins.smartfile.fs.removeSync(tempDir);
plugins.fs.rmSync(tempDir, { recursive: true, force: true });
});
tap.test('Migration - detects both legacy pattern', async () => {
// Create temporary legacy files
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration_both');
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
try { await plugins.smartfsInstance.directory(tempDir).recursive().delete(); } catch (e) { /* may not exist */ }
await plugins.smartfsInstance.directory(tempDir).recursive().create();
const browserFile = plugins.path.join(tempDir, 'test.browser.ts');
const bothFile = plugins.path.join(tempDir, 'test.both.ts');
await plugins.smartfile.memory.toFs('// Browser test\nexport default Promise.resolve();', browserFile);
await plugins.smartfile.memory.toFs('// Both test\nexport default Promise.resolve();', bothFile);
await plugins.smartfsInstance.file(browserFile).write('// Browser test\nexport default Promise.resolve();');
await plugins.smartfsInstance.file(bothFile).write('// Both test\nexport default Promise.resolve();');
const migration = new Migration({
baseDir: tempDir,
@@ -76,16 +78,17 @@ tap.test('Migration - detects both legacy pattern', async () => {
expect(legacyFiles.length).toEqual(2);
// Clean up
await plugins.smartfile.fs.removeSync(tempDir);
plugins.fs.rmSync(tempDir, { recursive: true, force: true });
});
tap.test('Migration - dry run does not modify files', async () => {
// Create a temporary legacy test file
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration_dryrun');
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
try { await plugins.smartfsInstance.directory(tempDir).recursive().delete(); } catch (e) { /* may not exist */ }
await plugins.smartfsInstance.directory(tempDir).recursive().create();
const legacyFile = plugins.path.join(tempDir, 'test.browser.ts');
await plugins.smartfile.memory.toFs('// Legacy test file\nexport default Promise.resolve();', legacyFile);
await plugins.smartfsInstance.file(legacyFile).write('// Legacy test file\nexport default Promise.resolve();');
const migration = new Migration({
baseDir: tempDir,
@@ -101,11 +104,11 @@ tap.test('Migration - dry run does not modify files', async () => {
expect(summary.migratedCount).toEqual(1); // Dry run still counts as "would migrate"
// Verify original file still exists
const fileExists = await plugins.smartfile.fs.fileExists(legacyFile);
const fileExists = await plugins.smartfsInstance.file(legacyFile).exists();
expect(fileExists).toEqual(true);
// Clean up
await plugins.smartfile.fs.removeSync(tempDir);
plugins.fs.rmSync(tempDir, { recursive: true, force: true });
});
export default tap.start();