svector-sdk
Version:
Official JavaScript and TypeScript SDK for accessing SVECTOR APIs.
187 lines (186 loc) • 6.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.toFile = toFile;
exports.isNodeEnvironment = isNodeEnvironment;
exports.isBrowserEnvironment = isBrowserEnvironment;
exports.getDefaultFetch = getDefaultFetch;
exports.imageToBase64 = imageToBase64;
exports.detectImageMimeType = detectImageMimeType;
exports.isValidImageUrl = isValidImageUrl;
exports.isValidBase64Image = isValidBase64Image;
exports.createImageContent = createImageContent;
async function toFile(value, filename, options) {
if (value instanceof File) {
return value;
}
if (typeof Buffer !== 'undefined' && value instanceof Buffer) {
const uint8Array = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
const blob = new Blob([uint8Array], { type: options?.type || 'application/octet-stream' });
return new File([blob], filename || 'file', { type: blob.type });
}
if (value instanceof Uint8Array) {
const blob = new Blob([value], { type: options?.type || 'application/octet-stream' });
return new File([blob], filename || 'file', { type: blob.type });
}
if (value instanceof ArrayBuffer) {
const blob = new Blob([value], { type: options?.type || 'application/octet-stream' });
return new File([blob], filename || 'file', { type: blob.type });
}
if (typeof value === 'string') {
const blob = new Blob([value], { type: options?.type || 'text/plain' });
return new File([blob], filename || 'file.txt', { type: blob.type });
}
if (value && typeof value.getReader === 'function') {
try {
const chunks = [];
const reader = value.getReader();
try {
while (true) {
const { done, value: chunk } = await reader.read();
if (done)
break;
chunks.push(chunk);
}
}
finally {
reader.releaseLock();
}
const blob = new Blob(chunks, { type: options?.type || 'application/octet-stream' });
return new File([blob], filename || 'file', { type: blob.type });
}
catch (error) {
throw new Error(`Failed to read stream: ${error}`);
}
}
if (value && typeof value.arrayBuffer === 'function') {
const arrayBuffer = await value.arrayBuffer();
const blob = new Blob([arrayBuffer], {
type: options?.type || value.headers?.get('content-type') || 'application/octet-stream'
});
return new File([blob], filename || 'file', { type: blob.type });
}
throw new Error('Unsupported input type for toFile()');
}
function isNodeEnvironment() {
return typeof process !== 'undefined' &&
process.versions != null &&
process.versions.node != null;
}
function isBrowserEnvironment() {
return typeof window !== 'undefined' && typeof window.document !== 'undefined';
}
function getDefaultFetch() {
if (typeof globalThis !== 'undefined' && globalThis.fetch) {
return globalThis.fetch;
}
if (typeof window !== 'undefined' && window.fetch) {
return window.fetch;
}
if (typeof global !== 'undefined' && global.fetch) {
return global.fetch;
}
if (isNodeEnvironment()) {
try {
const nodeFetch = require('node-fetch');
return nodeFetch.default || nodeFetch;
}
catch {
}
}
throw new Error('No fetch implementation found. Please provide a fetch function or install node-fetch for Node.js.');
}
async function imageToBase64(file) {
if (typeof Buffer !== 'undefined' && file instanceof Buffer) {
const mimeType = detectImageMimeType(file);
return `data:${mimeType};base64,${file.toString('base64')}`;
}
if (file instanceof Uint8Array) {
const mimeType = detectImageMimeType(file);
const base64 = Buffer.from(file).toString('base64');
return `data:${mimeType};base64,${base64}`;
}
if (file instanceof File) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
throw new Error('Unsupported file type for base64 conversion');
}
function detectImageMimeType(data) {
const bytes = data instanceof Buffer ? data : Buffer.from(data);
if (bytes.length >= 8 &&
bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4E && bytes[3] === 0x47) {
return 'image/png';
}
if (bytes.length >= 3 &&
bytes[0] === 0xFF && bytes[1] === 0xD8 && bytes[2] === 0xFF) {
return 'image/jpeg';
}
if (bytes.length >= 12 &&
bytes[0] === 0x52 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x46 &&
bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50) {
return 'image/webp';
}
if (bytes.length >= 6 &&
bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46) {
return 'image/gif';
}
return 'image/jpeg';
}
function isValidImageUrl(url) {
try {
const parsedUrl = new URL(url);
return ['http:', 'https:', 'data:', 'file:'].includes(parsedUrl.protocol);
}
catch {
return false;
}
}
function isValidBase64Image(base64) {
if (base64.startsWith('data:image/')) {
const base64Data = base64.split(',')[1];
return !!(base64Data && base64Data.length > 0);
}
try {
return btoa(atob(base64)) === base64;
}
catch {
return false;
}
}
function createImageContent(imageInput, text, detail) {
return new Promise(async (resolve, reject) => {
try {
const content = [];
if (text) {
content.push({ type: 'text', text });
}
if (typeof imageInput === 'string') {
if (isValidImageUrl(imageInput)) {
content.push({
type: 'image_url',
image_url: { url: imageInput, detail: detail || 'auto' }
});
}
else {
reject(new Error('Invalid image URL provided'));
return;
}
}
else {
const base64Url = await imageToBase64(imageInput);
content.push({
type: 'image_url',
image_url: { url: base64Url, detail: detail || 'auto' }
});
}
resolve(content);
}
catch (error) {
reject(error);
}
});
}