Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dbay

Package Overview
Dependencies
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dbay - npm Package Compare versions

Comparing version 0.100.3 to 0.101.0

lib/helpers.js

7

lib/errors.js

@@ -39,2 +39,9 @@ (function() {

this.Dbay_internal_error = class Dbay_internal_error extends this.Dbay_error {
constructor(ref, message) {
super(ref, message);
}
};
this.Dbay_schema_exists = class Dbay_schema_exists extends this.Dbay_error {

@@ -41,0 +48,0 @@ constructor(ref, schema) {

221

lib/main.js
(function() {
'use strict';
var CND, E, PATH, SQL, badge, debug, echo, guy, help, info, isa, new_bsqlt3_connection, rpr, type_of, types, urge, validate, validate_list_of, warn, whisper;
var CND, Dbay_query, Dbay_random, E, FS, H, PATH, SQL, badge, debug, echo, guy, help, info, isa, new_bsqlt3_connection, rpr, type_of, types, urge, validate, validate_list_of, warn, whisper;

@@ -29,2 +29,4 @@ //###########################################################################################################

FS = require('fs');
types = new (require('intertype')).Intertype();

@@ -42,14 +44,9 @@

//-----------------------------------------------------------------------------------------------------------
types.declare('dbay_urlsafe_word', {
tests: {
"@isa.nonempty_text x": function(x) {
return this.isa.nonempty_text(x);
},
"/^[a-zA-Z0-9_]+$/.test x": function(x) {
return /^[a-zA-Z0-9_]+$/.test(x);
}
}
});
H = require('./helpers');
//...........................................................................................................
({Dbay_random} = require('./random-mixin'));
({Dbay_query} = require('./query-mixin'));
//-----------------------------------------------------------------------------------------------------------

@@ -61,13 +58,7 @@ types.declare('constructor_cfg', {

},
"@isa_optional.boolean x.ram": function(x) {
return this.isa_optional.boolean(x.ram);
"@isa.nonempty_text x.path": function(x) {
return this.isa.nonempty_text(x.path);
},
"@isa_optional.nonempty_text x.url": function(x) {
return this.isa_optional.nonempty_text(x.url);
},
"@isa_optional.nonempty_text x.path": function(x) {
return this.isa_optional.nonempty_text(x.path);
},
"@isa_optional.dbay_urlsafe_word x.dbnick": function(x) {
return this.isa_optional.dbay_urlsafe_word(x.dbnick);
"@isa.boolean x.temporary": function(x) {
return this.isa.boolean(x.temporary);
}

@@ -78,61 +69,7 @@ }

//===========================================================================================================
this.Dbay_rnd = (function() {
class Dbay_rnd {
_initialize_prng() {
var clasz, delta, ref, ref1, ref2, ref3, seed;
clasz = this.constructor;
if (clasz._rnd_int_cfg != null) {
seed = (ref = (ref1 = clasz._rnd_int_cfg) != null ? ref1.seed : void 0) != null ? ref : 12.34;
delta = (ref2 = (ref3 = clasz._rnd_int_cfg) != null ? ref3.delta : void 0) != null ? ref2 : 1;
guy.props.def(this, '_rnd_int', {
enumerable: false,
value: CND.get_rnd_int(seed, delta)
});
} else {
guy.props.def(this, '_rnd_int', {
enumerable: false,
value: CND.random_integer.bind(CND)
});
}
return null;
}
//---------------------------------------------------------------------------------------------------------
_get_connection_url(dbnick = null) {
/* TAINT rename `dbnick` to `dbnick` */
/* Given an optional `dbnick`, return an object with the `dbnick` and the `url` for a new SQLite
connection. The url will look like `'file:your_name_here?mode=memory&cache=shared` so multiple
connections to the same RAM DB can be opened. When `dbnick` is not given, a random dbnick like
`_icql_6200294332` will be chosen (prefix `_icql_`, suffix ten decimal digits). For testing, setting
class property `@_rnd_int_cfg` can be used to obtain repeatable series of random names. */
var n10, url;
n10 = this._rnd_int(1_000_000_000, 9_999_999_999);
if (dbnick == null) {
dbnick = `_${n10}`;
}
url = `file:${dbnick}?mode=memory&cache=shared`;
return {url, dbnick};
}
};
//=========================================================================================================
// RANDOM NUMBER GENERATION
// seedable for testing purposes
//---------------------------------------------------------------------------------------------------------
/* To obtain a class with a seedable PRNG that emits repeatable sequences, define class property
`@_rnd_int_cfg: { seed, delta, }` where both seed and delta can be arbitrary finite numbers. **NOTE**
very small `delta` values (like 1e-10) may cause adjacent numbers to be close together or even repeat. To
use default values for both parameters, set `@_rnd_int_cfg: true`.*/
Dbay_rnd._rnd_int_cfg = null;
return Dbay_rnd;
}).call(this);
//===========================================================================================================
this.Dbay = (function() {
class Dbay extends this.Dbay_rnd {
class Dbay extends Dbay_query(Dbay_random()) {
//---------------------------------------------------------------------------------------------------------
static cast_sqlt_cfg(self) {
/* Produce a configuration object for `better-sqlite3` from `self.cfg`. */
var R;

@@ -147,27 +84,19 @@ R = guy.obj.pluck_with_fallback(self.cfg, null, 'readonly', 'timeout');

static cast_constructor_cfg(self) {
var base, base1, dbnick, ref, url;
// debug '^344476^', self
// debug '^344476^', self.cfg
if ((self.cfg.ram === false) && (self.cfg.path == null)) {
throw new E.Dbay_cfg_error('^dba@1^', `missing argument \`path\`, got ${rpr(self.cfg)}`);
}
if ((base = self.cfg).ram == null) {
base.ram = self.cfg.path == null;
}
if ((!self.cfg.ram) && (self.cfg.path != null) && (self.cfg.dbnick != null)) {
throw new E.Dbay_cfg_error('^dba@1^', `only RAM DB can have both \`path\` and \`dbnick\`, got ${rpr(self.cfg)}`);
}
if (self.cfg.ram) {
({dbnick, url} = self._get_connection_url((ref = self.cfg.dbnick) != null ? ref : null));
if ((base1 = self.cfg).dbnick == null) {
base1.dbnick = dbnick;
var R, clasz, filename;
clasz = self.constructor;
R = self.cfg;
//.......................................................................................................
if (R.path != null) {
if (R.temporary == null) {
R.temporary = false;
}
self.cfg.url = url;
R.path = PATH.resolve(R.path);
} else {
self.cfg.url = null;
if (R.temporary == null) {
R.temporary = true;
}
filename = self._get_random_filename();
R.path = PATH.resolve(PATH.join(clasz.C.autolocation, filename));
}
// self.cfg = guy.obj.nullify_undefined self.cfg
self.sqlt_cfg = guy.lft.freeze(guy.obj.omit_nullish(this.cast_sqlt_cfg(self)));
self.cfg = guy.lft.freeze(guy.obj.omit_nullish(self.cfg));
return null;
return R;
}

@@ -177,6 +106,8 @@

static declare_types(self) {
// debug '^133^', self.cfg, Object.isFrozen self.cfg
this.cast_constructor_cfg(self);
/* called from constructor via `guy.cfg.configure_with_types()` */
self.cfg = this.cast_constructor_cfg(self);
self.sqlt_cfg = this.cast_sqlt_cfg(self);
self.cfg = guy.lft.freeze(guy.obj.omit_nullish(self.cfg));
self.sqlt_cfg = guy.lft.freeze(guy.obj.omit_nullish(self.sqlt_cfg));
self.types.validate.constructor_cfg(self.cfg);
// guy.props.def self, 'dba', { enumerable: false, value: self.cfg.dba, }
return null;

@@ -186,27 +117,74 @@ }

//---------------------------------------------------------------------------------------------------------
_new_bsqlt3_connection() {
var path_or_url;
path_or_url = this.cfg.ram ? this.cfg.url : this.cfg.path;
return new_bsqlt3_connection(path_or_url, this.sqlt_cfg);
}
//---------------------------------------------------------------------------------------------------------
constructor(cfg) {
super();
this._initialize_prng();
guy.cfg.configure_with_types(this, cfg, types);
guy.props.def(this, 'sqlt1', {
enumerable: false,
value: this._new_bsqlt3_connection()
});
guy.props.def(this, 'sqlt2', {
enumerable: false,
value: this._new_bsqlt3_connection()
});
this._register_schema('main', this.cfg.path, this.cfg.temporary);
//.......................................................................................................
if (!this.constructor._skip_sqlt) {
guy.props.def(this, 'sqlt1', {
enumerable: false,
value: this._new_bsqlt3_connection()
});
guy.props.def(this, 'sqlt2', {
enumerable: false,
value: this._new_bsqlt3_connection()
});
}
// @_compile_sql()
// @_create_sql_functions()
// @_create_db_structure()
guy.process.on_exit(() => {
return this.destroy();
});
return void 0;
}
//---------------------------------------------------------------------------------------------------------
_new_bsqlt3_connection() {
return new_bsqlt3_connection(this.cfg.path, this.sqlt_cfg);
}
//---------------------------------------------------------------------------------------------------------
_register_schema(schema, path, temporary) {
if (this._dbs == null) {
/* Register a schema and descriptional properties, especially whether DB file is to be removed on
process exit. */
guy.props.def(this, '_dbs', {
enumerable: false,
value: {}
});
}
this._dbs[schema] = {path, temporary};
return null;
}
//=========================================================================================================
// CLEANUP ON DEMAND, ON PROCESS EXIT
//---------------------------------------------------------------------------------------------------------
destroy() {
var d, error, ref, schema;
try {
/* To be called on progress exit or explicitly by client code. Removes all DB files marked 'temporary'
in `@_dbs`. */
this.sqlt1.close();
} catch (error1) {
error = error1;
warn('^dbay@1^', error.message);
}
try {
this.sqlt2.close();
} catch (error1) {
error = error1;
warn('^dbay@1^', error.message);
}
ref = this._dbs;
for (schema in ref) {
d = ref[schema];
if (d.temporary) {
H.unlink_file(d.path);
}
}
return null;
}
};

@@ -216,2 +194,3 @@

Dbay.C = guy.lft.freeze({
autolocation: H.autolocation,
defaults: {

@@ -225,5 +204,3 @@ constructor_cfg: {

overwrite: false,
ram: null,
path: null,
dbnick: null
path: null
}

@@ -230,0 +207,0 @@ }

{
"name": "dbay",
"version": "0.100.3",
"version": "0.101.0",
"description": "In-Process, In-Memory & File-Based Relational Data Processing with SQLite, BetterSQLite3",
"main": "lib/main.js",
"scripts": {
"build": "coffee --map -o lib -c src",
"test": "echo see 'https://github.com/loveencounterflow/hengist/tree/master/dev/dbay'",
"preinstall": "./build-sqlite3"
},
"repository": {

@@ -24,11 +29,6 @@ "type": "git",

"cnd": "9.2.2",
"guy": "^2.2.0",
"intertype": "7.6.7",
"temp": "^0.9.4"
},
"scripts": {
"build": "coffee --map -o lib -c src",
"test": "echo see 'https://github.com/loveencounterflow/hengist/tree/master/dev/dbay'",
"preinstall": "./build-sqlite3"
"exit-hook": "^2.2.1",
"guy": "^2.3.0",
"intertype": "7.6.7"
}
}
}

@@ -10,2 +10,5 @@

- [Takeaways](#takeaways)
- [SQLite is Fast](#sqlite-is-fast)
- [SQLite is Not Fast Except When It Is](#sqlite-is-not-fast-except-when-it-is)
- [Top Runners](#top-runners)

@@ -15,8 +18,81 @@ - [Upper League](#upper-league)

- [Deplorables](#deplorables)
- [To Do](#to-do)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
### Takeaways
#### SQLite is Fast
The (preliminary) benchmark results (see below; code found at
[in-memory-sql.benchmarks.coffee](https://github.com/loveencounterflow/hengist/blob/master/dev/in-memory-sql/src/in-memory-sql.benchmarks.coffee),
[in-memory-sql.benchmarks.js](https://github.com/loveencounterflow/hengist/blob/master/dev/in-memory-sql/lib/in-memory-sql.benchmarks.js))
demonstrate that
* **SQLite can do RDBMS stuff faster than some of its competitors** (notably: PostgreSQL);
* this is no doubt helped by the in-process nature of SQLite as opposed to the server/client architecture
of more traditional RDBMSes.
* **You can get top speed out of SQLite under NodeJS using
[`better-sqlite3`](https://github.com/JoshuaWise/better-sqlite3)**, provided that
* SQLite is **configured correctly** (recommended to always use `pragma journal_mode = WAL`), and
* **explicit transactions (below marked `*_tx`) are used** to bundle many small actions (here: SQL
`insert`s) into atomic commits.
#### SQLite is Not Fast Except When It Is
There are, confusingly, several 'operational modes' to run SQLite:
* **(1)** The **classical way** is of course to pass in a file system path that SQLite will use to open an
existing or create a new database file.
* **(2)** One can **open a DB situated on a RAM disk** (read: Linux `ramfs` or `tmpfs`; also **`sh`**ared
**`m`**emory). **Opening a DB file on a RAM disk has many advantages** over using any of they ways listed
under (3), below, since a RAM disk is just a file system, meaning the file can be accessed by all the
usual means.
* **(3)** Last but not least there are no less than *three* competing, *almost* equivalent ways to obtain an
**in-memory DB**:
* **(3.1)** One can pass in the special string [`':memory:'` to obtain a so-called *in-memory DB* (without
'shared cache')](https://www.sqlite.org/inmemorydb.html),
* **(3.2)** or an empty string `''` that opens [a *temporary DB* (again without 'shared
cache')](https://www.sqlite.org/inmemorydb.html#temp_db) (which is almost but not 100% the same thing as
an in-memory DB).
* **(3.3)** The third (and in theory preferable) way to open a DB that resides in RAM is using [a
connection URL like with
`file:xxx?mode=memory&cache=shared`](https://www.sqlite.org/sharedcache.html#inmemsharedcache) instead
of a plain filename; since such an in-memory DB is identified via a name, several connections to the
*same* in-memory DB may be made (albeit only from the same client process).
* Having more than one connection to the same DB is necessary to enable user-defined functions (UDFs) to
issue queries against the DB, but
* the downside is that shared connections lacks feature-parity with [WAL
mode](https://sqlite.org/wal.html) and that
* [the 'shared connection' feature is not loved by the SQLite
devs](https://sqlite.org/forum/info/871b9085849abd6e) (quoting drh: "It was a clever work-around [...]
shared-cache is considered a mistake and a misfeature").
If the above litany is confusing for you that's because it is. Why *three* distinct, non-obvious ways to
obtain an in-memory DB?—Other than "That's the accumulated results of over 20 years of development" there's
probably no very good answer.
However, after much experimenting, benchmarking and feture-testing, I feel confident to state that **you
should probably forget about using SQLite in-memory DBs as outlined in point (3)**, above. The only
exception to the rule would be when you wanted top performance (and who wouldn't), not worry about explicit
transactions, do not need data durability (i.e. when the DB may become disposable on process exit), and do
not plan on having to use more than a single connection (meaning you can not query data in that DB from
within UDFs). In that case, feel free to pass in an empty string or `':memory:'` as path; but otherwise:
**Always just use ordinary file system paths**. If you're on Linux, consider to use `/dev/shm` which is a
read-to-use `tmpfs`, or use something like `sudo mount -t tmpfs -o size=512m none /mnt/ramdisk` to obtain a
new RAM disk. On Linux systems that have a directory called `/dev/shm`, DBay will use that location to open
DB files when no explicit `path` is passed in, and fall back to `/tmp` when `/dev/shm` is not found. You'll
get to use [WAL mode](https://sqlite.org/wal.html) which is great because together with multiple connections
it enables user-defined functions that can concurrently query rows from the same DB they deliver values to.
What's more, benchmarks indicate that **what is slowing down work with an SQLite DB is not so much file
system access *per se*, it's the implicit transactions that wrap each and every statement** in a pair of
`begin transaction`, `commit` statements. **Curiously, slowdown-by-transaction is much more pronounced with
RAM disks as opposed to SSD access**, as shown by the paltry `bsqlt_tmpfs 8.9%` result. I have no
explanation for that performance cliff other than that maybe disk writes are better managed between hardware
components and threads when using SSDs.
### Top Runners

@@ -63,3 +139,5 @@

### To Do
* explain different benchmarks scenarios

@@ -69,2 +147,1 @@

@@ -9,6 +9,5 @@

- [Using Defaults](#using-defaults)
- [Automatic Location](#automatic-location)
- [Randomly Chosen Filename](#randomly-chosen-filename)
- [Using Parameters](#using-parameters)
- [All Parameters in Systematic Order](#all-parameters-in-systematic-order)
- [Valid Parameter Combinations](#valid-parameter-combinations)
- [Invalid Parameter Combinations](#invalid-parameter-combinations)

@@ -27,117 +26,32 @@ <!-- END doctoc generated TOC please keep comment here to allow auto update -->

The `db` object will then have two properties `db.sqlt1` and `db.sqlt2` that are `better-sqlite3`
connections to the same in-memory DB (a RAM DB in our terminology). This is achieved by passing an URL like
`file:_6200294332?mode=memory&cache=shared` to `better-sqlite3` where the name (`_6200294332`) is a random
10-digit number.
connections to the same temporary DB in the ['automatic location'](#automatic-location).
### Using Parameters
### Automatic Location
You can also call the constructor with a configuration object that may have one or more of the following
fields:
The so-called 'automatic location' is either
* **`cfg.ram`** (`?boolean`): Specifies whether a RAM DB is to be opened. All DBay in-memory DBs are named
so several connections to the same RAM DB can be opened (this is necessitated by a <del>shortcome</del>
<ins>feature</ins> of `better-sqlite3` that prohibits any reads against the DB from within User-Defined
Functions).
* the directory `/dev/shm` on Linux systems that support **SH**ared **M**emory (a.k.a a RAM disk)
* the OS's temporary directory as announced by `os.tmpdir()`
* When neither **`cfg.path`** nor **`cfg.dbnick`** are given, an empty RAM DB will be opened.
* When **`cfg.dbnick`** (but not **`cfg.path`**) is given, a
* When **`cfg.path`** is given, an SQLite DB file will be (created if non-existant and) opened; then,
the DB will be mirrored to RAM so now you have a RAM DB associated with a disk location. You can use
`db.save()` any number of times to write changes to disk. DB contents will be lost should the
process terminate after changes to the DB but before `db.save()` terminates. This mode of operation
is called 'Eventual Persistency'.
In either case, a [file with a random name](#randomly-chosen-filename) will be created in that location.
* **`cfg.path`** (`?non-empty text`): Specifies which file system path to save the DB to.
* When `path` is given but `ram` is not set (or `null` or `undefined`), `ram` will assume the value
`false`.
* When `path` is given
* and `ram` is **`false`**, a file DB will be opened from or created at the location given. This DB
will have Continuous Persistency, i.e. operate in the normal DB mode where all changes are reflected
on disk and thus made durable with a high degree of safety against data losses. Otherwise,
* when `ram` is `true`, a RAM DB will be opened.
### Randomly Chosen Filename
* **`cfg.dbnick`** (`?URL-safe word`): name given to a RAM DB. It will be used to construct a URL that
will be passed to SQLite. There's little use in passing in `dbnick` explicitly; if one wishes to
construct multiple `Dbay()` objects to the same RAM DB, one can always use the `cfg` object of the first
instance:
Format `dbay-NNNNNNNNNN.sqlite`, where `N` is a digit `[0-9]`.
```coffee
db1 = new Dbay { ram: true, }
db2 = new Dbay db1.cfg
```
### Using Parameters
#### All Parameters in Systematic Order
You can also call the constructor with a configuration object that may have one or more of the following
fields:
**Note** in the below tables, `in.*` parameters are those passed in when calling `new Dbay { ... }`; `out.*`
parameters are those to be found under `db.cfg.*` in the newly constructed instance. Observe that
* **`cfg.path`** (`?non-empty text`): Specifies which file system path to save the DB to; if the path given
is relative, it will be resolved in reference to the current directory (`process.cwd()`). When not
specified, `cfg.path` will be derived from [`Dbay.C.autolocation`](#automatic-location) and a [randomly
chosen filename](#randomly-chosen-filename).
* where `in.*` parameters are shown with `null` values here they can also be `undefined` or missing;
* where `out.*` parameters are shown with `null` values they will be missing from `db.cfg`. This omission
of `null` values is deemed advantageous for the human reader who will have less text to process when
printing `db.cfg` for introspection, and fewer combinations of values have to be pondered.
* For combinations that are unacceptable (cause errors), `out.*` parameters are left unspecified.
* **`cfg.temporary`** (`?boolean`): Specifies whether DB file is to be removed when process exits or
`db.destry()` is called explicitly. `cfg.temporary` defaults to `false` if `cfg.path` is given, and `true`
otherwise (when a random filename is chosen).
In addition to the `out.*` parameters listed, `db.cfg.url` will be set whenever `dbnick` is set. This URL
will be of the form
* `file:_6200294332?mode=memory&cache=shared` when generated, or
* `file:your_db_name_here?mode=memory&cache=shared` where `dbnick` is given (as `'your_db_name_here'` in
this example).
| nr | in.ram | in.path | in.dbnick | out.ram | out.path | out.dbnick | out.persistency | out.error | same as |
|----|---------|-------------|------------|---------|-------------|-----------------|-----------------|-----------|----------|
| 1 | `null` | `null` | `null` | `true` | `null` | `'_6200294332'` | none | ——— | 1, 9 |
| 2 | | | `'dbnick'` | `true` | `null` | `'dbnick'` | none | ——— | 2, 10 |
| 3 | | `'db/path'` | `null` | `false` | `'db/path'` | `null` | continuous | ——— | 3, 7 |
| 4 | | | `'dbnick'` | ——— | ——— | ——— | ——— | **E01** | 4, 8, 12 |
| 5 | `false` | `null` | `null` | ——— | ——— | ——— | ——— | **E02** | 5, 6 |
| 6 | | | `'dbnick'` | ——— | ——— | ——— | ——— | **E02** | 5, 6 |
| 7 | | `'db/path'` | `null` | `false` | `'db/path'` | `null` | continuous | ——— | 3, 7 |
| 8 | | | `'dbnick'` | ——— | ——— | ——— | ——— | **E01** | 4, 8, 12 |
| 9 | `true` | `null` | `null` | `true` | `null` | `'_6200294332'` | none | ——— | 1, 9 |
| 10 | | | `'dbnick'` | `true` | `null` | `'dbnick'` | none | ——— | 2, 10 |
| 11 | | `'db/path'` | `null` | `true` | `'db/path'` | `'_6200294332'` | eventual | ——— | ——— |
| 12 | | | `'dbnick'` | ——— | ——— | ——— | none | **E01** | 4, 8, 12 |
#### Valid Parameter Combinations
| nr | in.ram | in.path | in.dbnick | out.ram | out.path | out.dbnick | out.persistency |
|-------|-----------------|-------------|------------|---------|-------------|-----------------|-----------------|
| 1, 9 | `null`, `true` | `null` | `null` | `true` | `null` | `'_6200294332'` | none |
| 2, 10 | `null`, `true` | `null` | `'dbnick'` | `true` | `null` | `'dbnick'` | none |
| 11 | `true` | `'db/path'` | `null` | `true` | `'db/path'` | `'_6200294332'` | eventual |
| 3, 7 | `null`, `false` | `'db/path'` | `null` | `false` | `'db/path'` | `null` | continuous |
Resulting shapes of `db.cfg` when the above `in.*` parameters are applied; observe that additional
properties may be present:
| nr | |
|-------|-------------------------------------------------------------------------------------------------|
| 1, 9 | `{ ram: true, dbnick: '_6200294332', url: 'file:_6200294332?mode=memory&cache=shared' }` |
| 2, 10 | `{ ram: true, dbnick: 'dbnick', url: 'file:dbnick?mode=memory&cache=shared' }` |
| 11 | `{ ram: true, dbnick: 'dbnick', url: 'file:dbnick?mode=memory&cache=shared', path: 'db/path' }` |
| 3, 7 | `{ ram: false, path: 'db/path' }` |
| | |
#### Invalid Parameter Combinations
* When a `path` is given, `dbnick` must not be set. In the future, we may allow this `dbnick` to be used when
`db.transfer_to_ram()` is called.
* When `ram` is explicitly `false`, then `path` must be set.
| nr | in.ram | in.path | in.dbnick | out.error |
|----------|-------------------------|-----------------|--------------------|----------------------------------------------|
| 4, 8, 12 | `null`, `false`, `true` | **`'db/path'`** | **`'dbnick'`** | **E01 cannot give both `path` and `dbnick`** |
| 5, 6 | `false` | **`null`** | `null`, `'dbnick'` | **E02 missing argument `path`** |

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc