hypercore-storage 0.0.41 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,107 @@
1
+ const { Readable, getStreamError } = require('streamx')
2
+ const { core } = require('./keys')
3
+
4
+ module.exports = class BlockStream extends Readable {
5
+ constructor (core, db, updates, start, end, reverse) {
6
+ super()
7
+
8
+ this.core = core
9
+ this.db = db
10
+ this.updates = updates
11
+ this.end = end
12
+ this.reverse = reverse === true
13
+
14
+ this._drained = true
15
+ this._consumed = 0
16
+ this._stream = null
17
+ this._oncloseBound = this._onclose.bind(this)
18
+ this._maybeDrainBound = this._maybeDrain.bind(this)
19
+
20
+ this._update()
21
+ }
22
+
23
+ _update () {
24
+ if (this._consumed > this.core.dependencies.length) return
25
+
26
+ const index = this.reverse ? this.core.dependencies.length - this._consumed : this._consumed
27
+ const offset = index === 0 ? 0 : this.core.dependencies[index - 1].length
28
+
29
+ let end = 0
30
+ let ptr = 0
31
+
32
+ if (this._consumed < this.core.dependencies.length) {
33
+ const dep = this.core.dependencies[this._consumed]
34
+ end = this.end === -1 ? dep.length : Math.min(this.end, dep.length)
35
+ ptr = dep.dataPointer
36
+ } else {
37
+ end = this.end === -1 ? Infinity : this.end
38
+ ptr = this.core.dataPointer
39
+ }
40
+
41
+ this._consumed++
42
+
43
+ if (end === offset) return
44
+
45
+ this._makeStream(core.block(ptr, offset), core.block(ptr, end))
46
+ }
47
+
48
+ _predestroy () {
49
+ if (this._stream !== null) this._stream.destroy()
50
+ }
51
+
52
+ _read (cb) {
53
+ this._drained = this._onreadable()
54
+ cb(null)
55
+ }
56
+
57
+ _maybeDrain () {
58
+ if (this._drained === true) return
59
+ this._drained = this._onreadable()
60
+ }
61
+
62
+ _onreadable () {
63
+ if (this._stream === null) {
64
+ this.push(null)
65
+ return true
66
+ }
67
+
68
+ let data = this._stream.read()
69
+
70
+ if (data === null) return false
71
+
72
+ do {
73
+ this.push(data)
74
+ data = this._stream.read()
75
+ } while (data !== null)
76
+
77
+ return true
78
+ }
79
+
80
+ _onclose () {
81
+ if (this.destroying) return
82
+
83
+ const err = getStreamError(this._stream)
84
+
85
+ if (err !== null) {
86
+ this.destroy(err)
87
+ return
88
+ }
89
+
90
+ // empty the current stream
91
+ if (this._onreadable() === true) this._drained = true
92
+
93
+ this._stream = this._start = this._end = null
94
+
95
+ this._update()
96
+ this._maybeDrain()
97
+ }
98
+
99
+ _makeStream (start, end) {
100
+ this._stream = this.updates.iterator(this.db, start, end, this.reverse)
101
+ this._stream.on('readable', this._maybeDrainBound)
102
+ this._stream.on('error', noop)
103
+ this._stream.on('close', this._oncloseBound)
104
+ }
105
+ }
106
+
107
+ function noop () {}
package/lib/keys.js ADDED
@@ -0,0 +1,242 @@
1
+ const { UINT, STRING } = require('index-encoder')
2
+ const c = require('compact-encoding')
3
+ const b4a = require('b4a')
4
+
5
+ const TL_HEAD = 0
6
+ const TL_CORE_BY_DKEY = 1
7
+ const TL_CORE_BY_ALIAS = 2
8
+ const TL_CORE = 3
9
+ const TL_DATA = 4
10
+
11
+ const TL_END = TL_DATA + 1
12
+
13
+ const CORE_AUTH = 0
14
+ const CORE_SESSIONS = 1
15
+
16
+ const DATA_HEAD = 0
17
+ const DATA_DEPENDENCY = 1
18
+ const DATA_HINTS = 2
19
+ const DATA_BLOCK = 3
20
+ const DATA_TREE = 4
21
+ const DATA_BITFIELD = 5
22
+ const DATA_USER_DATA = 6
23
+
24
+ const slab = { buffer: b4a.allocUnsafe(65536), start: 0, end: 0 }
25
+
26
+ const store = {}
27
+ const core = {}
28
+
29
+ store.clear = function () {
30
+ const state = alloc()
31
+ let start = state.start
32
+ UINT.encode(state, 0)
33
+ const a = state.buffer.subarray(start, state.start)
34
+ start = state.start
35
+ UINT.encode(state, TL_END)
36
+ const b = state.buffer.subarray(start, state.start)
37
+ return [a, b]
38
+ }
39
+
40
+ store.head = function () {
41
+ const state = alloc()
42
+ const start = state.start
43
+ UINT.encode(state, TL_HEAD)
44
+ return state.buffer.subarray(start, state.start)
45
+ }
46
+
47
+ store.core = function (discoveryKey) {
48
+ const state = alloc()
49
+ const start = state.start
50
+ UINT.encode(state, TL_CORE_BY_DKEY)
51
+ c.fixed32.encode(state, discoveryKey)
52
+ return state.buffer.subarray(start, state.start)
53
+ }
54
+
55
+ store.coreStart = function () {
56
+ const state = alloc()
57
+ const start = state.start
58
+ UINT.encode(state, TL_CORE_BY_DKEY)
59
+ return state.buffer.subarray(start, state.start)
60
+ }
61
+
62
+ store.coreEnd = function () {
63
+ const state = alloc()
64
+ const start = state.start
65
+ UINT.encode(state, TL_CORE_BY_DKEY + 1)
66
+ return state.buffer.subarray(start, state.start)
67
+ }
68
+
69
+ store.coreByAlias = function ({ namespace, name }) {
70
+ const state = alloc()
71
+ const start = state.start
72
+ UINT.encode(state, TL_CORE_BY_ALIAS)
73
+ c.fixed32.encode(state, namespace)
74
+ STRING.encode(state, name)
75
+ return state.buffer.subarray(start, state.start)
76
+ }
77
+
78
+ store.coreByAliasStart = function (namespace) {
79
+ const state = alloc()
80
+ const start = state.start
81
+ UINT.encode(state, TL_CORE_BY_ALIAS)
82
+ if (namespace) c.fixed32.encode(state, namespace)
83
+ return state.buffer.subarray(start, state.start)
84
+ }
85
+
86
+ store.coreByAliasEnd = function (namespace) {
87
+ const state = alloc()
88
+ const start = state.start
89
+
90
+ if (namespace) {
91
+ UINT.encode(state, TL_CORE_BY_ALIAS)
92
+ c.fixed32.encode(state, namespace)
93
+ state.buffer[state.start++] = 0xff
94
+ } else {
95
+ UINT.encode(state, TL_CORE_BY_ALIAS + 1)
96
+ }
97
+
98
+ return state.buffer.subarray(start, state.start)
99
+ }
100
+
101
+ store.alias = function (buffer) {
102
+ const state = { buffer, start: 0, end: buffer.byteLength }
103
+ UINT.decode(state) // ns
104
+ const namespace = c.fixed32.decode(state)
105
+ const name = STRING.decode(state)
106
+ return { namespace, name }
107
+ }
108
+
109
+ store.discoveryKey = function (buffer) {
110
+ const state = { buffer, start: 0, end: buffer.byteLength }
111
+ UINT.decode(state) // ns
112
+ return c.fixed32.decode(state)
113
+ }
114
+
115
+ core.auth = function (ptr) {
116
+ const state = alloc()
117
+ const start = state.start
118
+ UINT.encode(state, TL_CORE)
119
+ UINT.encode(state, ptr)
120
+ UINT.encode(state, CORE_AUTH)
121
+ return state.buffer.subarray(start, state.start)
122
+ }
123
+
124
+ core.sessions = function (ptr) {
125
+ const state = alloc()
126
+ const start = state.start
127
+ UINT.encode(state, TL_CORE)
128
+ UINT.encode(state, ptr)
129
+ UINT.encode(state, CORE_SESSIONS)
130
+ return state.buffer.subarray(start, state.start)
131
+ }
132
+
133
+ core.head = function (ptr) {
134
+ const state = alloc()
135
+ const start = state.start
136
+ UINT.encode(state, TL_DATA)
137
+ UINT.encode(state, ptr)
138
+ UINT.encode(state, DATA_HEAD)
139
+ return state.buffer.subarray(start, state.start)
140
+ }
141
+
142
+ core.dependency = function (ptr) {
143
+ const state = alloc()
144
+ const start = state.start
145
+ UINT.encode(state, TL_DATA)
146
+ UINT.encode(state, ptr)
147
+ UINT.encode(state, DATA_DEPENDENCY)
148
+ return state.buffer.subarray(start, state.start)
149
+ }
150
+
151
+ core.hints = function (ptr) {
152
+ const state = alloc()
153
+ const start = state.start
154
+ UINT.encode(state, TL_DATA)
155
+ UINT.encode(state, ptr)
156
+ UINT.encode(state, DATA_HINTS)
157
+ return state.buffer.subarray(start, state.start)
158
+ }
159
+
160
+ core.block = function (ptr, index) {
161
+ const state = alloc()
162
+ const start = state.start
163
+ UINT.encode(state, TL_DATA)
164
+ UINT.encode(state, ptr)
165
+ UINT.encode(state, DATA_BLOCK)
166
+ UINT.encode(state, index)
167
+ return state.buffer.subarray(start, state.start)
168
+ }
169
+
170
+ core.tree = function (ptr, index) {
171
+ const state = alloc()
172
+ const start = state.start
173
+ UINT.encode(state, TL_DATA)
174
+ UINT.encode(state, ptr)
175
+ UINT.encode(state, DATA_TREE)
176
+ UINT.encode(state, index)
177
+ return state.buffer.subarray(start, state.start)
178
+ }
179
+
180
+ core.bitfield = function (ptr, index, type) {
181
+ const state = alloc()
182
+ const start = state.start
183
+ UINT.encode(state, TL_DATA)
184
+ UINT.encode(state, ptr)
185
+ UINT.encode(state, DATA_BITFIELD)
186
+ UINT.encode(state, index)
187
+ UINT.encode(state, type)
188
+ return state.buffer.subarray(start, state.start)
189
+ }
190
+
191
+ core.userData = function (ptr, key) {
192
+ const state = alloc()
193
+ const start = state.start
194
+ UINT.encode(state, TL_DATA)
195
+ UINT.encode(state, ptr)
196
+ UINT.encode(state, DATA_USER_DATA)
197
+ STRING.encode(state, key)
198
+ return state.buffer.subarray(start, state.start)
199
+ }
200
+
201
+ core.userDataEnd = function (ptr) {
202
+ const state = alloc()
203
+ const start = state.start
204
+ UINT.encode(state, TL_DATA)
205
+ UINT.encode(state, ptr)
206
+ UINT.encode(state, DATA_USER_DATA + 1)
207
+ return state.buffer.subarray(start, state.start)
208
+ }
209
+
210
+ core.blockIndex = function (buffer) {
211
+ const state = { buffer, start: 0, end: buffer.byteLength }
212
+ UINT.decode(state) // ns
213
+ UINT.decode(state) // ptr
214
+ UINT.decode(state) // type
215
+ return UINT.decode(state)
216
+ }
217
+
218
+ core.bitfieldIndexAndType = function (buffer) {
219
+ const state = { buffer, start: 0, end: buffer.byteLength }
220
+ UINT.decode(state) // ns
221
+ UINT.decode(state) // ptr
222
+ UINT.decode(state) // type
223
+ return [UINT.decode(state), UINT.decode(state)]
224
+ }
225
+
226
+ core.userDataKey = function (buffer) {
227
+ const state = { buffer, start: 0, end: buffer.byteLength }
228
+ UINT.decode(state) // ns
229
+ UINT.decode(state) // ptr
230
+ UINT.decode(state) // type
231
+ return STRING.decode(state)
232
+ }
233
+
234
+ module.exports = { store, core }
235
+
236
+ function alloc () {
237
+ if (slab.buffer.byteLength - slab.start < 4096) {
238
+ slab.buffer = b4a.allocUnsafe(slab.buffer.byteLength)
239
+ slab.start = 0
240
+ }
241
+ return slab
242
+ }
package/lib/streams.js ADDED
@@ -0,0 +1,112 @@
1
+ const BlockDependencyStream = require('./block-dependency-stream.js')
2
+ const { core, store } = require('./keys.js')
3
+ const schema = require('../spec/hyperschema')
4
+
5
+ const CORESTORE_CORE = schema.getEncoding('@corestore/core')
6
+ const CORE_TREE_NODE = schema.getEncoding('@core/tree-node')
7
+
8
+ module.exports = {
9
+ createBlockStream,
10
+ createBitfieldStream,
11
+ createUserDataStream,
12
+ createCoreStream,
13
+ createAliasStream,
14
+ createTreeNodeStream
15
+ }
16
+
17
+ function createCoreStream (db, view) {
18
+ const start = store.coreStart()
19
+ const end = store.coreEnd()
20
+
21
+ const ite = view.iterator(db, start, end, false)
22
+
23
+ ite._readableState.map = mapCore
24
+ return ite
25
+ }
26
+
27
+ function createAliasStream (db, view, namespace) {
28
+ const start = store.coreByAliasStart(namespace)
29
+ const end = store.coreByAliasEnd(namespace)
30
+
31
+ const ite = view.iterator(db, start, end, false)
32
+
33
+ ite._readableState.map = mapAlias
34
+ return ite
35
+ }
36
+
37
+ function createBlockIterator (ptr, db, view, start, end, reverse) {
38
+ if (ptr.dependencies.length > 0) {
39
+ return new BlockDependencyStream(ptr, db, view, start, end, reverse)
40
+ }
41
+
42
+ const s = core.block(ptr.dataPointer, start)
43
+ const e = core.block(ptr.dataPointer, end === -1 ? Infinity : end)
44
+ return view.iterator(db, s, e, reverse)
45
+ }
46
+
47
+ function createBlockStream (ptr, db, view, { gt = -1, gte = gt + 1, lte = -1, lt = lte === -1 ? -1 : lte + 1, reverse = false } = {}) {
48
+ const ite = createBlockIterator(ptr, db, view, gte, lt, reverse)
49
+
50
+ ite._readableState.map = mapBlock
51
+ return ite
52
+ }
53
+
54
+ function createBitfieldStream (ptr, db, view, { gt = -1, gte = gt + 1, lte = -1, lt = lte === -1 ? -1 : lte + 1, reverse = false } = {}) {
55
+ const s = core.bitfield(ptr.dataPointer, gte, 0)
56
+ const e = core.bitfield(ptr.dataPointer, lt === -1 ? Infinity : lt, 0)
57
+ const ite = view.iterator(db, s, e, false)
58
+
59
+ ite._readableState.map = mapBitfield
60
+ return ite
61
+ }
62
+
63
+ // NOTE: this does not do dependency lookups atm
64
+ function createTreeNodeStream (ptr, db, view, { gt = -1, gte = gt + 1, lte = -1, lt = lte === -1 ? -1 : lte + 1, reverse = false } = {}) {
65
+ const s = core.tree(ptr.dataPointer, gte, 0)
66
+ const e = core.tree(ptr.dataPointer, lt === -1 ? Infinity : lt, 0)
67
+ const ite = view.iterator(db, s, e, false)
68
+
69
+ ite._readableState.map = mapTreeNode
70
+ return ite
71
+ }
72
+
73
+ function createUserDataStream (ptr, db, view, { gt = null, gte = '', lte = null, lt = null, reverse = false } = {}) {
74
+ if (gt !== null || lte !== null) throw new Error('gt and lte not yet supported for user data streams')
75
+
76
+ const s = core.userData(ptr.dataPointer, gte)
77
+ const e = lt === null ? core.userDataEnd(ptr.dataPointer) : core.userData(ptr.dataPointer, lt)
78
+ const ite = view.iterator(db, s, e, false)
79
+
80
+ ite._readableState.map = mapUserData
81
+ return ite
82
+ }
83
+
84
+ function mapBitfield (data) {
85
+ const [index, type] = core.bitfieldIndexAndType(data.key)
86
+ if (type !== 0) return null // ignore for now
87
+ return { index, page: data.value }
88
+ }
89
+
90
+ function mapUserData (data) {
91
+ const key = core.userDataKey(data.key)
92
+ return { key, value: data.value }
93
+ }
94
+
95
+ function mapCore (data) {
96
+ const discoveryKey = store.discoveryKey(data.key)
97
+ const core = CORESTORE_CORE.decode({ start: 0, end: data.value.byteLength, buffer: data.value })
98
+ return { discoveryKey, core }
99
+ }
100
+
101
+ function mapAlias (data) {
102
+ const alias = store.alias(data.key)
103
+ return { alias, discoveryKey: data.value }
104
+ }
105
+
106
+ function mapBlock (data) {
107
+ return { index: core.blockIndex(data.key), value: data.value }
108
+ }
109
+
110
+ function mapTreeNode (data) {
111
+ return CORE_TREE_NODE.decode({ start: 0, end: data.value.byteLength, buffer: data.value })
112
+ }