New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

git-ssb-web

Package Overview
Dependencies
Maintainers
1
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

git-ssb-web - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

async-memo.js

19

about.js

@@ -12,20 +12,7 @@ /* ssb-about

var cat = require('pull-cat')
var asyncMemo = require('./async-memo')
module.exports = function (sbot, myId) {
var cache = {/* id: about */}
var callbacks = {/* id: [callback] */}
module.exports = function (sbot, id) {
var getAbout = asyncMemo(getAboutFull, sbot, id)
function getAbout(id, cb) {
if (id in cache)
return cb(null, cache[id])
if (id in callbacks)
return callbacks[id].push(cb)
var cbs = callbacks[id] = [cb]
getAboutFull(sbot, myId, id, function (err, about) {
var about = !err && (cache[id] = about)
while (cbs.length)
cbs.pop()(err, about)
})
}
getAbout.getName = function (id, cb) {

@@ -32,0 +19,0 @@ getAbout(id, function (err, about) {

@@ -0,2 +1,4 @@

var fs = require('fs')
var http = require('http')
var path = require('path')
var url = require('url')

@@ -10,3 +12,17 @@ var ref = require('ssb-ref')

var ssbAbout = require('./about')
var marked = require('ssb-marked')
var asyncMemo = require('./async-memo')
var multicb = require('multicb')
marked.setOptions({
gfm: true,
mentions: true,
tables: true,
breaks: true,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: false
})
function parseAddr(str, def) {

@@ -77,2 +93,30 @@ if (!str) return def

function tryDecodeURIComponent(str) {
if (!str || (str[0] == '%' && ref.isBlobId(str)))
return str
try {
str = decodeURIComponent(str)
} finally {
return str
}
}
function getRepoName(repoId, cb) {
// TODO: use petnames
cb(null, repoId.substr(0, 20) + '…')
}
var hasOwnProp = Object.prototype.hasOwnProperty
function getContentType(filename) {
var ext = filename.split('.').pop()
return hasOwnProp.call(contentTypes, ext)
? contentTypes[ext]
: 'text/plain'
}
var contentTypes = {
css: 'text/css'
}
var msgTypes = {

@@ -88,3 +132,3 @@ 'git-repo': true,

module.exports = function (listenAddr, cb) {
var ssb, reconnect, myId
var ssb, reconnect, myId, getRepo
var about = function (id, cb) { cb(null, {name: id}) }

@@ -103,2 +147,5 @@

})
getRepo = asyncMemo(function (id, cb) {
ssbGit.getRepo(ssb, id, {live: true}, cb)
})
}

@@ -132,7 +179,10 @@ }

var u = url.parse(req.url)
var dirs = u.pathname.slice(1).split(/\/+/).map(decodeURIComponent)
var dirs = u.pathname.slice(1).split(/\/+/)
switch (dirs[0]) {
case '':
return serveIndex(req)
case 'static':
return serveFile(req, dirs)
default:
dirs = dirs.map(tryDecodeURIComponent)
if (ref.isMsgId(dirs[0]))

@@ -147,13 +197,37 @@ return serveRepoPage(dirs[0], dirs.slice(1))

function serve404(req) {
var body = '404 Not Found'
function serveFile(req, dirs) {
var filename = path.join.apply(path, [__dirname].concat(dirs))
return readNext(function (cb) {
fs.stat(filename, function (err, stats) {
cb(null, err ?
err.code == 'ENOENT' ? serve404(req)
: servePlainError(500, err.message)
: stats.isDirectory() ?
servePlainError(403, 'Directory not listable')
: cat([
pull.once([200, {
'Content-Type': getContentType(filename),
'Content-Length': stats.size,
'Last-Modified': stats.mtime.toGMTString()
}]),
toPull(fs.createReadStream(filename))
]))
})
})
}
function servePlainError(code, msg) {
return pull.values([
[404, {
'Content-Length': body.length,
[code, {
'Content-Length': msg.length,
'Content-Type': 'text/plain'
}],
body
msg
])
}
function serve404(req) {
return servePlainError(404, '404 Not Found')
}
function renderTry(read) {

@@ -177,16 +251,32 @@ var ended

function serveError(id, err) {
function serveTemplate(title, code, read) {
if (read === undefined) return serveTemplate.bind(this, title, code)
return cat([
pull.values([
[code || 200, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>' + escapeHTML(title || 'git ssb') + '</title>',
'<link rel=stylesheet href="/static/styles.css?' + Math.random() + '"/>',
'</head>\n',
'<body>',
'<header>',
'<h1><a href="/">git ssb</a></h1>',
'</header>',
'<article>']),
renderTry(read),
pull.once('</article></body></html>')
])
}
function serveError(err) {
if (err.message == 'stream is closed')
reconnect()
return pull.values([
[500, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>' + err.name + '</title></head><body>',
'<h1><a href="/">git ssb</a></h1>',
'<h2>' + err.name + '</h3>' +
'<pre>' + escapeHTML(err.stack) + '</pre>' +
'</body></html>'
])
return pull(
pull.once(
'<h2>' + err.name + '</h3>' +
'<pre>' + escapeHTML(err.stack) + '</pre>'),
serveTemplate(err.name, 500)
)
}

@@ -197,31 +287,36 @@

function renderFeed(feedId) {
var opts = {
reverse: true,
id: feedId
}
return pull(
ssb.links({
reverse: true,
rel: 'repo',
source: feedId,
values: true
feedId ? ssb.createUserStream(opts) : ssb.createLogStream(opts),
pull.filter(function (msg) {
return msg.value.content.type in msgTypes
}),
pull.take(20),
pull.asyncMap(renderUpdate)
pull.asyncMap(function (msg, cb) {
about.getName(msg.value.author, function (err, name) {
if (err) return cb(err)
switch (msg.value.content.type) {
case 'git-repo': return renderRepoCreated(msg, name, cb)
case 'git-update': return renderUpdate(msg, name, cb)
}
})
})
)
}
/*
function renderRepoCreated(msg, cb) {
function renderRepoCreated(msg, authorName, cb) {
var repoLink = link([msg.key])
var authorLink = link([msg.value.author])
cb(null, '<p>' + timestamp(msg.value.timestamp) + '<br>' +
authorLink + ' created repo ' + repoLink + '</p>')
var authorLink = link([msg.value.author], authorName)
cb(null, '<section class="collapse">' + timestamp(msg.value.timestamp) + '<br>' +
authorLink + ' created repo ' + repoLink + '</section>')
}
*/
function renderUpdate(msg, cb) {
about.getName(msg.value.author, function (err, name) {
if (err) return cb(err)
var repoLink = link([msg.value.content.repo])
var authorLink = link([msg.value.author], name)
cb(null, '<p>' + timestamp(msg.value.timestamp) + '<br>' +
authorLink + ' pushed to ' + repoLink + '</p>')
})
function renderUpdate(msg, authorName, cb) {
var repoLink = link([msg.value.content.repo])
var authorLink = link([msg.value.author], authorName)
cb(null, '<section class="collapse">' + timestamp(msg.value.timestamp) + '<br>' +
authorLink + ' pushed to ' + repoLink + '</section>')
}

@@ -232,35 +327,15 @@

function serveIndex() {
return cat([
pull.values([
[200, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>git ssb</title></head><body>',
'<h1><a href="/">git ssb</a></h1>'
]),
renderTry(renderFeed()),
pull.once('</body></html>')
])
return serveTemplate('git ssb')(renderFeed())
}
function serveUserPage(feedId) {
return cat([
pull.values([
[200, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>git ssb</title></head><body>',
'<h1><a href="/">git ssb</a></h1>',
]),
return serveTemplate(feedId)(cat([
readOnce(function (cb) {
about.getName(feedId, function (err, name) {
cb(null, '<h2>' + link([feedId], name) + '</h2>' +
'<p><small><code>' + feedId + '</code></small></p>')
cb(null, '<h2>' + link([feedId], name) +
'<code class="user-id">' + feedId + '</code></h2>')
})
}),
renderFeed(feedId),
pull.once('</body></html>')
])
]))
}

@@ -273,3 +348,3 @@

return readNext(function (cb) {
ssbGit.getRepo(ssb, id, function (err, repo) {
getRepo(id, function (err, repo) {
if (err) {

@@ -279,3 +354,3 @@ if (0)

else
cb(null, serveError(id, err))
cb(null, serveError(err))
return

@@ -309,14 +384,7 @@ }

function serveRepoNotFound(id, err) {
return pull.values([
[404, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>Repo not found</title></head><body>',
'<h1><a href="/">git ssb</a></h1>',
return serveTemplate('Repo not found', 404, pull.values([
'<h2>Repo not found</h2>',
'<p>Repo ' + id + ' was not found</p>',
'<pre>' + escapeHTML(err.stack) + '</pre>',
'</body></html>'
])
]))
}

@@ -326,28 +394,26 @@

var gitUrl = 'ssb://' + repo.id
var gitLink = '<code>' + gitUrl + '</code>'
var gitLink = '<input class="clone-url" readonly="readonly" ' +
'value="' + gitUrl + '" size="' + gitUrl.length + '" ' +
'onclick="this.select()"/>'
return cat([
pull.values([
[200, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>' +
'<title>git ssb</title></head><body>' +
'<h1><a href="/">git ssb</a></h1>' +
'<h2>' + link([repo.id]) + '</h2>' +
'<p>git URL: ' + gitLink + '</p>']),
readOnce(function (cb) {
about.getName(repo.feed, function (err, name) {
cb(null, '<p>Author: ' + link([repo.feed], name) + '</p>')
})
}),
pull.once(
'<p>' + link([repo.id], 'Code') + ' ' +
link([repo.id, 'activity'], 'Activity') + ' ' +
link([repo.id, 'commits', branch], 'Commits') + '</p>' +
'<hr/>'
),
renderTry(body),
pull.once('<hr/></body></html>')
])
var done = multicb({ pluck: 1, spread: true })
getRepoName(repo.id, done())
about.getName(repo.feed, done())
return readNext(function (cb) {
done(function (err, repoName, authorName) {
if (err) return cb(null, serveError(err))
cb(null, serveTemplate(repo.id)(cat([
pull.once(
'<h2 class="repo-name">' + link([repo.feed], authorName) + ' / ' +
link([repo.id], repoName) + '</h2>' +
'<div class="repo-nav">' + link([repo.id], 'Code') +
link([repo.id, 'activity'], 'Activity') +
link([repo.id, 'commits', branch], 'Commits') +
gitLink +
'</div>'),
body
])))
})
})
}

@@ -358,8 +424,10 @@

return renderRepoPage(repo, rev, cat([
pull.once('<h3>' + type + ': ' + rev + ' '),
pull.once('<section><h3>' + type + ': ' + rev + ' '),
revMenu(repo, rev),
pull.once('</h3>'),
type == 'Branch' && renderRepoLatest(repo, rev),
pull.once('</section><section>'),
renderRepoTree(repo, rev, path),
renderRepoReadme(repo, rev, path),
pull.once('</section>'),
renderRepoReadme(repo, rev, path)
]))

@@ -395,3 +463,3 @@ }

return '<p>' + timestamp(msg.value.timestamp) + '<br>' +
return '<section class="collapse">' + timestamp(msg.value.timestamp) + '<br>' +
(numObjects ? 'Pushed ' + numObjects + ' objects<br>' : '') +

@@ -407,3 +475,3 @@ refs.map(function (update) {

}).join('<br>') +
'</p>'
'</section>'
}

@@ -416,3 +484,3 @@ }

return renderRepoPage(repo, branch, cat([
pull.once('<h3>Commits</h3><ul>'),
pull.once('<h3>Commits</h3>'),
pull(

@@ -425,3 +493,3 @@ repo.readLog(branch),

var treePath = [repo.id, 'tree', commit.id]
cb(null, '<li>' +
cb(null, '<section class="collapse">' +
'<strong>' + link(commitPath, escapeHTML(commit.title)) + '</strong><br>' +

@@ -432,7 +500,6 @@ '<code>' + commit.id + '</code> ' +

escapeHTML(commit.committer.name) + ' committed on ' + commit.committer.date.toLocaleString() +
'</li>')
'</section>')
})
})
),
pull.once('</ul>')
)
]))

@@ -479,3 +546,3 @@ }

var commitPath = [repo.id, 'commit', commit.id]
cb(null, '<p>' +
cb(null,
'Latest: <strong>' + link(commitPath, escapeHTML(commit.title)) +

@@ -488,4 +555,3 @@ '</strong><br>' +

escapeHTML(commit.author.name) + ' authored on ' +
commit.author.date.toLocaleString() : '') +
'</p>')
commit.author.date.toLocaleString() : ''))
})

@@ -505,5 +571,7 @@ })

function renderRepoTree(repo, rev, path) {
var pathLinks = linkPath([repo.id, 'tree'], [rev].concat(path))
var pathLinks = path.length === 0 ? '' :
': ' + linkPath([repo.id, 'tree'], [rev].concat(path))
return cat([
pull.once('<h3>Files: ' + pathLinks + '</h3><ul>'),
pull.once('<h3>Files' + pathLinks + '</h3>' +
'<ul class="files">'),
pull(

@@ -514,3 +582,4 @@ repo.readDir(rev, path),

var filePath = [repo.id, type, rev].concat(path, file.name)
return '<li>' + link(filePath) + '</li>'
var fileName = (type == 'tree') ? file.name + '/' : file.name
return '<li>' + link(filePath, fileName) + '</li>'
})

@@ -540,9 +609,17 @@ ),

cb(null, cat([
pull.once('<h4>' + escapeHTML(file.name) + '</h4>' +
'<blockquote><pre>'),
pull(
obj.read,
escapeHTMLStream()
),
pull.once('</pre></blockquote>')
pull.once('<section><h4>' + escapeHTML(file.name) + '</h4><hr/>'),
/\.md|\/.markdown/i.test(file.name) ?
readOnce(function (cb) {
pull(obj.read, pull.collect(function (err, bufs) {
if (err) return cb(err)
var buf = Buffer.concat(bufs, obj.length)
cb(null, marked(buf.toString()))
}))
})
: cat([
pull.once('<pre>'),
pull(obj.read, escapeHTMLStream()),
pull.once('</pre>')
]),
pull.once('</section>')
]))

@@ -598,14 +675,7 @@ })

function serveBlobNotFound(repoId, err) {
return pull.values([
[404, {
'Content-Type': 'text/html'
}],
'<!doctype html><html><head><meta charset=utf-8>',
'<title>Blob not found</title></head><body>',
'<h1><a href="/">git ssb</a></h1>',
return serveTemplate(400, 'Blob not found', pull.values([
'<h2>Blob not found</h2>',
'<p>Blob in repo ' + link([repoId]) + ' was not found</p>',
'<pre>' + escapeHTML(err.stack) + '</pre>',
'</body></html>'
])
'<pre>' + escapeHTML(err.stack) + '</pre>'
]))
}

@@ -612,0 +682,0 @@

{
"name": "git-ssb-web",
"version": "1.2.0",
"version": "1.3.0",
"description": "web server for browsing git repos on ssb",
"bin": "server.js",
"dependencies": {
"multicb": "^1.2.1",
"pull-cat": "^1.1.8",

@@ -14,2 +15,3 @@ "pull-git-repo": "^0.2.0",

"ssb-keys": "^4.0.10",
"ssb-marked": "^0.5.4",
"ssb-ref": "^2.2.2",

@@ -16,0 +18,0 @@ "ssb-reconnect": "^0.1.0",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc