Skip to content

Commit

Permalink
fix: address PR comments, refactor to modern class
Browse files Browse the repository at this point in the history
  • Loading branch information
achingbrain committed Dec 18, 2019
1 parent 9517501 commit 45b0b30
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 62 deletions.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
![](https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square)
![](https://img.shields.io/badge/Node.js-%3E%3D8.0.0-orange.svg?style=flat-square)

> JavaScript implementation of IPFS' unixfs (a Unix FileSystem files representation on top of a MerkleDAG)
> JavaScript implementation of IPFS' UnixFS (a Unix FileSystem files representation on top of a MerkleDAG)
[The unixfs spec can be found inside the ipfs/specs repository](http://github.com/ipfs/specs)
The UnixFS spec can be found inside the [ipfs/specs repository](http://github.com/ipfs/specs)

## Lead Maintainer <!-- omit in toc -->

Expand All @@ -30,11 +30,12 @@
- [Create a file composed by several blocks](#create-a-file-composed-by-several-blocks)
- [Create a directory that contains several files](#create-a-directory-that-contains-several-files)
- [API](#api)
- [unixfs Data Structure](#unixfs-data-structure)
- [UnixFS Data Structure](#unixfs-data-structure)
- [create an unixfs Data element](#create-an-unixfs-data-element)
- [add and remove a block size to the block size list](#add-and-remove-a-block-size-to-the-block-size-list)
- [get total fileSize](#get-total-filesize)
- [marshal and unmarshal](#marshal-and-unmarshal)
- [is this UnixFS entry a directory?](#is-this-unixfs-entry-a-directory)
- [Contribute](#contribute)
- [License](#license)

Expand All @@ -49,20 +50,20 @@
### Use in Node.js

```JavaScript
var Unixfs = require('ipfs-unixfs')
var UnixFS = require('ipfs-unixfs')
```

### Use in a browser with browserify, webpack or any other bundler

The code published to npm that gets loaded on require is in fact a ES5 transpiled version with the right shims added. This means that you can require it and use with your favourite bundler without having to adjust asset management process.

```JavaScript
var Unixfs = require('ipfs-unixfs')
var UnixFS = require('ipfs-unixfs')
```

### Use in a browser Using a script tag

Loading this module through a script tag will make the `Unixfs` obj available in the global namespace.
Loading this module through a script tag will make the `UnixFS` obj available in the global namespace.

```html
<script src="https://npmcdn.com/ipfs-unixfs/dist/index.min.js"></script>
Expand All @@ -77,7 +78,7 @@ Loading this module through a script tag will make the `Unixfs` obj available in
#### Create a file composed by several blocks

```JavaScript
const data = new Unixfs({ type: 'file' })
const data = new UnixFS({ type: 'file' })
data.addBlockSize(256) // add the size of each block
data.addBlockSize(256)
// ...
Expand All @@ -88,12 +89,12 @@ data.addBlockSize(256)
Creating a directory that contains several files is achieve by creating a unixfs element that identifies a MerkleDAG node as a directory. The links of that MerkleDAG node are the files that are contained in this directory.

```JavaScript
const data = new Unixfs({ type: 'directory' })
const data = new UnixFS({ type: 'directory' })
```

## API

#### unixfs Data Structure
#### UnixFS Data Structure

```protobuf
syntax = "proto2";
Expand All @@ -119,7 +120,7 @@ message Data {
}
message Metadata {
required string MimeType = 1;
optional string MimeType = 1;
}
```

Expand All @@ -131,7 +132,7 @@ const data = new UnixFS([options])

`options` is an optional object argument that might include the following keys:

- type (string, default `file`): The type of UnixFS node. Can be:
- type (string, default `file`): The type of UnixFS entry. Can be:
- `raw`
- `directory`
- `file`
Expand Down Expand Up @@ -166,6 +167,16 @@ const marshaled = data.marshal()
const unmarshaled = Unixfs.unmarshal(marshaled)
```

#### is this UnixFS entry a directory?

```JavaScript
const dir = new Data({ type: 'directory' })
dir.isDirectory() // true

const file = new Data({ type: 'file' })
file.isDirectory() // false
```

## Contribute

Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/js-ipfs-unixfs/issues)!
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
"devDependencies": {
"aegir": "^20.4.1",
"chai": "^4.2.0",
"dirty-chai": "^2.0.1",
"safe-buffer": "^5.1.2"
"dirty-chai": "^2.0.1"
},
"dependencies": {
"protons": "^1.1.0"
Expand Down
117 changes: 70 additions & 47 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

const protons = require('protons')
const pb = protons(require('./unixfs.proto'))
// encode/decode
const unixfsData = pb.Data
// const unixfsMetadata = pb.MetaData // encode/decode

const types = [
'raw',
Expand All @@ -23,55 +21,91 @@ const dirTypes = [
const DEFAULT_FILE_MODE = parseInt('0644', 8)
const DEFAULT_DIRECTORY_MODE = parseInt('0755', 8)

function Data (arg1, arg2) {
if (!(this instanceof Data)) {
return new Data(arg1, arg2)
}

if (arg1 == null) {
arg1 = {
function parseArgs (args) {
if (args.length === 0) {
return {
type: 'file'
}
}

let { type, data, blockSizes, mtime, mode } = arg1

if (typeof arg1 === 'string' || arg1 instanceof String) {
if (args.length === 2) {
// support old-style constructor
type = arg1
data = arg2
return {
type: args[0],
data: args[1]
}
}

if (types.indexOf(type) === -1) {
throw new Error('Type: ' + type + ' is not valid')
if (typeof args[0] === 'string' || args[0] instanceof String) {
return {
type: args[0]
}
}

return args[0]
}

class Data {
// decode from protobuf https://github.com/ipfs/specs/blob/master/UNIXFS.md
static unmarshal (marshaled) {
const decoded = unixfsData.decode(marshaled)

return new Data({
type: types[decoded.Type],
data: decoded.hasData() ? decoded.Data : undefined,
blockSizes: decoded.blocksizes,
mode: decoded.hasMode() ? decoded.mode : undefined,
mtime: decoded.hasMtime() ? new Date(decoded.mtime * 1000) : undefined
})
}

this.type = type
this.data = data
this.blockSizes = blockSizes || []
constructor (...args) {
const {
type,
data,
blockSizes,
hashType,
fanout,
mtime,
mode
} = parseArgs(args)

if (!types.includes(type)) {
throw new Error('Type: ' + type + ' is not valid')
}

this.mtime = mtime || new Date(0)
this.mode = mode
this.type = type
this.data = data
this.hashType = hashType
this.fanout = fanout
this.blockSizes = blockSizes || []
this.mtime = mtime || new Date(0)
this.mode = mode

if (this.mode === undefined && type === 'file') {
this.mode = DEFAULT_FILE_MODE
if (this.mode === undefined && type === 'file') {
this.mode = DEFAULT_FILE_MODE
}

if (this.mode === undefined && this.isDirectory()) {
this.mode = DEFAULT_DIRECTORY_MODE
}
}

if (this.mode === undefined && type.includes('directory')) {
this.mode = DEFAULT_DIRECTORY_MODE
isDirectory () {
return dirTypes.includes(this.type)
}

this.addBlockSize = (size) => {
addBlockSize (size) {
this.blockSizes.push(size)
}

this.removeBlockSize = (index) => {
removeBlockSize (index) {
this.blockSizes.splice(index, 1)
}

// data.length + blockSizes
this.fileSize = () => {
if (dirTypes.indexOf(this.type) >= 0) {
fileSize () {
if (this.isDirectory()) {
// dirs don't have file size
return undefined
}
Expand All @@ -80,14 +114,16 @@ function Data (arg1, arg2) {
this.blockSizes.forEach((size) => {
sum += size
})

if (this.data) {
sum += this.data.length
}

return sum
}

// encode to protobuf
this.marshal = () => {
marshal () {
let type

switch (this.type) {
Expand Down Expand Up @@ -115,7 +151,7 @@ function Data (arg1, arg2) {

let mode

if (!isNaN(this.mode)) {
if (!isNaN(parseInt(this.mode))) {
mode = this.mode

if (mode === DEFAULT_FILE_MODE && this.type === 'file') {
Expand Down Expand Up @@ -144,23 +180,10 @@ function Data (arg1, arg2) {
blocksizes: blockSizes,
hashType: this.hashType,
fanout: this.fanout,
mode: mode,
mtime: mtime
mode,
mtime
})
}
}

// decode from protobuf https://github.com/ipfs/go-ipfs/blob/master/unixfs/format.go#L24
Data.unmarshal = (marshaled) => {
const decoded = unixfsData.decode(marshaled)

return new Data({
type: types[decoded.Type],
data: decoded.hasData() ? decoded.Data : undefined,
blockSizes: decoded.blocksizes,
mode: decoded.hasMode() ? decoded.mode : undefined,
mtime: decoded.hasMtime() ? new Date(decoded.mtime * 1000) : undefined
})
}

exports = module.exports = Data
module.exports = Data
2 changes: 1 addition & 1 deletion src/unixfs.proto.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ message Data {
}
message Metadata {
required string MimeType = 1;
optional string MimeType = 1;
}
`
2 changes: 1 addition & 1 deletion test/unixfs-format.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const raw = loadFixture('test/fixtures/raw.unixfs')
const directory = loadFixture('test/fixtures/directory.unixfs')
const file = loadFixture('test/fixtures/file.txt.unixfs')
const symlink = loadFixture('test/fixtures/symlink.txt.unixfs')
const Buffer = require('safe-buffer').Buffer
const { Buffer } = require('buffer')

describe('unixfs-format', () => {
it('defaults to file', () => {
Expand Down

0 comments on commit 45b0b30

Please sign in to comment.