Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": ["prettier", "eslint:recommended"],
"env": {
"node": true
"node": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2017
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ typings/
package-lock.json
yarn.lock

pub-archive
pub-archive
applications/*
NOTES.md
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public/vendor/
6 changes: 5 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{"semi": false, "singleQuote": true, "bracketSpacing": true}
{
"semi": false,
"singleQuote": true,
"bracketSpacing": true
}
68 changes: 68 additions & 0 deletions applications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const DatArchive = require('node-dat-archive')
const { lstatSync, readdirSync } = require('fs')
const { join, basename } = require('path')
const mkdirp = require('mkdirp')

const APPLICATIONS_DIR = join(__dirname, 'applications')
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be configurable by the user.


const isDirectory = source => lstatSync(source).isDirectory()

const getDirectories = source =>
readdirSync(source)
.map(name => join(source, name))
.filter(isDirectory)
.map(name => basename(name))
.filter(name => name.length === 64)

mkdirp.sync(APPLICATIONS_DIR)

const archives = new Map()

exports.getApplicationPubs = () => archives

exports.createApplicationPub = async applicationKey => {
if (archives.has(applicationKey)) {
return archives.get(applicationKey)
}

const localPath = join(APPLICATIONS_DIR, applicationKey, 'pub')

mkdirp.sync(localPath)

const archive = await DatArchive.create({
localPath,
title: `Known archives for application: dat://${applicationKey}`,
description: 'Pub archive for application',
datOptions: { latest: true }
})

// wait for archive to be ready for use
await archive._loadPromise

await loadAllArchives()

return archive
}

async function loadAllArchives() {
const dirs = getDirectories(APPLICATIONS_DIR).filter(
applicationKey => archives.has(applicationKey) === false
)

for (let applicationKey of dirs) {
const archive = await DatArchive.load({
localPath: join(APPLICATIONS_DIR, applicationKey, 'pub'),
datOptions: { latest: true }
})

if (archive == null) {
throw new Error(
`Error when creating or loading archive for ${applicationKey}`
)
}

archives.set(applicationKey, archive)
}
}

exports.loadAllArchives = loadAllArchives
108 changes: 10 additions & 98 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,102 +1,14 @@
const DatArchive = require('node-dat-archive')
const fastify = require('fastify')({ logger: true })
const mkdirp = require('dat-mkdirp')
const datPathExists = require('dat-path-exists')
const { createServer } = require('./server')

const IS_DAT = /^dat:\/\/.+/
async function main() {
const fastify = await createServer()

function createServer(archive) {
fastify.get('/', async () => {
return {
url: archive.url
}
})

fastify.post(
'/',
{
schema: {
body: {
type: 'object',
required: ['url', 'application'],
properties: {
url: {
type: 'string'
},
application: {
type: 'string'
}
}
},
response: {
200: {
type: 'object',
properties: {
location: {
type: 'string'
}
}
}
}
}
},
async (request) => {
const newURL = request.body.url
const application = request.body.application

if (!IS_DAT.exec(newURL)) throw new Error('Invalid url')

if (!IS_DAT.exec(application)) throw new Error('Invalid application url')

const newArchive = new DatArchive(newURL, {
datOptions: { latest: true }
})

const proofLocation = `/.well-known/dat-pubs/${archive.url.slice(6)}.json`
try {
const file = await newArchive.readFile(proofLocation)
const proofData = JSON.parse(file)

if (!proofData || !Array.isArray(proofData.applications)) {
throw new Error('Invalid format for proof file')
}

if (proofData.applications.indexOf(application) === -1) {
throw new Error(`Missing application (${application}) in proof list`)
}

const recordLocation = `/${application.slice(6)}/${newURL.slice(
6
)}.json`

const alreadyExists = await datPathExists(recordLocation, archive)

if (alreadyExists) throw new Error('Already registered')

const recordData = JSON.stringify({})

await mkdirp(`/${application.slice(6)}`, archive)

await archive.writeFile(recordLocation, recordData)

return {
location: `${archive.url}${recordLocation}`
}
} catch (e) {
const err = new Error(
`${
e.message
}. Could not find a valid proof at '${newURL}${proofLocation}'`
)
err.statusCode = 403
throw err
}
}
)

return fastify
try {
await fastify.listen(process.env.PORT || 3000, '0.0.0.0')
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}

module.exports = {
createServer
}
main()
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Lightweight HTTP service for discovering dats",
"main": "index.js",
"scripts": {
"start": "node server.js",
"start": "node index.js",
"pretest": "eslint --ignore-path .gitignore .",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand All @@ -28,8 +28,12 @@
"dependencies": {
"dat-mkdirp": "^1.0.0",
"dat-path-exists": "^1.0.0",
"ejs": "^2.6.1",
"fastify": "^1.3.1",
"node-dat-archive": "^2.0.1"
"fastify-static": "^0.12.0",
"mkdirp": "^0.5.1",
"node-dat-archive": "^2.0.1",
"parse-dat-url": "^3.0.1"
},
"devDependencies": {
"eslint": "^5.1.0",
Expand Down
Loading