Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 8c13bb0

Browse files
committed
refactor: remove proxy api object and detect initialisaion state
Ask the repo if it has been initialised, if so, allow the user to skip the `.init()` step and move on to `.start()` Removes the proxy api object in favour of vanilla functions because it was causing errors to be thrown if you even referenced properties that were from a different api state. E.g. with an unitialised repo: ```javascript const ipfs = await IPFS.create({ init: false, start: false }) // no invocation, just referencing the property causes an error to be thrown console.info(ipfs.start) ``` I'd looked at changing the proxy behaviour to return a function that throws if invoked, but at the time the proxy is called you don't know what the calling code is going to do with the return value so it's hard to know if it's accessing a function or a property - the return value is just put on the stack and interacted with so it seemed simpler to just pull it out and define the API up front. A nice future improvement might be to have `.init`, `.start` and `.stop` export functions that update the API - that way after `.stop` has been invoked, it could restore the API from the post-`.init` state, but this can come later. Also upgrades `ipfsd-ctl` to pass refs only during factory creation. Depends on: - [ ] ipfs/js-ipfsd-ctl#457 - [ ] ipfs/js-ipfs-repo#219 - [ ] ipfs-inactive/npm-go-ipfs-dep#40
1 parent 39d87c5 commit 8c13bb0

File tree

12 files changed

+323
-103
lines changed

12 files changed

+323
-103
lines changed

.aegir.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,8 @@ module.exports = {
6969
port: 43134
7070
}, {
7171
type: 'js',
72-
ipfsModule: {
73-
path: __dirname,
74-
ref: require(__dirname)
75-
},
76-
ipfsHttpModule: {
77-
path: require.resolve('ipfs-http-client'),
78-
ref: require('ipfs-http-client')
79-
},
72+
ipfsModule: require(__dirname),
73+
ipfsHttpModule: require('ipfs-http-client'),
8074
ipfsBin: path.join(__dirname, 'src', 'cli', 'bin.js'),
8175
ipfsOptions: {
8276
config: {
@@ -89,7 +83,7 @@ module.exports = {
8983
}
9084
}, {
9185
go: {
92-
ipfsBin: require.resolve(`go-ipfs-dep/go-ipfs/ipfs${os.platform() === 'win32' ? '.exe' : ''}`)
86+
ipfsBin: require('go-ipfs-dep').path()
9387
}
9488
}).start()
9589
},

examples/circuit-relaying/test.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,8 @@ const execa = require('execa')
77
const delay = require('delay')
88
const { createFactory } = require('ipfsd-ctl')
99
const df = createFactory({
10-
ipfsModule: {
11-
path: require.resolve('../../src'),
12-
ref: require('../../src')
13-
},
14-
ipfsHttpModule: {
15-
path: require.resolve('ipfs-http-client'),
16-
ref: require('ipfs-http-client')
17-
}
10+
ipfsModule: require('../../src'),
11+
ipfsHttpModule: require('ipfs-http-client')
1812
})
1913
const {
2014
startServer

examples/exchange-files-in-browser/test.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,8 @@ const execa = require('execa')
77
const delay = require('delay')
88
const { createFactory } = require('ipfsd-ctl')
99
const df = createFactory({
10-
ipfsModule: {
11-
path: require.resolve('../../src'),
12-
ref: require('../../src')
13-
},
14-
ipfsHttpModule: {
15-
path: require.resolve('ipfs-http-client'),
16-
ref: require('ipfs-http-client')
17-
}
10+
ipfsModule: require('../../src'),
11+
ipfsHttpModule: require('ipfs-http-client')
1812
}, {
1913
js: {
2014
ipfsBin: path.resolve(`${__dirname}/../../src/cli/bin.js`)

examples/explore-ethereum-blockchain/test.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@ const fs = require('fs-extra')
44
const path = require('path')
55
const { createFactory } = require('ipfsd-ctl')
66
const df = createFactory({
7-
ipfsModule: {
8-
path: require.resolve('../../src'),
9-
ref: require('../../src')
10-
},
11-
ipfsHttpModule: {
12-
path: require.resolve('ipfs-http-client'),
13-
ref: require('ipfs-http-client')
14-
}
7+
ipfsModule: require('../../src'),
8+
ipfsHttpModule: require('ipfs-http-client')
159
}, {
1610
js: {
1711
ipfsBin: path.resolve(`${__dirname}/../../src/cli/bin.js`)

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
"ipfs-http-response": "^0.5.0",
103103
"ipfs-mfs": "^1.0.0",
104104
"ipfs-multipart": "^0.3.0",
105-
"ipfs-repo": "^0.30.0",
105+
"ipfs-repo": "github:ipfs/js-ipfs-repo#feat-add-is-initialized-meethod",
106106
"ipfs-unixfs": "^0.3.0",
107107
"ipfs-unixfs-exporter": "^0.41.0",
108108
"ipfs-unixfs-importer": "^0.44.0",
@@ -182,11 +182,11 @@
182182
"dir-compare": "^1.7.3",
183183
"execa": "^3.0.0",
184184
"form-data": "^3.0.0",
185-
"go-ipfs-dep": "^0.4.23",
185+
"go-ipfs-dep": "github:ipfs/npm-go-ipfs-dep#add-path-function-to-detect-binary",
186186
"hat": "0.0.3",
187187
"interface-ipfs-core": "^0.132.0",
188188
"ipfs-interop": "github:ipfs/interop#refactor/async-await",
189-
"ipfsd-ctl": "github:ipfs/js-ipfsd-ctl#remove-option-normalisation",
189+
"ipfsd-ctl": "github:ipfs/js-ipfsd-ctl#remove-path-ref-and-findbin",
190190
"ncp": "^2.0.0",
191191
"p-event": "^4.1.0",
192192
"p-map": "^3.0.0",

src/core/api-manager.js

Lines changed: 116 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,128 @@
11
'use strict'
22

3+
const noop = () => {}
4+
const defaultApi = (onUndef = noop) => ({
5+
add: onUndef,
6+
bitswap: {
7+
stat: onUndef,
8+
unwant: onUndef,
9+
wantlist: onUndef
10+
},
11+
block: {
12+
get: onUndef,
13+
put: onUndef,
14+
rm: onUndef,
15+
stat: onUndef
16+
},
17+
bootstrap: {
18+
add: onUndef,
19+
list: onUndef,
20+
rm: onUndef
21+
},
22+
cat: onUndef,
23+
config: onUndef,
24+
dag: {
25+
get: onUndef,
26+
put: onUndef,
27+
resolve: onUndef,
28+
tree: onUndef
29+
},
30+
dns: onUndef,
31+
files: {
32+
chmod: onUndef,
33+
cp: onUndef,
34+
flush: onUndef,
35+
ls: onUndef,
36+
mkdir: onUndef,
37+
mv: onUndef,
38+
read: onUndef,
39+
rm: onUndef,
40+
stat: onUndef,
41+
touch: onUndef,
42+
write: onUndef
43+
},
44+
get: onUndef,
45+
id: onUndef,
46+
init: onUndef,
47+
isOnline: onUndef,
48+
key: {
49+
export: onUndef,
50+
gen: onUndef,
51+
import: onUndef,
52+
info: onUndef,
53+
list: onUndef,
54+
rename: onUndef,
55+
rm: onUndef
56+
},
57+
ls: onUndef,
58+
name: {
59+
publish: onUndef,
60+
pubsub: {
61+
cancel: onUndef,
62+
state: onUndef,
63+
subs: onUndef
64+
}
65+
},
66+
object: {
67+
data: onUndef,
68+
get: onUndef,
69+
links: onUndef,
70+
new: onUndef,
71+
patch: {
72+
addLink: onUndef,
73+
appendData: onUndef,
74+
rmLink: onUndef,
75+
setData: onUndef
76+
},
77+
put: onUndef,
78+
stat: onUndef
79+
},
80+
pin: onUndef,
81+
ping: onUndef,
82+
pubsub: {
83+
subscribe: onUndef,
84+
unsubscribe: onUndef,
85+
publish: onUndef,
86+
ls: onUndef,
87+
peers: onUndef
88+
},
89+
refs: onUndef,
90+
repo: {
91+
gc: onUndef,
92+
stat: onUndef,
93+
version: onUndef
94+
},
95+
resolve: onUndef,
96+
start: onUndef,
97+
stats: {
98+
bitswap: onUndef,
99+
bw: onUndef,
100+
repo: onUndef
101+
},
102+
stop: onUndef,
103+
swarm: {
104+
addrs: onUndef,
105+
connect: onUndef,
106+
disconnect: onUndef,
107+
localAddrs: onUndef,
108+
peers: onUndef
109+
},
110+
version: onUndef
111+
})
112+
3113
module.exports = class ApiManager {
4114
constructor () {
5-
this._api = {}
6-
this._onUndef = () => undefined
7-
this.api = new Proxy(this._api, {
8-
get: (_, prop) => {
9-
if (prop === 'then') return undefined // Not a promise!
10-
return this._api[prop] === undefined ? this._onUndef(prop) : this._api[prop]
11-
}
12-
})
115+
this.api = {
116+
...defaultApi()
117+
}
13118
}
14119

15120
update (nextApi, onUndef) {
16121
const prevApi = { ...this._api }
17122
const prevUndef = this._onUndef
18-
Object.keys(this._api).forEach(k => { delete this._api[k] })
19-
Object.assign(this._api, nextApi)
20-
if (onUndef) this._onUndef = onUndef
123+
Object.keys(this.api).forEach(k => { delete this.api[k] })
124+
Object.assign(this.api, defaultApi(onUndef), nextApi)
125+
this._onUndef = onUndef || noop
21126
return { cancel: () => this.update(prevApi, prevUndef), api: this.api }
22127
}
23128
}

src/core/components/init.js

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
11
'use strict'
22

33
const log = require('debug')('ipfs:components:init')
4+
const defer = require('p-defer')
45
const PeerId = require('peer-id')
56
const PeerInfo = require('peer-info')
67
const mergeOptions = require('merge-options')
78
const getDefaultConfig = require('../runtime/config-nodejs.js')
8-
const createRepo = require('../runtime/repo-nodejs')
99
const Keychain = require('libp2p-keychain')
1010
const NoKeychain = require('./no-keychain')
1111
const mortice = require('mortice')
1212
const { DAGNode } = require('ipld-dag-pb')
1313
const UnixFs = require('ipfs-unixfs')
1414
const multicodec = require('multicodec')
1515
const {
16-
AlreadyInitializingError,
1716
AlreadyInitializedError,
18-
NotStartedError,
19-
NotEnabledError
17+
NotStartedError
2018
} = require('../errors')
2119
const BlockService = require('ipfs-block-service')
2220
const Ipld = require('ipld')
2321
const getDefaultIpldOptions = require('../runtime/ipld-nodejs')
2422
const createPreloader = require('../preload')
25-
const { ERR_REPO_NOT_INITIALIZED } = require('ipfs-repo').errors
2623
const IPNS = require('../ipns')
2724
const OfflineDatastore = require('../ipns/routing/offline-datastore')
2825
const initAssets = require('../runtime/init-assets-nodejs')
@@ -32,9 +29,11 @@ const Components = require('./')
3229
module.exports = ({
3330
apiManager,
3431
print,
35-
options: constructorOptions
32+
options: constructorOptions,
33+
repo
3634
}) => async function init (options) {
37-
const { cancel } = apiManager.update({ init: () => { throw new AlreadyInitializingError() } })
35+
const initPromise = defer()
36+
const { cancel } = apiManager.update({ init: () => initPromise.promise })
3837

3938
try {
4039
options = options || {}
@@ -49,30 +48,9 @@ module.exports = ({
4948
options.config = mergeOptions(options.config, constructorOptions.config)
5049
}
5150

52-
options.repo = options.repo || constructorOptions.repo
5351
options.repoAutoMigrate = options.repoAutoMigrate || constructorOptions.repoAutoMigrate
5452

55-
const repo = typeof options.repo === 'string' || options.repo == null
56-
? createRepo({ path: options.repo, autoMigrate: options.repoAutoMigrate })
57-
: options.repo
58-
59-
let isInitialized = true
60-
61-
if (repo.closed) {
62-
try {
63-
await repo.open()
64-
} catch (err) {
65-
if (err.code === ERR_REPO_NOT_INITIALIZED) {
66-
isInitialized = false
67-
} else {
68-
throw err
69-
}
70-
}
71-
}
72-
73-
if (!isInitialized && options.allowNew === false) {
74-
throw new NotEnabledError('new repo initialization is not enabled')
75-
}
53+
const isInitialized = await repo.isInitialized()
7654

7755
const { peerId, keychain } = isInitialized
7856
? await initExistingRepo(repo, options)
@@ -160,9 +138,11 @@ module.exports = ({
160138
apiManager.update(api, () => { throw new NotStartedError() })
161139
} catch (err) {
162140
cancel()
141+
initPromise.reject(err)
163142
throw err
164143
}
165144

145+
initPromise.resolve(apiManager.api)
166146
return apiManager.api
167147
}
168148

@@ -212,6 +192,7 @@ async function initNewRepo (repo, { privateKey, emptyRepo, bits, profiles, confi
212192
}
213193

214194
async function initExistingRepo (repo, { config: newConfig, profiles, pass }) {
195+
await repo.open()
215196
let config = await repo.config.get()
216197

217198
if (newConfig || profiles) {

0 commit comments

Comments
 (0)