From 1ba0b69447694541f7743de1a4ea0f697b1d7498 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sun, 6 Mar 2022 15:29:37 +0100 Subject: [PATCH] Create location directory recursively (#6) --- README.md | 2 +- index.js | 10 +++++++++- test/mkdir-test.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/mkdir-test.js diff --git a/README.md b/README.md index 51d68a9d..296de128 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ An `abstract-level` and thus `classic-level` database is at its core a [key-valu ### `db = new ClassicLevel(location[, options])` -Create a database or open an existing database. The `location` argument must be a directory path (relative or absolute) where LevelDB will store its files. The optional `options` object may contain: +Create a database or open an existing database. The `location` argument must be a directory path (relative or absolute) where LevelDB will store its files. If the directory does not yet exist (and `options.createIfMissing` is true) it will be created recursively. The optional `options` object may contain: - `keyEncoding` (string or object, default `'utf8'`): encoding to use for keys - `valueEncoding` (string or object, default `'utf8'`): encoding to use for values. diff --git a/index.js b/index.js index fe81cda3..c39264af 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ const { AbstractLevel } = require('abstract-level') const ModuleError = require('module-error') const { fromCallback } = require('catering') +const fs = require('fs') const binding = require('./binding') const { ChainedBatch } = require('./chained-batch') const { Iterator } = require('./iterator') @@ -47,7 +48,14 @@ class ClassicLevel extends AbstractLevel { } _open (options, callback) { - binding.db_open(this[kContext], this[kLocation], options, callback) + if (options.createIfMissing) { + fs.mkdir(this[kLocation], { recursive: true }, (err) => { + if (err) return callback(err) + binding.db_open(this[kContext], this[kLocation], options, callback) + }) + } else { + binding.db_open(this[kContext], this[kLocation], options, callback) + } } _close (callback) { diff --git a/test/mkdir-test.js b/test/mkdir-test.js new file mode 100644 index 00000000..2592969f --- /dev/null +++ b/test/mkdir-test.js @@ -0,0 +1,35 @@ +'use strict' + +const test = require('tape') +const tempy = require('tempy') +const path = require('path') +const fs = require('fs') +const { ClassicLevel } = require('..') + +test('creates location directory recursively', async function (t) { + const location = path.join(tempy.directory(), 'beep', 'boop') + const db = new ClassicLevel(location) + + t.is(fs.existsSync(location), false) + await db.open() + t.is(fs.existsSync(location), true) +}) + +test('does not create location directory recursively if createIfMissing is false', async function (t) { + t.plan(3) + + const location = path.join(tempy.directory(), 'beep', 'boop') + const db = new ClassicLevel(location, { createIfMissing: false }) + + try { + await db.open() + } catch (err) { + t.is(err.code, 'LEVEL_DATABASE_NOT_OPEN') + + // Error message is inconsistent between platforms so not checked + t.ok(err.cause) + + // On Windows, LevelDB itself creates the directory (technically a bug) + t.is(fs.existsSync(location), process.platform === 'win32') + } +})