-
-
Notifications
You must be signed in to change notification settings - Fork 1
Decide on additionalMethods format #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
One thing the manifest currently can't cover is "static" additional methods like |
To use the manifest in |
Combined with function myIndexPlugin (db) {
db.supports.additionalMethods.createIndex = {
args: [{ type: 'key' }]
}
db.createIndex = function (prefix) {
// prefix is encoded
}
return db
}
const factory = compose()
.use(leveldown)
.use(myIndexPlugin)
.use(encode, { keyEncoding: charwise })
.use(levelup)
const db = factory()
db.createIndex(['my_indexes', 'foo']) |
The api looks very nice I think. |
A more complex example, where function getAllPlugin (db) {
db.supports.additionalMethods.getAll = {
args: ['options?', 'callback'],
yields: ['entry'] // TODO: type depends on options
}
db.getAll = function (options, callback) {
const it = db.iterator(options)
concat(it, function (err, entries) {
if (err) return callback(err)
if (options.keys === false) {
entries = entries.map(e => e.value)
} else if (options.values === false) {
entries = entries.map(e => e.key)
}
callback(null, entries)
})
}
return db
}
const factory = compose()
.use(leveldown)
.use(getAllPlugin)
.use(encode, { valueEncoding: 'json' })
.use(levelup)
const db = factory()
const entries = await db.getAll({ lt: 18 })
const values = await db.getAll({ lt: 18, keys: false }) |
Perhaps we should simply stop using that pattern ( // Yields entries, values or keys
db._internalCreateReadStream = function (options, ..) {
if (options.keys === false) // ..
}
// Always yields entries
db.createReadStream = function (..) {
return this._internalCreateReadStream(..)
}
// Always yields values
db.createValueStream = function (..) {
return this._internalCreateReadStream({ keys: false })
} |
Although if you swap the layers: .use(encode, { valueEncoding: 'json' })
.use(getAllPlugin) Then the problem disappears, because the |
If we want dynamic return types like described above, then the manifest would also have to be dynamic: {
args: ['options?', 'callback'],
yields (options) {
if (options.keys === false) return ['value']
if (options.values === false) return ['key']
return ['entry']
}
} Which is not impossible, but...: Click to expand encoding-down examplefunction EncodingDown (db, opts) {
AbstractLevelDOWN.call(this, db.supports)
// ..
Object.keys(this.supports.additionalMethods).forEach((m) => {
var signature = this.supports.additionalMethods[m]
this[m] = function () {
var i = Math.min(arguments.length, signature.args.length)
var args = []
var opts
var callback
while (i--) {
if (signature.args[i] === 'callback') {
callback = arguments[i]
} else if (signature.args[i] === 'options' && !opts && isOptions(arguments[i])) {
opts = arguments[i]
args.unshift(this.codec.encodeLtgt(opts))
} else if (signature.args[i] === 'key') {
args.unshift(this.codec.encodeKey(arguments[i], opts))
} else {
args.unshift(arguments[i])
}
}
const resultType = signature.yields(opts)
const decode = (result, type) => {
if (type === 'key') {
return this.codec.decodeKey(result, opts)
} else if (type === 'value') {
return this.codec.decodeValue(result, opts)
} else if (type === 'entry') {
return {
key: this.codec.decodeKey(result.key, opts),
value: this.codec.decodeValue(result.value, opts)
}
} else {
return result
}
}
args.push(function (err, result) {
if (err) return callback(err)
if (Array.isArray(resultType)) {
result = result.map((r, i) => decode(r, resultType[i]))
} else {
result = decode(result, resultType)
}
callback(null, result)
})
return this.db[m].apply(this.db, args)
}
})
} I don't want to go there. For situations like this we should instead write some abstraction like hooks or perhaps |
@ralphtheninja TLDR, I don't want args or return types in the manifest for now. And maybe never. I'll update Level/encoding-down#93 to simply do |
It's a fine line when to stop engineering stuff. |
Uh oh!
There was an error while loading. Please reload this page.
Initially we can do:
Which is enough to start using that in
deferred-leveldown
(Level/deferred-leveldown#35) andlevel-packager
levelup
. @ralphtheninja WDYT?Later we can add function signature info. I propose to stick with boolean properties, so that we can describe multiple signatures (e.g. callbacks and promises):
With that in place, a db wrapper could do things like:
Even later, we can add a return type to the manifest. Mainly for streams. Not sure what that should look like. Perhaps:
The text was updated successfully, but these errors were encountered: