Skip to content

feat: add multi database backend supports #49

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Options object:

| Param | Type [= default] | Description |
| --------------- | ------------------ | --------------------------------------------------------------------- |
| `backend` | string = "idb" | Defults to IndexedDb Store.This is the only built-in backend currently |
| `wipe` | boolean = false | Delete the database and start with an empty filesystem |
| `url` | string = undefined | Let `readFile` requests fall back to an HTTP request to this base URL |
| `urlauto` | boolean = false | Fall back to HTTP for every read of a missing file, even if unbacked |
Expand Down Expand Up @@ -190,6 +191,43 @@ Returns the size of a file or directory in bytes.

All the same functions as above, but instead of passing a callback they return a promise.

## Storage Backend

You can create your own storage backend if the default idb storage backend does not meet your needs.

You should implement these methods in your backend:

```ts
export default class YourBackend {
// new FS(name, options?)
constructor(name: string, options?) {}
// save the superblock to your backend
async saveSuperblock(superblock: Map) {}
// load the superblock from your backend
async loadSuperblock(): Map {}
async readFile(inode: string): Buffer {}
async writeFile(inode: string, data: Uint8Array) {}
// remove inode file
async unlink(inode: string) {}
// clean all data
async wipe()
// close backend
async close()
}
```

See the `errors.js` for the error code to raise.

Then register it to the `FS`

```ts
import FS from '@isomorphic-git/lightning-fs'
FS.register('YourBackend', YourBackend)

// now you can use your backend:
const fs = new FS('your-fs-name', {backend: 'YourBackend', ...yourBackendOptions})
```

## License

MIT
4 changes: 2 additions & 2 deletions src/IdbBackend.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const idb = require("@isomorphic-git/idb-keyval");

module.exports = class IdbBackend {
constructor(dbname, storename) {
constructor(dbname, options) {
this._database = dbname;
this._storename = storename;
this._storename = (options && options.storename) || (dbname + "_files");
this._store = new idb.Store(this._database, this._storename);
}
saveSuperblock(superblock) {
Expand Down
35 changes: 24 additions & 11 deletions src/PromisifiedFS.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ function cleanParams2(oldFilepath, newFilepath) {
}

module.exports = class PromisifiedFS {
static register(name, backend) {
if (!this.prototype.backends) this.prototype.backends = {};
this.prototype.backends[name] = backend;
}

static unregister(name) {
if (this.prototype.backends)
return delete this.prototype.backends[name];
}

constructor(name, options) {
this.init = this.init.bind(this)
this.readFile = this._wrap(this.readFile, false)
Expand Down Expand Up @@ -69,19 +79,22 @@ module.exports = class PromisifiedFS {
this._initPromise = this._init(...args)
return this._initPromise
}
async _init (name, {
wipe,
url,
urlauto,
fileDbName = name,
fileStoreName = name + "_files",
lockDbName = name + "_lock",
lockStoreName = name + "_lock",
} = {}) {
async _init (name, options = {}) {
await this._gracefulShutdown()
const {
wipe,
url,
urlauto,
backend,
fileDbName = name,
fileStoreName = name + "_files",
lockDbName = name + "_lock",
lockStoreName = name + "_lock",
} = options
this._name = name
this._idb = new IdbBackend(fileDbName, fileStoreName);
this._mutex = navigator.locks ? new Mutex2(name) : new Mutex(lockDbName, lockStoreName);
let Backend = (this.backends && this.backends[backend]) || IdbBackend;
this._idb = new Backend(fileDbName, {...options, storename: fileStoreName});
this._mutex = typeof navigator !== 'undefined' && navigator.locks ? new Mutex2(name) : new Mutex(lockDbName, lockStoreName);
this._cache = new CacheFS(name);
this._opts = { wipe, url };
this._needsWipe = !!wipe;
Expand Down
Loading