Skip to content

Instantly share code, notes, and snippets.

@carsonfarmer
Created February 21, 2019 17:22
Show Gist options
  • Save carsonfarmer/a26a0d01ae58ffa7b8cd2689e149406b to your computer and use it in GitHub Desktop.
Save carsonfarmer/a26a0d01ae58ffa7b8cd2689e149406b to your computer and use it in GitHub Desktop.
Working with Textile REST API from Javascript
/* eslint no-undef: "error" */
/* eslint-env browser */
import 'babel-polyfill'
import toposort from 'toposort'
import waterfall from 'async/waterfall'
const getThreadInfo = async (thread) => {
const threadId = thread || 'default'
return executeJsonCmd('GET', `${API}/threads/${threadId}`, { ctype: 'application/json' })
}
const addFile = async (file, opts, output) => {
if (!opts.schema) {
const info = await getThreadInfo(opts.thread)
opts.schema = info.schema
}
const payload = new FormData()
payload.append('file', file, file.name)
orderLinks(opts.schema.links)
const milled = await millNode(payload, opts.schema, output)
return executeJsonCmd('POST', `${API}/threads/${opts.thread}/files`,
{
opts: { caption: opts.caption },
payload: JSON.stringify([milled]),
ctype: 'application/json'
})
}
const executeJsonCmd = async (method, url, pars) => {
const headers = {}
if (pars.opts) {
const opts = Object.entries(pars.opts || {})
.map(a => `${a[0]}=${a[1]}`)
.join(',')
headers['X-Textile-Opts'] = opts
}
if (pars.ctype) {
headers['Content-Type'] = pars.ctype
}
if (pars.args) {
headers['X-Textile-Args'] = (pars.args || []).join(',')
}
const params = {
method: method,
headers: headers
}
if (pars.payload) {
params.body = pars.payload
}
try {
const fetched = await fetch(url, params)
return fetched.json()
} catch (err) {
throw err
}
}
var orderLinks = (links) => {
// Map of links and those links that depend on them
var G = Object
.entries(links)
.map(([name, link]) => [name, link.use])
return toposort(G).reverse()
}
const millNode = async (payload, node, output, name) => {
if (node.links) {
const sorted = orderLinks(node.links)
const links = node.links
const promises = sorted
.filter(name => name !== ':file')
.map((name, index) => {
if (index === 0) {
return async (cb) => {
const res = await millNode(payload, links[name], output, name)
const dir = {}
dir[name] = res
cb(null, dir)
}
}
return async (dir, cb) => {
let body = payload
if (!links[name].opts) {
links[name].opts = {}
}
// Check for top-level opts
links[name].opts.plaintext = links[name].plaintext
links[name].opts.pin = links[name].pin
if (links[name].use !== ':file') {
body = undefined
links[name].opts.use = dir[links[name].use].hash
}
const res = await millNode(body, links[name], output, name)
dir[name] = res
cb(null, dir)
}
})
return new Promise((resolve, reject) => {
waterfall(promises, (err, result) => {
if (err) {
reject(err)
} else {
resolve(result)
}
})
})
} else { // We're just processing a single file
const out = await executeJsonCmd('POST', `${API}/mills${node.mill}`, { opts: node.opts, payload })
out.name = name
console.log(out)
output(out)
return out
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment