Level / abstract-level

Abstract class for a lexicographically sorted key-value database.
MIT License
123 stars 8 forks source link

Decide on naming of modules #6

Closed vweevers closed 2 years ago

vweevers commented 2 years ago

With abstract-level, there is no "down" or "up" anymore. For example, memdown does not have to be wrapped with levelup. This means level-mem could just do module.exports = require('memdown') to export (largely) the same functionality as before. Which begs the question, should we:

  1. Keep memdown (as an abstract-level database); deprecate level-mem (as a levelup db)
  2. Deprecate memdown (as an abstract-leveldown database); move code to level-mem (as an abstract-level db)
  3. Deprecate both and create a new memory-level package (as well as leveldb-level, indexeddb-level, etc)

@Level/core thoughts?

vweevers commented 2 years ago

Option 3, where *-level naming means a database and level-* means a plugin, could look like:

Old module(s) New module
abstract-leveldown abstract-level
memdown / level-mem memory-level
leveldown leveldb-level
level-js indexeddb-level
level level1
rocksdb / level-rocksdb rocks-level
level-party party-level
multileveldown protobuf-level? peer-level?
subleveldown ?
level-test can be done differently
encoding-down n/a
deferred-leveldown n/a

1 Would export leveldb-level in Node and indexeddb-level in browsers.

juliangruber commented 2 years ago
  1. Keep memdown (as an abstract-level database); deprecate level-mem (as a levelup db)

Not really an option to me, when it doesn't make sense for everything to be called down.

2. Deprecate memdown (as an abstract-leveldown database); move code to level-mem (as an abstract-level db)

I think this is the best for consumers, but I wonder how we would do that. If we moved the code, we'd lose history, if we renamed the repos people might be confused.

3. Deprecate both and create a new memory-level package (as well as leveldb-level, indexeddb-level, etc)

Prefixes are nicer because they sort well 🤔

vweevers commented 2 years ago

I wonder how we would do that. If we moved the code, we'd lose history, if we renamed the repos people might be confused.

The best (but indeed not perfect) way would be to rename level-mem to e.g. level-mem-archived and fork memdown to level-mem (not through github). Because level-mem is a light wrapper with relatively little git(hub) history.

The potential confusion is why I'm leaning towards option 3 atm, because it makes a clean split. Consumers will have to replace their require() or import statements, which is not that bad especially if it results in a consistent set of names (which is a source of confusion today and not just because of "up" vs "down"; I'm looking at you level-js and rocksdb).

Prefixes are nicer because they sort well

It's a crowded namespace so we'd have to use an npm @level scope for that. A nice thing about the current "down" naming is that you can tell if a module is a store or a plugin; *-level naming preserves that (though again, not perfectly).

ralphtheninja commented 2 years ago

It will be confusing either way, so I'm also leaning towards option 3, to make it less confusing. New names also makes it easier to talk about different things.

vweevers commented 2 years ago

To increase the benefit of new names, we could take them a bit further. For example rave-level to replace level-party.

Flashing image ![schrute](https://user-images.githubusercontent.com/3055345/144708966-830bd124-443c-4153-a74a-f77db0d4125e.gif)

I considered scopes for a bit but it doesn't help because we'll still lack unique names for repos, code variables and human communication.

vweevers commented 2 years ago

As for subleveldown (though later on I want to merge that into abstract-level too) I think I'll go for prefix-level:

Click to expand ✖ sublevel (​https://www.npmjs.com/package/sublevel​) is unavailable ✖ level-sublevel (​https://www.npmjs.com/package/level-sublevel​) is unavailable ⚠ level-sub (​https://www.npmjs.com/package/level-sub​) is squatted ✖ sub-level (​https://www.npmjs.com/package/sub-level​) is unavailable ✔ sublevel-level is available ✔ namespaced-level is available ✔ namespace-level is available ✔ section-level is available ✔ sectioned-level is available ✔ prefix-level is available ✔ prefixed-level is available ✔ subspace-level is available ⚠ subspace (​https://www.npmjs.com/package/subspace​) is squatted ✔ spacelevel is available ✔ space-level is available
vweevers commented 2 years ago

Here's a complete set of names. Unique enough, available on npm, and able to distinguish between the name of the abstract-level implementation and its underlying store (e.g. LevelDB). I think this works rather well.

Old module(s) New module Named export
abstract-leveldown abstract-level AbstractLevel
leveldown classic-level ClassicLevel
memdown & level-mem memory-level MemoryLevel
level-js browser-level BrowserLevel
level level1 Level
rocksdb & level-rocksdb rocks-level RocksLevel
multileveldown many-level ManyLevel
level-party rave-level RaveLevel
subleveldown 2 prefix-level PrefixLevel

1 Will export classic-level in Node and browser-level in browsers. 2 Later decided to make sublevels builtin to abstract-level.

vweevers commented 2 years ago

To clarify that "Named export" column, I'm also thinking of using classes and named exports everywhere. E.g.:

const { ClassicLevel } = require('classic-level')
const { MemoryLevel } = require('memory-level')

const db = new ClassicLevel('./db', { valueEncoding: 'json' })
const db = new MemoryLevel({ valueEncoding: 'json' })

This makes TypeScript typings easier (cc @MeirionHughes) as the main class can only be called in one way (with new) which is simpler to type, and the type declarations can have additional exports (that don't necessarily have a counterpart in JS) like reusable interfaces. Without messing with default exports. E.g.:

export class ClassicLevel {
  // ...
}

export interface ReadOptions {
  fillCache?: boolean | undefined
}
vweevers commented 2 years ago

Closing as "resolved". If you have objections please raise them soon, because after landing https://github.com/Level/abstract-level/pull/8, I'll release abstract-level 1.0.0 and start to push new repo's - classic-level, memory-level and browser-level are code complete (what's left is mainly docs). I've been postponing benchmarks just because I'm not in the mood for that type of work (in my free time) and that's fine. I want to get this thing out the door. I'm not gonna do a prerelease round, going straight to 1.0.0 versions.