Skip to content
This repository was archived by the owner on Sep 28, 2021. It is now read-only.

Commit 319e2b4

Browse files
authored
fix: update module (#104)
- Adds types - Converts to ESM - Uses [ejs](https://www.npmjs.com/package/ejs) for html templating
1 parent b9a998a commit 319e2b4

12 files changed

+301
-216
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ typings/
6262
# while testing npm5
6363
package-lock.json
6464
yarn.lock
65+
types

package.json

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,32 @@
44
"description": "Creates an HTTP response from an IPFS Hash",
55
"leadMaintainer": "Vasco Santos <[email protected]>",
66
"main": "src/index.js",
7+
"types": "./types/src/index.d.ts",
8+
"type": "module",
9+
"eslintConfig": {
10+
"extends": "ipfs",
11+
"parserOptions": {
12+
"sourceType": "module"
13+
}
14+
},
15+
"exports": {
16+
".": {
17+
"import": "./src/index.js"
18+
}
19+
},
720
"scripts": {
8-
"lint": "aegir lint",
21+
"prepare": "aegir build --no-bundle && cp -R types dist",
22+
"lint": "aegir ts -p check && aegir lint",
923
"build": "aegir build",
1024
"release": "aegir release --target node",
1125
"release-minor": "aegir release --type minor --target node",
26+
"pretest": "aegir build --esm-tests",
1227
"test": "aegir test -t node",
1328
"test:node": "aegir test -t node"
1429
},
1530
"browser": {
16-
"file-type": "file-type/browser"
31+
"file-type": "file-type/browser",
32+
"fs": false
1733
},
1834
"repository": {
1935
"type": "git",
@@ -32,8 +48,9 @@
3248
"homepage": "https://github.com/ipfs/js-ipfs-http-response#readme",
3349
"dependencies": {
3450
"debug": "^4.3.1",
51+
"ejs": "^3.1.6",
3552
"file-type": "^16.0.0",
36-
"filesize": "^7.0.0",
53+
"filesize": "^8.0.0",
3754
"it-buffer": "^0.1.1",
3855
"it-concat": "^2.0.0",
3956
"it-reader": "^3.0.0",
@@ -43,13 +60,14 @@
4360
"p-try-each": "^1.0.1"
4461
},
4562
"devDependencies": {
46-
"aegir": "^34.0.2",
63+
"@types/ejs": "^3.1.0",
64+
"aegir": "^35.0.3",
4765
"get-stream": "^6.0.0",
48-
"ipfs-core": "^0.9.1",
66+
"ipfs-core": "^0.10.5",
4967
"ipfsd-ctl": "^10.0.1",
5068
"it-all": "^1.0.5",
5169
"path": "^0.12.7",
52-
"uint8arrays": "^2.0.5",
70+
"uint8arrays": "^3.0.0",
5371
"util": "^0.12.3"
5472
},
5573
"contributors": [

src/dir-view/index.js

Lines changed: 65 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,76 @@
1-
'use strict'
2-
3-
const filesize = require('filesize')
4-
5-
const mainStyle = require('./style')
6-
const pathUtil = require('../utils/path')
1+
import filesize from 'filesize'
2+
import style from './style.js'
3+
import { cidArray } from '../utils/path.js'
4+
import ejs from 'ejs'
75

6+
/**
7+
* @param {string} path
8+
*/
89
function getParentHref (path) {
9-
const parts = pathUtil.cidArray(path).slice()
10+
const parts = cidArray(path).slice()
1011
if (parts.length > 1) {
1112
// drop the last segment in a safe way that works for both paths and urls
1213
return path.replace(`/${parts.pop()}`, '')
1314
}
1415
return path
1516
}
1617

17-
function buildFilesList (path, links) {
18-
const rows = links.map((link) => {
19-
let row = [
20-
'<div class="ipfs-icon ipfs-_blank">&nbsp;</div>',
21-
`<a href="${path}${path.endsWith('/') ? '' : '/'}${link.Name}">${link.Name}</a>`,
22-
filesize(link.Tsize)
23-
]
24-
25-
row = row.map((cell) => `<td>${cell}</td>`).join('')
26-
27-
return `<tr>${row}</tr>`
28-
})
29-
30-
return rows.join('')
31-
}
32-
33-
function buildTable (path, links) {
34-
return `
35-
<table class="table table-striped">
36-
<tbody>
37-
<tr>
38-
<td class="narrow">
39-
<div class="ipfs-icon ipfs-_blank">&nbsp;</div>
40-
</td>
41-
<td class="padding">
42-
<a href="${getParentHref(path)}">..</a>
43-
</td>
44-
<td></td>
45-
</tr>
46-
${buildFilesList(path, links)}
47-
</tbody>
48-
</table>
49-
`
50-
}
51-
52-
function render (path, links) {
53-
return `
54-
<!DOCTYPE html>
55-
<html>
56-
<head>
57-
<meta charset="utf-8">
58-
<title>${path}</title>
59-
<style>${mainStyle}</style>
60-
</head>
61-
<body>
62-
<div id="header" class="row">
63-
<div class="col-xs-2">
64-
<div id="logo" class="ipfs-logo"></div>
65-
</div>
18+
/**
19+
* @param {string} path
20+
* @param {({ Name: string, Tsize: number })[]} links
21+
*/
22+
export function render (path, links) {
23+
return ejs.render(`<!DOCTYPE html>
24+
<html>
25+
<head>
26+
<meta charset="utf-8">
27+
<title><%= path %></title>
28+
<style>${style}</style>
29+
</head>
30+
<body>
31+
<div id="header" class="row">
32+
<div class="col-xs-2">
33+
<div id="logo" class="ipfs-logo"></div>
34+
</div>
35+
</div>
36+
<br>
37+
<div class="col-xs-12">
38+
<div class="panel panel-default">
39+
<div class="panel-heading">
40+
<strong>Index of <%= path %></strong>
6641
</div>
67-
<br>
68-
<div class="col-xs-12">
69-
<div class="panel panel-default">
70-
<div class="panel-heading">
71-
<strong>Index of ${path}</strong>
72-
</div>
73-
${buildTable(path, links)}
74-
</div>
75-
</div>
76-
</body>
77-
</html>
78-
`
42+
<table class="table table-striped">
43+
<tbody>
44+
<tr>
45+
<td class="narrow">
46+
<div class="ipfs-icon ipfs-_blank">&nbsp;</div>
47+
</td>
48+
<td class="padding">
49+
<a href="<%= parentHref %>">..</a>
50+
</td>
51+
<td></td>
52+
</tr>
53+
<% links.forEach(function (link) { %>
54+
<tr>
55+
<td><div class="ipfs-icon ipfs-_blank">&nbsp;</div></td>
56+
<td><a href="<%= link.link %>"><%= link.name %></a></t>
57+
<td><%= link.size %></td>
58+
</td>
59+
</tr>
60+
<% }) %>
61+
</tbody>
62+
</table>
63+
</div>
64+
</div>
65+
</body>
66+
</html>
67+
`, {
68+
path,
69+
links: links.map((link) => ({
70+
name: link.Name,
71+
size: filesize(link.Tsize),
72+
link: `${path}${path.endsWith('/') ? '' : '/'}${link.Name}`
73+
})),
74+
parentHref: getParentHref(path)
75+
})
7976
}
80-
81-
exports.render = render

src/dir-view/style.js

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
/* global Response, Blob */
22

3-
'use strict'
4-
5-
const toStream = require('it-to-stream')
6-
const concat = require('it-concat')
7-
const toBuffer = require('it-buffer')
8-
const log = require('debug')('ipfs:http:response')
9-
10-
const resolver = require('./resolver')
11-
const pathUtils = require('./utils/path')
12-
const detectContentType = require('./utils/content-type')
3+
// @ts-ignore no types
4+
import toStream from 'it-to-stream'
5+
import concat from 'it-concat'
6+
// @ts-ignore no types
7+
import toBuffer from 'it-buffer'
8+
import debug from 'debug'
9+
import * as ipfsResolver from './resolver.js'
10+
import * as pathUtils from './utils/path.js'
11+
import { detectContentType } from './utils/content-type.js'
12+
13+
const log = debug('ipfs:http:response')
1314

1415
// TODO: pass path and add Etag and X-Ipfs-Path + tests
1516
const getHeader = (status = 200, statusText = 'OK', headers = {}) => ({
@@ -18,21 +19,27 @@ const getHeader = (status = 200, statusText = 'OK', headers = {}) => ({
1819
headers
1920
})
2021

21-
// handle hash resolve error (simple hash, test for directory now)
22+
/**
23+
* handle hash resolve error (simple hash, test for directory now)
24+
*
25+
* @param {*} node
26+
* @param {string} path
27+
* @param {*} error
28+
*/
2229
const handleResolveError = async (node, path, error) => {
2330
const errorString = error.toString()
2431

2532
if (errorString.includes('dag node is a directory')) {
2633
try {
27-
const content = await resolver.directory(node, path, error.cid)
34+
const content = await ipfsResolver.directory(node, path, error.cid)
2835
// dir render
2936
if (typeof content === 'string') {
3037
return new Response(content, getHeader(200, 'OK', { 'Content-Type': 'text/html' }))
3138
}
3239

3340
// redirect to dir entry point (index)
3441
return Response.redirect(pathUtils.joinURLParts(path, content[0].Name))
35-
} catch (error) {
42+
} catch (/** @type {any} */ error) {
3643
log(error)
3744
return new Response(errorString, getHeader(500, error.toString()))
3845
}
@@ -49,14 +56,20 @@ const handleResolveError = async (node, path, error) => {
4956
return new Response(errorString, getHeader(500, errorString))
5057
}
5158

52-
const getResponse = async (ipfsNode, ipfsPath) => {
59+
/**
60+
*
61+
* @param {*} ipfsNode
62+
* @param {*} ipfsPath
63+
* @returns
64+
*/
65+
export async function getResponse (ipfsNode, ipfsPath) {
5366
// remove trailing slash for files if needed
5467
if (ipfsPath.endsWith('/')) {
5568
return Response.redirect(pathUtils.removeTrailingSlash(ipfsPath))
5669
}
5770

5871
try {
59-
const resolvedData = await resolver.cid(ipfsNode, ipfsPath)
72+
const resolvedData = await ipfsResolver.cid(ipfsNode, ipfsPath)
6073
const { source, contentType } = await detectContentType(ipfsPath, ipfsNode.cat(resolvedData.cid))
6174

6275
if (typeof Blob === 'undefined') {
@@ -74,7 +87,7 @@ const getResponse = async (ipfsNode, ipfsPath) => {
7487
return contentType
7588
? new Response(blob, getHeader(200, 'OK', { 'Content-Type': contentType }))
7689
: new Response(blob, getHeader())
77-
} catch (err) {
90+
} catch (/** @type {any} */ err) {
7891
return new Response(err.toString(), getHeader(500, 'Error fetching the file'))
7992
}
8093
} catch (error) {
@@ -83,7 +96,10 @@ const getResponse = async (ipfsNode, ipfsPath) => {
8396
}
8497
}
8598

86-
module.exports = {
87-
getResponse,
88-
resolver
99+
export const resolver = {
100+
...ipfsResolver
101+
}
102+
103+
export const utils = {
104+
detectContentType
89105
}

0 commit comments

Comments
 (0)