Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 73bae74

Browse files
authored
fix: do not strip prefixes for MountDatastores (#82)
If you have a mount datastore: ```js const d = new MountDatastore([{ datastore: foo, prefix: new Key('/bar') }]) ``` `d.put(new Key('/bar/baz'), val)` results in `foo.put(new Key('/baz'), val)`. This PR changes the default behaviour to `foo.put(new Key('/bar/baz'), val)`. If you need the old behaviour, use a `KeyTransformDatastore` to strip the prefix - see [stripPrefixDatastore](https://github.com/ipfs/js-datastore-core/blob/master/test/mount.spec.js#L17) in the MountDatastore tests for an example. BREAKING CHANGE: key prefixes are no longer stripped by MountDatastore
1 parent 06c2ecb commit 73bae74

File tree

8 files changed

+104
-169
lines changed

8 files changed

+104
-169
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
- Keytransform: [`src/keytransform`](src/keytransform.js)
3030
- Sharding: [`src/sharding`](src/sharding.js)
3131
- Tiered: [`src/tiered`](src/tirered.js)
32-
- Namespace: [`src/tiered`](src/namespace.js)
32+
- Namespace: [`src/namespace`](src/namespace.js)
3333

3434
## Install
3535

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"homepage": "https://github.com/ipfs/js-datastore-core#readme",
8585
"devDependencies": {
8686
"@types/debug": "^4.1.5",
87-
"aegir": "^35.0.2",
87+
"aegir": "^36.1.3",
8888
"interface-datastore-tests": "^2.0.3",
8989
"it-all": "^1.0.4",
9090
"rimraf": "^3.0.2",

src/keytransform.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,33 @@ export class KeyTransformDatastore extends BaseDatastore {
169169
* @param {Options} [options]
170170
*/
171171
query (q, options) {
172-
return map(this.child.query(q, options), ({ key, value }) => {
172+
/** @type {Query} */
173+
const query = {
174+
...q
175+
}
176+
177+
query.filters = (query.filters || []).map(filter => {
178+
return ({ key, value }) => filter({ key: this.transform.convert(key), value })
179+
})
180+
181+
const { prefix } = q
182+
if (prefix != null && prefix !== '/') {
183+
delete query.prefix
184+
query.filters.push(({ key }) => {
185+
return this.transform.invert(key).toString().startsWith(prefix)
186+
})
187+
}
188+
189+
if (query.orders) {
190+
query.orders = query.orders.map(order => {
191+
return (a, b) => order(
192+
{ key: this.transform.invert(a.key), value: a.value },
193+
{ key: this.transform.invert(b.key), value: b.value }
194+
)
195+
})
196+
}
197+
198+
return map(this.child.query(query, options), ({ key, value }) => {
173199
return {
174200
key: this.transform.invert(key),
175201
value
@@ -182,7 +208,32 @@ export class KeyTransformDatastore extends BaseDatastore {
182208
* @param {Options} [options]
183209
*/
184210
queryKeys (q, options) {
185-
return map(this.child.queryKeys(q, options), key => {
211+
const query = {
212+
...q
213+
}
214+
215+
query.filters = (query.filters || []).map(filter => {
216+
return (key) => filter(this.transform.convert(key))
217+
})
218+
219+
const { prefix } = q
220+
if (prefix != null && prefix !== '/') {
221+
delete query.prefix
222+
query.filters.push((key) => {
223+
return this.transform.invert(key).toString().startsWith(prefix)
224+
})
225+
}
226+
227+
if (query.orders) {
228+
query.orders = query.orders.map(order => {
229+
return (a, b) => order(
230+
this.transform.invert(a),
231+
this.transform.invert(b)
232+
)
233+
})
234+
}
235+
236+
return map(this.child.queryKeys(query, options), key => {
186237
return this.transform.invert(key)
187238
})
188239
}

src/mount.js

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ import filter from 'it-filter'
22
import take from 'it-take'
33
import merge from 'it-merge'
44
import { BaseDatastore } from './base.js'
5-
import { KeyTransformDatastore } from './keytransform.js'
65
import * as Errors from './errors.js'
76
import {
8-
sortAll,
9-
replaceStartWith
7+
sortAll
108
} from './utils.js'
11-
import { Key } from 'interface-datastore/key'
129

1310
/**
1411
* @typedef {import('interface-datastore').Datastore} Datastore
12+
* @typedef {import('interface-datastore').Key} Key
1513
* @typedef {import('interface-datastore').Options} Options
1614
* @typedef {import('interface-datastore').Batch} Batch
1715
* @typedef {import('interface-datastore').Query} Query
@@ -44,16 +42,14 @@ export class MountDatastore extends BaseDatastore {
4442
*
4543
* @private
4644
* @param {Key} key
47-
* @returns {{datastore: Datastore, mountpoint: Key, rest: Key} | undefined}
45+
* @returns {{datastore: Datastore, mountpoint: Key} | undefined}
4846
*/
4947
_lookup (key) {
5048
for (const mount of this.mounts) {
5149
if (mount.prefix.toString() === key.toString() || mount.prefix.isAncestorOf(key)) {
52-
const s = replaceStartWith(key.toString(), mount.prefix.toString())
5350
return {
5451
datastore: mount.datastore,
55-
mountpoint: mount.prefix,
56-
rest: new Key(s)
52+
mountpoint: mount.prefix
5753
}
5854
}
5955
}
@@ -70,7 +66,7 @@ export class MountDatastore extends BaseDatastore {
7066
throw Errors.dbWriteFailedError(new Error('No datastore mounted for this key'))
7167
}
7268

73-
return match.datastore.put(match.rest, value, options)
69+
return match.datastore.put(key, value, options)
7470
}
7571

7672
/**
@@ -82,7 +78,7 @@ export class MountDatastore extends BaseDatastore {
8278
if (match == null) {
8379
throw Errors.notFoundError(new Error('No datastore mounted for this key'))
8480
}
85-
return match.datastore.get(match.rest, options)
81+
return match.datastore.get(key, options)
8682
}
8783

8884
/**
@@ -94,7 +90,7 @@ export class MountDatastore extends BaseDatastore {
9490
if (match == null) {
9591
return Promise.resolve(false)
9692
}
97-
return match.datastore.has(match.rest, options)
93+
return match.datastore.has(key, options)
9894
}
9995

10096
/**
@@ -107,7 +103,7 @@ export class MountDatastore extends BaseDatastore {
107103
throw Errors.dbDeleteFailedError(new Error('No datastore mounted for this key'))
108104
}
109105

110-
return match.datastore.delete(match.rest, options)
106+
return match.datastore.delete(key, options)
111107
}
112108

113109
async close () {
@@ -137,19 +133,18 @@ export class MountDatastore extends BaseDatastore {
137133
}
138134

139135
return {
140-
batch: batchMounts[m],
141-
rest: match.rest
136+
batch: batchMounts[m]
142137
}
143138
}
144139

145140
return {
146141
put: (key, value) => {
147142
const match = lookup(key)
148-
match.batch.put(match.rest, value)
143+
match.batch.put(key, value)
149144
},
150145
delete: (key) => {
151146
const match = lookup(key)
152-
match.batch.delete(match.rest)
147+
match.batch.delete(key)
153148
},
154149
commit: async (options) => {
155150
await Promise.all(Object.keys(batchMounts).map(p => batchMounts[p].commit(options)))
@@ -163,22 +158,8 @@ export class MountDatastore extends BaseDatastore {
163158
*/
164159
query (q, options) {
165160
const qs = this.mounts.map(m => {
166-
const ks = new KeyTransformDatastore(m.datastore, {
167-
convert: (key) => {
168-
throw new Error('should never be called')
169-
},
170-
invert: (key) => {
171-
return m.prefix.child(key)
172-
}
173-
})
174-
175-
let prefix
176-
if (q.prefix != null) {
177-
prefix = replaceStartWith(q.prefix, m.prefix.toString())
178-
}
179-
180-
return ks.query({
181-
prefix: prefix,
161+
return m.datastore.query({
162+
prefix: q.prefix,
182163
filters: q.filters
183164
}, options)
184165
})
@@ -201,22 +182,8 @@ export class MountDatastore extends BaseDatastore {
201182
*/
202183
queryKeys (q, options) {
203184
const qs = this.mounts.map(m => {
204-
const ks = new KeyTransformDatastore(m.datastore, {
205-
convert: (key) => {
206-
throw new Error('should never be called')
207-
},
208-
invert: (key) => {
209-
return m.prefix.child(key)
210-
}
211-
})
212-
213-
let prefix
214-
if (q.prefix != null) {
215-
prefix = replaceStartWith(q.prefix, m.prefix.toString())
216-
}
217-
218-
return ks.queryKeys({
219-
prefix: prefix,
185+
return m.datastore.queryKeys({
186+
prefix: q.prefix,
220187
filters: q.filters
221188
}, options)
222189
})

src/namespace.js

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { KeyTransformDatastore } from './keytransform.js'
1616
* For example, if the prefix is `new Key(/hello)` a call
1717
* to `store.put(new Key('/world'), mydata)` would store the data under
1818
* `/hello/world`.
19-
*
2019
*/
2120
export class NamespaceDatastore extends KeyTransformDatastore {
2221
/**
@@ -40,33 +39,5 @@ export class NamespaceDatastore extends KeyTransformDatastore {
4039
return new Key(key.toString().slice(prefix.toString().length), false)
4140
}
4241
})
43-
44-
this.prefix = prefix
45-
}
46-
47-
/**
48-
* @param {Query} q
49-
* @param {Options} [options]
50-
*/
51-
query (q, options) {
52-
if (q.prefix && this.prefix.toString() !== '/') {
53-
return super.query(Object.assign({}, q, {
54-
prefix: this.prefix.child(new Key(q.prefix)).toString()
55-
}))
56-
}
57-
return super.query(q, options)
58-
}
59-
60-
/**
61-
* @param {KeyQuery} q
62-
* @param {Options} [options]
63-
*/
64-
queryKeys (q, options) {
65-
if (q.prefix && this.prefix.toString() !== '/') {
66-
return super.queryKeys(Object.assign({}, q, {
67-
prefix: this.prefix.child(new Key(q.prefix)).toString()
68-
}))
69-
}
70-
return super.queryKeys(q, options)
7142
}
7243
}

src/sharding.js

Lines changed: 8 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -208,57 +208,15 @@ export class ShardingDatastore extends BaseDatastore {
208208
* @param {Options} [options]
209209
*/
210210
query (q, options) {
211+
/** @type {Query} */
211212
const tq = {
212-
offset: q.offset,
213-
limit: q.limit,
214-
/** @type {QueryOrder[]} */
215-
orders: [],
216-
/** @type {QueryFilter[]} */
213+
...q,
217214
filters: [
218215
/** @type {QueryFilter} */
219-
e => e.key.toString() !== shardKey.toString(),
216+
({ key }) => key.toString() !== shardKey.toString(),
220217
/** @type {QueryFilter} */
221-
e => e.key.toString() !== shardReadmeKey.toString()
222-
]
223-
}
224-
225-
const { prefix } = q
226-
if (prefix != null) {
227-
tq.filters.push((e) => {
228-
return this._invertKey(e.key).toString().startsWith(prefix)
229-
})
230-
}
231-
232-
if (q.filters != null) {
233-
const filters = q.filters.map(f => {
234-
/** @type {QueryFilter} */
235-
const filter = ({ key, value }) => {
236-
return f({
237-
key: this._invertKey(key),
238-
value
239-
})
240-
}
241-
242-
return filter
243-
})
244-
tq.filters = tq.filters.concat(filters)
245-
}
246-
247-
if (q.orders != null) {
248-
tq.orders = q.orders.map(o => {
249-
/** @type {QueryOrder} */
250-
const order = (a, b) => {
251-
return o({
252-
key: this._invertKey(a.key),
253-
value: a.value
254-
}, {
255-
key: this._invertKey(b.key),
256-
value: b.value
257-
})
258-
}
259-
260-
return order
261-
})
218+
({ key }) => key.toString() !== shardReadmeKey.toString()
219+
].concat(q.filters || [])
262220
}
263221

264222
return this.child.query(tq, options)
@@ -269,46 +227,15 @@ export class ShardingDatastore extends BaseDatastore {
269227
* @param {Options} [options]
270228
*/
271229
queryKeys (q, options) {
230+
/** @type {KeyQuery} */
272231
const tq = {
273-
offset: q.offset,
274-
limit: q.limit,
275-
/** @type {KeyQueryOrder[]} */
276-
orders: [],
277-
/** @type {KeyQueryFilter[]} */
232+
...q,
278233
filters: [
279234
/** @type {KeyQueryFilter} */
280235
key => key.toString() !== shardKey.toString(),
281236
/** @type {KeyQueryFilter} */
282237
key => key.toString() !== shardReadmeKey.toString()
283-
]
284-
}
285-
286-
const { prefix } = q
287-
if (prefix != null) {
288-
tq.filters.push((key) => {
289-
return this._invertKey(key).toString().startsWith(prefix)
290-
})
291-
}
292-
293-
if (q.filters != null) {
294-
const filters = q.filters.map(f => {
295-
/** @type {KeyQueryFilter} */
296-
const filter = (key) => {
297-
return f(this._invertKey(key))
298-
}
299-
300-
return filter
301-
})
302-
tq.filters = tq.filters.concat(filters)
303-
}
304-
305-
if (q.orders != null) {
306-
tq.orders = q.orders.map(o => {
307-
/** @type {KeyQueryOrder} */
308-
const order = (a, b) => o(this._invertKey(a), this._invertKey(b))
309-
310-
return order
311-
})
238+
].concat(q.filters || [])
312239
}
313240

314241
return this.child.queryKeys(tq, options)

0 commit comments

Comments
 (0)