feat(core): Add Bun and Deno runtime support, unify core loader, unix-socket support and cross-runtime streaming/tests
This commit is contained in:
@@ -1,71 +1,58 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as fs from 'node:fs';
|
||||
import { SmartRequest } from '../ts/index.js';
|
||||
|
||||
// Cross-platform tests using web-standard APIs only
|
||||
|
||||
tap.test('should send a buffer using buffer() method', async () => {
|
||||
const testBuffer = Buffer.from('Hello, World!');
|
||||
|
||||
|
||||
const smartRequest = SmartRequest.create()
|
||||
.url('https://httpbin.org/post')
|
||||
.buffer(testBuffer, 'text/plain')
|
||||
.method('POST');
|
||||
|
||||
|
||||
const response = await smartRequest.post();
|
||||
const data = await response.json();
|
||||
|
||||
|
||||
expect(data).toHaveProperty('data');
|
||||
expect(data.data).toEqual('Hello, World!');
|
||||
expect(data.headers['Content-Type']).toEqual('text/plain');
|
||||
});
|
||||
|
||||
tap.test('should send a stream using stream() method', async () => {
|
||||
// Create a simple readable stream
|
||||
const { Readable } = await import('stream');
|
||||
tap.test('should send a web ReadableStream using stream() method', async () => {
|
||||
const testData = 'Stream data test';
|
||||
const stream = Readable.from([testData]);
|
||||
|
||||
|
||||
// Use web-standard ReadableStream (works on all platforms)
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(new TextEncoder().encode(testData));
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
|
||||
const smartRequest = SmartRequest.create()
|
||||
.url('https://httpbin.org/post')
|
||||
.stream(stream, 'text/plain')
|
||||
.method('POST');
|
||||
|
||||
const response = await smartRequest.post();
|
||||
const data = await response.json();
|
||||
|
||||
expect(data).toHaveProperty('data');
|
||||
expect(data.data).toEqual(testData);
|
||||
});
|
||||
|
||||
tap.test('should handle raw streaming with custom function', async () => {
|
||||
const testData = 'Custom raw stream data';
|
||||
|
||||
const smartRequest = SmartRequest.create()
|
||||
.url('https://httpbin.org/post')
|
||||
.raw((request) => {
|
||||
// Custom streaming logic
|
||||
request.write(testData);
|
||||
request.end();
|
||||
})
|
||||
.method('POST');
|
||||
|
||||
const response = await smartRequest.post();
|
||||
const data = await response.json();
|
||||
|
||||
|
||||
expect(data).toHaveProperty('data');
|
||||
expect(data.data).toEqual(testData);
|
||||
});
|
||||
|
||||
tap.test('should send Uint8Array using buffer() method', async () => {
|
||||
const testData = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" in ASCII
|
||||
|
||||
|
||||
const smartRequest = SmartRequest.create()
|
||||
.url('https://httpbin.org/post')
|
||||
.buffer(testData, 'application/octet-stream')
|
||||
.method('POST');
|
||||
|
||||
|
||||
const response = await smartRequest.post();
|
||||
const data = await response.json();
|
||||
|
||||
|
||||
// Just verify that data was sent
|
||||
expect(data).toHaveProperty('data');
|
||||
expect(data.headers['Content-Type']).toEqual('application/octet-stream');
|
||||
101
test/test.unixsocket.bun.ts
Normal file
101
test/test.unixsocket.bun.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { SmartRequest } from '../ts/client/index.js';
|
||||
import { CoreRequest } from '../ts/core_bun/index.js';
|
||||
|
||||
// Check if Docker socket exists (common unix socket for testing)
|
||||
const dockerSocketPath = '/var/run/docker.sock';
|
||||
let dockerAvailable = false;
|
||||
|
||||
try {
|
||||
const file = Bun.file(dockerSocketPath);
|
||||
dockerAvailable = await file.exists();
|
||||
} catch (error) {
|
||||
console.log(
|
||||
'Docker socket not available - skipping unix socket tests. To enable, ensure Docker is running.',
|
||||
);
|
||||
}
|
||||
|
||||
tap.test('bun: should detect unix socket URLs correctly', async () => {
|
||||
expect(CoreRequest.isUnixSocket('unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('https://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://example.com')).toBeFalse();
|
||||
expect(CoreRequest.isUnixSocket('https://example.com')).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('bun: should parse unix socket URLs correctly', async () => {
|
||||
const result = CoreRequest.parseUnixSocketUrl('unix:/var/run/docker.sock:/v1.24/version');
|
||||
expect(result.socketPath).toEqual('unix:/var/run/docker.sock');
|
||||
expect(result.path).toEqual('/v1.24/version');
|
||||
});
|
||||
|
||||
if (dockerAvailable) {
|
||||
tap.test('bun: should connect to Docker via unix socket (unix: protocol)', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
console.log(`Docker version: ${body.Version}`);
|
||||
});
|
||||
|
||||
tap.test('bun: should connect to Docker via socketPath option', async () => {
|
||||
const response = await CoreRequest.create('http://localhost/version', {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
});
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
});
|
||||
|
||||
tap.test('bun: should connect to Docker via unix option', async () => {
|
||||
const response = await CoreRequest.create('http://localhost/version', {
|
||||
unix: '/var/run/docker.sock',
|
||||
});
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
});
|
||||
|
||||
tap.test('bun: should handle unix socket with query parameters', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true' })
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(Array.isArray(body)).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('bun: should handle unix socket with POST requests', async () => {
|
||||
// Test POST to Docker API (this specific endpoint may require permissions)
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true', limit: '1' })
|
||||
.get();
|
||||
|
||||
expect(response.status).toBeGreaterThanOrEqual(200);
|
||||
expect(response.status).toBeLessThan(500);
|
||||
|
||||
await response.text(); // Consume body
|
||||
});
|
||||
} else {
|
||||
tap.skip.test(
|
||||
'bun: unix socket tests skipped - Docker socket not available',
|
||||
);
|
||||
}
|
||||
|
||||
export default tap.start();
|
||||
154
test/test.unixsocket.deno.ts
Normal file
154
test/test.unixsocket.deno.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { SmartRequest } from '../ts/client/index.js';
|
||||
import { CoreRequest } from '../ts/core_deno/index.js';
|
||||
|
||||
// Check if Docker socket exists (common unix socket for testing)
|
||||
const dockerSocketPath = '/var/run/docker.sock';
|
||||
let dockerAvailable = false;
|
||||
|
||||
try {
|
||||
const fileInfo = await Deno.stat(dockerSocketPath);
|
||||
dockerAvailable = fileInfo.isFile || fileInfo.isSymlink;
|
||||
} catch (error) {
|
||||
console.log(
|
||||
'Docker socket not available - skipping unix socket tests. To enable, ensure Docker is running.',
|
||||
);
|
||||
}
|
||||
|
||||
tap.test('deno: should detect unix socket URLs correctly', async () => {
|
||||
expect(CoreRequest.isUnixSocket('unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('https://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://example.com')).toBeFalse();
|
||||
expect(CoreRequest.isUnixSocket('https://example.com')).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('deno: should parse unix socket URLs correctly', async () => {
|
||||
const result = CoreRequest.parseUnixSocketUrl('unix:/var/run/docker.sock:/v1.24/version');
|
||||
expect(result.socketPath).toEqual('unix:/var/run/docker.sock');
|
||||
expect(result.path).toEqual('/v1.24/version');
|
||||
});
|
||||
|
||||
if (dockerAvailable) {
|
||||
tap.test('deno: should connect to Docker via unix socket (unix: protocol)', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
console.log(`Docker version: ${body.Version}`);
|
||||
});
|
||||
|
||||
tap.test('deno: should connect to Docker via socketPath option', async () => {
|
||||
const response = await CoreRequest.create('http://localhost/version', {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
});
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
});
|
||||
|
||||
tap.test('deno: should connect to Docker via HttpClient', async () => {
|
||||
const client = Deno.createHttpClient({
|
||||
proxy: {
|
||||
url: 'unix:///var/run/docker.sock',
|
||||
},
|
||||
});
|
||||
|
||||
const response = await CoreRequest.create('http://localhost/version', {
|
||||
client,
|
||||
});
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
|
||||
// Clean up client
|
||||
client.close();
|
||||
});
|
||||
|
||||
tap.test('deno: should handle unix socket with query parameters', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true' })
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(Array.isArray(body)).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('deno: should handle unix socket with POST requests', async () => {
|
||||
// Test POST to Docker API (this specific endpoint may require permissions)
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true', limit: '1' })
|
||||
.get();
|
||||
|
||||
expect(response.status).toBeGreaterThanOrEqual(200);
|
||||
expect(response.status).toBeLessThan(500);
|
||||
|
||||
await response.text(); // Consume body
|
||||
});
|
||||
|
||||
tap.test('deno: should cache HttpClient for reuse', async () => {
|
||||
// First request creates a client
|
||||
const response1 = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response1.ok).toBeTrue();
|
||||
await response1.text();
|
||||
|
||||
// Second request should reuse the cached client
|
||||
const response2 = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response2.ok).toBeTrue();
|
||||
await response2.text();
|
||||
|
||||
// Clean up cache
|
||||
CoreRequest.clearClientCache();
|
||||
});
|
||||
|
||||
tap.test('deno: should clear HttpClient cache', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
await response.text();
|
||||
|
||||
// Clear cache - should not throw
|
||||
CoreRequest.clearClientCache();
|
||||
|
||||
// Subsequent request should create new client
|
||||
const response2 = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response2.ok).toBeTrue();
|
||||
await response2.text();
|
||||
|
||||
// Clean up
|
||||
CoreRequest.clearClientCache();
|
||||
});
|
||||
} else {
|
||||
tap.skip.test(
|
||||
'deno: unix socket tests skipped - Docker socket not available',
|
||||
);
|
||||
}
|
||||
|
||||
export default tap.start();
|
||||
90
test/test.unixsocket.node.ts
Normal file
90
test/test.unixsocket.node.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as plugins from '../ts/core_node/plugins.js';
|
||||
import { SmartRequest } from '../ts/client/index.js';
|
||||
import { CoreRequest } from '../ts/core_node/index.js';
|
||||
|
||||
// Check if Docker socket exists (common unix socket for testing)
|
||||
const dockerSocketPath = '/var/run/docker.sock';
|
||||
let dockerAvailable = false;
|
||||
|
||||
try {
|
||||
await plugins.fs.promises.access(dockerSocketPath, plugins.fs.constants.R_OK);
|
||||
dockerAvailable = true;
|
||||
} catch (error) {
|
||||
console.log(
|
||||
'Docker socket not available - skipping unix socket tests. To enable, ensure Docker is running.',
|
||||
);
|
||||
}
|
||||
|
||||
tap.test('node: should detect unix socket URLs correctly', async () => {
|
||||
expect(CoreRequest.isUnixSocket('unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('https://unix:/var/run/docker.sock:/version')).toBeTrue();
|
||||
expect(CoreRequest.isUnixSocket('http://example.com')).toBeFalse();
|
||||
expect(CoreRequest.isUnixSocket('https://example.com')).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('node: should parse unix socket URLs correctly', async () => {
|
||||
const result = CoreRequest.parseUnixSocketUrl('unix:/var/run/docker.sock:/v1.24/version');
|
||||
expect(result.socketPath).toEqual('unix:/var/run/docker.sock');
|
||||
expect(result.path).toEqual('/v1.24/version');
|
||||
});
|
||||
|
||||
if (dockerAvailable) {
|
||||
tap.test('node: should connect to Docker via unix socket (unix: protocol)', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/version')
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
console.log(`Docker version: ${body.Version}`);
|
||||
});
|
||||
|
||||
tap.test('node: should connect to Docker via socketPath option', async () => {
|
||||
const response = await CoreRequest.create('http://localhost/version', {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
});
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(body).toHaveProperty('Version');
|
||||
});
|
||||
|
||||
tap.test('node: should handle unix socket with query parameters', async () => {
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true' })
|
||||
.get();
|
||||
|
||||
expect(response.ok).toBeTrue();
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
const body = await response.json();
|
||||
expect(Array.isArray(body)).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('node: should handle unix socket with POST requests', async () => {
|
||||
// Test POST to Docker API (this specific endpoint may require permissions)
|
||||
const response = await SmartRequest.create()
|
||||
.url('http://unix:/var/run/docker.sock:/containers/json')
|
||||
.query({ all: 'true', limit: '1' })
|
||||
.get();
|
||||
|
||||
expect(response.status).toBeGreaterThanOrEqual(200);
|
||||
expect(response.status).toBeLessThan(500);
|
||||
|
||||
await response.text(); // Consume body
|
||||
});
|
||||
} else {
|
||||
tap.skip.test(
|
||||
'node: unix socket tests skipped - Docker socket not available',
|
||||
);
|
||||
}
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user