Skip to content

Using the DatArchive API in Bunsen to create dat applications

Chris E. Kelley edited this page Nov 23, 2018 · 5 revisions

Support for the DatArchive API is being rolled out in Bunsen. Bunsen exposes a REST API via its node application (nodejs-project/index.js) that calls the DatArchive API.

Using DatArchive API in bunsen

The bunsen-datArchive-test dat archive, also available at dat://bunsen-play.hashbase.io demonstrates how to use Bunsen's DatArchive support.

In your application, link to the DatArchive class, datArchive.js, which implements the REST calls to the node server running on the device. This will then provide an instance of DatArchive you may summon.

Create a DatArchive

DatArchive.create({ title: 'Bunsen Test ', description: 'Testing Bunsen support of DatArchive API.' })

async function create() {
    Test.archive = await DatArchive.create({
        title: 'Bunsen Test ',
        description: 'Testing Bunsen support of DatArchive API.'
    })
    console.log("create returned" + JSON.stringify(Test.archive))
    document.querySelector("#createDocumentResponse").innerHTML = JSON.stringify(Test.archive)
}

Read a file

archive.readFile(url, filename)

async function readFile() {
    if (typeof Test.archive.readFile === "function") {
        // let url = Test.archive.url + "/dat.json"
        let url = Test.archive.url
        let filename = "/dat.json"
        try {
            let readFile = await Test.archive.readFile(url, filename)
            console.log("readFile returned" + JSON.stringify(readFile))
            document.querySelector("#readFileResponse").innerHTML = JSON.stringify(readFile)
        } catch (e) {
            console.log("Error reading " + url + " error: " + JSON.stringify(e))
        }
    } else {
        alert("Create the document first pleeeze.")
    }
}

Implementing DatArchive API calls in node

I had to make a small modification to node-dat-archive to enable the use an instance of dat-storage configured to point to the secret_keys directory. I forked it here; here is the change in node-dat-archive/index.js:

      let dirOrStorage = localPath || ram;
      if (typeof options.hd !== 'undefined') {
          dirOrStorage = options.hd
      }
//      Dat(localPath || ram, options, async (err, dat) => {
      Dat(dirOrStorage, options, async (err, dat) => {

Bunsen needs support implementing DatArchive API. Basics are working, but could be better. Here are some tips to get you going.

For basic operations, implementing the DatArchive API is simple:

app.post('/readFile', async function (request, response) {
    console.log("read a DatArchive")
    var filename = request.body.filename;
    var url = request.body.url;
    var datName = url.replace('dat://','')
    var localPath = dir + '/' + datName
    console.log("loading into DatArchive " + localPath)
    var datOptions = {latest: true}
    var netOptions = null;
    let data = {localPath, datOptions, netOptions}
    var archive = await DatArchive.load(data)
    console.log("now reading the file " + filename)
    var manifest = JSON.parse(await archive.readFile(filename))
    response.send(JSON.stringify(manifest))
});

To create data in DatArchive, you must have permissions. Normally DatArchive saves secret_keys at ~/.dat; however, this is not possible in Android; therefore, you must save them in a writable space on the Android filesystem. Currently, these keys are being stored in nodejs-project/secret_keys; ideally we can save them in the Android Keystore system using something like cordova-plugin-secure-key-store.

Note in the following code how a storage instance is created var store = storage(localPath, {secretDir: secretKeysRoot}); with the secretDir key:

app.post('/create', async function (request, response) {
    console.log("Creating a datArchive")
    var title = request.body.title;
    var description = request.body.description;
    var type = request.body.type;
    var author = request.body.author;
    var uuid = uuidv4();
    var localPath = datGatewayRoot + '/' + uuid;
    var store = storage(localPath, {secretDir: secretKeysRoot});
    var datOptions = {latest: true, hd: store}
    var netOptions = null;
    let data = {localPath, datOptions, netOptions, title, description, type, author}
    try {
        var archive = await DatArchive.create(data)
    } catch (e) {
        console.log("Error: " + e);
        var stack = new Error().stack
        console.log( stack )
        response.status(400).send({ statusText: e.toString() });
    }
    let url = archive.url
    data.url = url
    const newDir = url.replace('dat://','')
    const newPath = datGatewayRoot + '/' + newDir;
    // await sleep(1000)
    fs.rename(localPath, newPath, (err) => {
        if (err)  {
            // throw err;
            var stack = new Error().stack
            console.log( stack )
        }
        console.log('Rename complete!' + localPath + " to " + newPath);
    });
    data.localPath = newPath
    response.send(JSON.stringify(data))
});