This repository has been archived by the owner on Aug 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
createResolver.js
103 lines (87 loc) · 2.88 KB
/
createResolver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
'use strict'
const waterfall = require('async/waterfall')
const createIsLink = require('../util/createIsLink')
const createUtil = require('../util/createUtil')
module.exports = createResolver
function createResolver (multicodec, EthObjClass, mapFromEthObject) {
const util = createUtil(multicodec, EthObjClass)
const resolver = {
multicodec: multicodec,
defaultHashAlg: 'keccak-256',
resolve: resolve,
tree: tree,
isLink: createIsLink(resolve),
_resolveFromEthObject: resolveFromEthObject,
_treeFromEthObject: treeFromEthObject,
_mapFromEthObject: mapFromEthObject
}
return {
resolver: resolver,
util: util,
}
/*
* tree: returns a flattened array with paths: values of the project. options
* are option (i.e. nestness)
*/
function tree (binaryBlob, options, callback) {
// parse arguments
if (typeof options === 'function') {
callback = options
options = undefined
}
if (!options) {
options = {}
}
waterfall([
(cb) => util.deserialize(binaryBlob, cb),
(ethObj, cb) => treeFromEthObject(ethObj, options, cb)
], callback)
}
function treeFromEthObject (ethObj, options, callback) {
waterfall([
(cb) => mapFromEthObject(ethObj, options, cb),
(tuples, cb) => cb(null, tuples.map((tuple) => tuple.path))
], callback)
}
/*
* resolve: receives a path and a binary blob and returns the value on path,
* throw if not possible. `binaryBlob`` is an Ethereum binary block.
*/
function resolve (binaryBlob, path, callback) {
waterfall([
(cb) => util.deserialize(binaryBlob, cb),
(ethObj, cb) => resolveFromEthObject(ethObj, path, cb)
], callback)
}
function resolveFromEthObject (ethObj, path, callback) {
// root
if (!path || path === '/') {
const result = { value: ethObj, remainderPath: '' }
return callback(null, result)
}
// check tree results
mapFromEthObject(ethObj, {}, (err, paths) => {
if (err) return callback(err)
// parse path
const pathParts = path.split('/')
// find potential matches
let matches = paths.filter((child) => child.path === path.slice(0, child.path.length))
// only match whole path chunks
matches = matches.filter((child) => child.path.split('/').every((part, index) => part === pathParts[index]))
// take longest match
const sortedMatches = matches.sort((a, b) => a.path.length < b.path.length)
const treeResult = sortedMatches[0]
if (!treeResult) {
let err = new Error('Path not found ("' + path + '").')
return callback(err)
}
// slice off remaining path (after match and following slash)
const remainderPath = path.slice(treeResult.path.length + 1)
const result = {
value: treeResult.value,
remainderPath: remainderPath
}
return callback(null, result)
})
}
}