Skip to content

Commit 4f055a6

Browse files
authored
ESM conversion (#8)
* ESM conversion Signed-off-by: Prabhu Subramanian <[email protected]> --------- Signed-off-by: Prabhu Subramanian <[email protected]>
1 parent e5993c3 commit 4f055a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+902
-645
lines changed

.eslintrc.js renamed to .eslintrc.cjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
module.exports = {
22
"extends": "eslint:recommended",
3+
"parserOptions": {
4+
"sourceType": "module"
5+
},
36
"env": {
47
"es2017": true,
58
"node": true

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ See the [API documentation](https://github.com/AppThreat/node-sqlite3/wiki/API)
6666

6767
**Note:** the module must be [installed](#installing) before use.
6868

69+
This package is now ESM only.
70+
6971
``` js
70-
const sqlite3 = require('sqlite3').verbose();
71-
const db = new sqlite3.Database(':memory:');
72+
import sqlite3 from 'sqlite3';
73+
const db = new sqlite3.verbose().Database(':memory:');
7274

7375
db.serialize(() => {
7476
db.run("CREATE TABLE lorem (info TEXT)");

lib/bindings.js

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/**
2+
* Module dependencies.
3+
*/
4+
5+
import fs from 'fs';
6+
import path from 'path';
7+
import { fileURLToPath } from 'url';
8+
import { createRequire } from 'module';
9+
10+
const require = createRequire(import.meta.url);
11+
12+
const join = path.join;
13+
const dirname = path.dirname;
14+
const exists =
15+
(fs.accessSync &&
16+
function(path) {
17+
try {
18+
fs.accessSync(path);
19+
} catch (e) {
20+
return false;
21+
}
22+
return true;
23+
}) ||
24+
fs.existsSync ||
25+
path.existsSync;
26+
27+
const defaults = {
28+
arrow: process.env.NODE_BINDINGS_ARROW || ' → ',
29+
compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled',
30+
platform: process.platform,
31+
arch: process.arch,
32+
nodePreGyp:
33+
'node-v' +
34+
process.versions.modules +
35+
'-' +
36+
process.platform +
37+
'-' +
38+
process.arch,
39+
version: process.versions.node,
40+
bindings: 'bindings.node',
41+
try: [
42+
// node-gyp's linked version in the "build" dir
43+
['module_root', 'build', 'bindings'],
44+
// node-waf and gyp_addon (a.k.a node-gyp)
45+
['module_root', 'build', 'Debug', 'bindings'],
46+
['module_root', 'build', 'Release', 'bindings'],
47+
// Debug files, for development (legacy behavior, remove for node v0.9)
48+
['module_root', 'out', 'Debug', 'bindings'],
49+
['module_root', 'Debug', 'bindings'],
50+
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
51+
['module_root', 'out', 'Release', 'bindings'],
52+
['module_root', 'Release', 'bindings'],
53+
// Legacy from node-waf, node <= 0.4.x
54+
['module_root', 'build', 'default', 'bindings'],
55+
// Production "Release" buildtype binary (meh...)
56+
['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],
57+
// node-qbs builds
58+
['module_root', 'addon-build', 'release', 'install-root', 'bindings'],
59+
['module_root', 'addon-build', 'debug', 'install-root', 'bindings'],
60+
['module_root', 'addon-build', 'default', 'install-root', 'bindings'],
61+
// node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
62+
['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']
63+
]
64+
};
65+
66+
/**
67+
* The main `bindings()` function loads the compiled bindings for a given module.
68+
* It uses V8's Error API to determine the parent filename that this function is
69+
* being invoked from, which is then used to find the root directory.
70+
*/
71+
72+
function bindings(opts) {
73+
// Argument surgery
74+
if (typeof opts == 'string') {
75+
opts = { bindings: opts };
76+
} else if (!opts) {
77+
opts = {};
78+
}
79+
80+
// maps `defaults` onto `opts` object
81+
Object.keys(defaults).map(function(i) {
82+
if (!(i in opts)) opts[i] = defaults[i];
83+
});
84+
85+
// Get the module root
86+
if (!opts.module_root) {
87+
opts.module_root = getRoot(getFileName());
88+
}
89+
90+
// Ensure the given bindings name ends with .node
91+
if (path.extname(opts.bindings) != '.node') {
92+
opts.bindings += '.node';
93+
}
94+
95+
// https://github.com/webpack/webpack/issues/4175#issuecomment-342931035
96+
const requireFunc =
97+
typeof __webpack_require__ === 'function'
98+
? __non_webpack_require__
99+
: require;
100+
101+
const tries = [];
102+
let i = 0;
103+
const l = opts.try.length;
104+
let n, b, err;
105+
106+
for (; i < l; i++) {
107+
n = join.apply(
108+
null,
109+
opts.try[i].map(function(p) {
110+
return opts[p] || p;
111+
})
112+
);
113+
tries.push(n);
114+
try {
115+
b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
116+
if (!opts.path) {
117+
b.path = n;
118+
}
119+
return b;
120+
} catch (e) {
121+
if (
122+
e.code !== 'MODULE_NOT_FOUND' &&
123+
e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' &&
124+
!/not find/i.test(e.message)
125+
) {
126+
throw e;
127+
}
128+
}
129+
}
130+
131+
err = new Error(
132+
'Could not locate the bindings file. Tried:\n' +
133+
tries
134+
.map(function(a) {
135+
return opts.arrow + a;
136+
})
137+
.join('\n')
138+
);
139+
err.tries = tries;
140+
throw err;
141+
}
142+
143+
/**
144+
* Gets the filename of the JavaScript file that invokes this function.
145+
* Used to help find the root directory of a module.
146+
* Optionally accepts an filename argument to skip when searching for the invoking filename
147+
*/
148+
149+
function getFileName(calling_file) {
150+
const origPST = Error.prepareStackTrace;
151+
const origSTL = Error.stackTraceLimit;
152+
const dummy = {};
153+
let fileName;
154+
155+
Error.stackTraceLimit = 10;
156+
157+
Error.prepareStackTrace = function(e, st) {
158+
for (let i = 0, l = st.length; i < l; i++) {
159+
fileName = st[i].getFileName();
160+
if (fileName !== import.meta.url) {
161+
if (calling_file) {
162+
if (fileName !== calling_file) {
163+
return;
164+
}
165+
} else {
166+
return;
167+
}
168+
}
169+
}
170+
};
171+
172+
// run the 'prepareStackTrace' function above
173+
Error.captureStackTrace(dummy);
174+
dummy.stack;
175+
176+
// cleanup
177+
Error.prepareStackTrace = origPST;
178+
Error.stackTraceLimit = origSTL;
179+
180+
// handle filename that starts with "file://"
181+
const fileSchema = 'file://';
182+
if (fileName && fileName.indexOf(fileSchema) === 0) {
183+
fileName = fileURLToPath(fileName);
184+
}
185+
186+
return fileName;
187+
}
188+
189+
/**
190+
* Gets the root directory of a module, given an arbitrary filename
191+
* somewhere in the module tree. The "root directory" is the directory
192+
* containing the `package.json` file.
193+
*
194+
* In: /home/nate/node-native-module/lib/index.js
195+
* Out: /home/nate/node-native-module
196+
*/
197+
198+
function getRoot(file) {
199+
let dir = dirname(file);
200+
let prev;
201+
while (true) {
202+
if (dir === '.') {
203+
// Avoids an infinite loop in rare cases, like the REPL
204+
dir = process.cwd();
205+
}
206+
if (
207+
exists(join(dir, 'package.json')) ||
208+
exists(join(dir, 'node_modules'))
209+
) {
210+
// Found the 'package.json' file or 'node_modules' dir; we're done
211+
return dir;
212+
}
213+
if (prev === dir) {
214+
// Got to the top
215+
throw new Error(
216+
'Could not find module root given file: "' +
217+
file +
218+
'". Do you have a `package.json` file? '
219+
);
220+
}
221+
// Try the parent dir next
222+
prev = dir;
223+
dir = join(dir, '..');
224+
}
225+
}
226+
227+
export default bindings;
228+
export { getFileName, getRoot };

lib/sqlite3-binding.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
module.exports = require('bindings')('node_sqlite3.node');
1+
import bindings from './bindings.js';
2+
export default bindings('node_sqlite3.node');

lib/sqlite3.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
const path = require('path');
2-
const sqlite3 = require('./sqlite3-binding.js');
3-
const EventEmitter = require('events').EventEmitter;
4-
module.exports = exports = sqlite3;
1+
import path from 'path';
2+
import sqlite3 from './sqlite3-binding.js';
3+
import { EventEmitter } from 'events';
4+
import { extendTrace } from "./trace.js";
55

6-
function normalizeMethod (fn) {
7-
return function (sql) {
6+
function normalizeMethod(fn) {
7+
return function(sql) {
88
let errBack;
99
const args = Array.prototype.slice.call(arguments, 1);
1010

@@ -55,7 +55,6 @@ sqlite3.cached = {
5555
objects: {}
5656
};
5757

58-
5958
const Database = sqlite3.Database;
6059
const Statement = sqlite3.Statement;
6160
const Backup = sqlite3.Backup;
@@ -105,11 +104,11 @@ Database.prototype.map = normalizeMethod(function(statement, params) {
105104
Database.prototype.backup = function() {
106105
let backup;
107106
if (arguments.length <= 2) {
108-
// By default, we write the main database out to the main database of the named file.
109-
// This is the most likely use of the backup api.
107+
// By default, we write the main database out to the main database of the named file.
108+
// This is the most likely use of the backup api.
110109
backup = new Backup(this, arguments[0], 'main', 'main', true, arguments[1]);
111110
} else {
112-
// Otherwise, give the user full control over the sqlite3_backup_init arguments.
111+
// Otherwise, give the user full control over the sqlite3_backup_init arguments.
113112
backup = new Backup(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
114113
}
115114
// Per the sqlite docs, exclude the following errors as non-fatal by default.
@@ -175,7 +174,6 @@ Database.prototype.removeAllListeners = function(type) {
175174
// Save the stack trace over EIO callbacks.
176175
sqlite3.verbose = function() {
177176
if (!isVerbose) {
178-
const trace = require('./trace');
179177
[
180178
'prepare',
181179
'get',
@@ -186,7 +184,7 @@ sqlite3.verbose = function() {
186184
'close',
187185
'exec'
188186
].forEach(function (name) {
189-
trace.extendTrace(Database.prototype, name);
187+
extendTrace(Database.prototype, name);
190188
});
191189
[
192190
'bind',
@@ -198,10 +196,12 @@ sqlite3.verbose = function() {
198196
'reset',
199197
'finalize',
200198
].forEach(function (name) {
201-
trace.extendTrace(Statement.prototype, name);
199+
extendTrace(Statement.prototype, name);
202200
});
203201
isVerbose = true;
204202
}
205-
206203
return sqlite3;
207204
};
205+
206+
export default sqlite3;
207+
export { Database, Statement, Backup };

0 commit comments

Comments
 (0)