Created
August 30, 2023 09:16
-
-
Save jeriko/11d2432bde653e9549ec6dc03cd326cd to your computer and use it in GitHub Desktop.
recombinary web
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (typeof variableName == 'undefined') { | |
const process = { env: {} } | |
// the browser complained about "process" not existing in readable package | |
} | |
import axios from 'axios' | |
import qs from 'qs'; | |
let tokenCache; | |
async function getToken() { | |
console.log('get token') | |
// TODO this should handle refresh tokens somehow too idk | |
if (process.env.RECOMBINARY_TOKEN) { | |
return process.env.RECOMBINARY_TOKEN | |
} | |
if (!process.env.RECOMBINARY_CLIENT_ID || !process.env.RECOMBINARY_CLIENT_SECRET) { | |
throw ('Please set either RECOMBINARY_TOKEN or both RECOMBINARY_CLIENT_ID and RECOMBINARY_CLIENT_SECRET. Sign up at https://platform.recombinary.com :)') | |
} | |
const url = 'https://recombinary.eu.auth0.com/oauth/token'; | |
let currentTime = Math.floor(Date.now() / 1000) | |
let oneHourFromNow = currentTime + (60 * 60) | |
if (tokenCache && tokenCache.expires_at > oneHourFromNow) { | |
return tokenCache.access_token | |
} | |
const data = { | |
client_id: process.env.RECOMBINARY_CLIENT_ID, | |
client_secret: process.env.RECOMBINARY_CLIENT_SECRET, | |
audience: 'https://api.recombinary.com', | |
grant_type: 'client_credentials', | |
}; | |
try { | |
const response = await axios.post(url, data, { | |
headers: { 'Content-Type': 'application/json' }, | |
}); | |
if (response.data && response.data.access_token) { | |
tokenCache = response.data | |
tokenCache.expires_at = currentTime + tokenCache.expires_in | |
return response.data.access_token; | |
} else { | |
throw new Error('No access token found in the response'); | |
} | |
} catch (error) { | |
tokenCache = null | |
console.error(`Error fetching API key: ${error.message}`); | |
throw error; | |
} | |
} | |
class API { | |
constructor(domain, token = null) { | |
this.domain = domain; | |
this.token = token | |
} | |
auth(token) { | |
this.token = token | |
} | |
async getHeaders() { | |
let token = this.token || await getToken() | |
return { Authorization: `Bearer ${token}` }; | |
} | |
url(path = '') { | |
return `https://${this.domain}/${path}`; | |
} | |
async get(path = '', queryParams = {}) { | |
let headers = await this.getHeaders(); | |
let query = qs.stringify(queryParams); | |
let url = this.url(path) + (query ? `?${query}` : ''); | |
let { data, status } = await axios.get(url, { headers }); | |
if (status >= 400) { throw new Error(data); } | |
return data; | |
} | |
async sendRequest(method, path, payload, responseType = null) { | |
if (typeof path === 'object') { | |
payload = path; | |
path = ''; | |
} | |
let options = { headers: await this.getHeaders() } | |
if (responseType) { | |
options['responseType'] = responseType; | |
} | |
if (responseType) options['responseType'] = responseType | |
return axios({ | |
method, | |
url: this.url(path), | |
data: payload, | |
...options | |
}); | |
} | |
async post(path, payload, responseType = null) { | |
let { data, status } = await this.sendRequest('POST', path, payload, responseType); | |
if (status >= 400) { throw new Error(data); } // TODO rather throw the content of the response.data? | |
return data; | |
} | |
async stream(path, payload) { | |
if (typeof path === 'object') { | |
payload = path; | |
path = ''; | |
} | |
const url = this.url(path) + `?stream=true`; | |
console.log(url) | |
console.log(payload) | |
let options = { headers: await this.getHeaders() } | |
options.headers['Content-Type'] = 'application/json' | |
console.log(options) | |
// Create an EventTarget-like object to allow registration of event listeners | |
const eventTarget = new EventTarget(); | |
const response = await fetch(url, { | |
method: 'POST', | |
...options, | |
body: JSON.stringify(payload) | |
}); | |
const reader = await response.body.getReader(); | |
const stream = new ReadableStream({ | |
async start(controller) { | |
while (true) { | |
const { done, value } = await reader.read(); | |
if (done) { | |
eventTarget.dispatchEvent(new Event('end')); | |
controller.close(); | |
return; | |
} | |
eventTarget.dispatchEvent(new MessageEvent('data', { data: new TextDecoder().decode(value) })); | |
controller.enqueue(value); | |
} | |
} | |
}); | |
return { | |
on: (eventName, callback) => eventTarget.addEventListener(eventName, callback), | |
off: (eventName, callback) => eventTarget.removeEventListener(eventName, callback) | |
}; | |
} | |
} | |
function connect(domain, token) { | |
const api = new API(domain, token); | |
const callableInstance = async function(...args) { | |
if (args.length === 0) { | |
return api.get(); | |
} | |
if (typeof args[0] === 'string' && args.length === 1) { | |
return api.get(args[0]); | |
} | |
if (typeof args[0] === 'object') { | |
return api.post(args[0]); | |
} | |
if (typeof args[0] === 'string' && typeof args[1] === 'object') { | |
return api.post(args[0], args[1]); | |
} | |
throw new Error("Invalid arguments"); | |
} | |
callableInstance.get = api.get.bind(api); | |
callableInstance.post = api.post.bind(api); | |
callableInstance.stream = api.stream.bind(api); | |
return callableInstance; | |
} | |
const cpu = connect('cpu.recombinary.com') | |
const drive = connect('drive.recombinary.com') | |
const wallet = connect('wallet.recombinary.com') | |
const io = connect('io.recombinary.com') | |
async function encode(fileBuffer, mimeType = 'audio/mpeg') { | |
const bytes = new Uint8Array(fileBuffer); | |
let binary = ''; | |
for (let i = 0; i < bytes.byteLength; i++) { | |
binary += String.fromCharCode(bytes[i]); | |
} | |
const base64 = window.btoa(binary); | |
return `data:${mimeType};base64,${base64}`; | |
} | |
export { API, connect, encode, cpu, drive, wallet, io }; | |
const recombinary = { API, connect, encode, cpu, drive, wallet, io } | |
export default recombinary; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment