database.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. 'use strict';
  2. const fs = require('fs');
  3. const path = require('path');
  4. const util = require('./util');
  5. const SqliteError = require('./sqlite-error');
  6. let DEFAULT_ADDON;
  7. function Database(filenameGiven, options) {
  8. if (new.target == null) {
  9. return new Database(filenameGiven, options);
  10. }
  11. // Apply defaults
  12. let buffer;
  13. if (Buffer.isBuffer(filenameGiven)) {
  14. buffer = filenameGiven;
  15. filenameGiven = ':memory:';
  16. }
  17. if (filenameGiven == null) filenameGiven = '';
  18. if (options == null) options = {};
  19. // Validate arguments
  20. if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
  21. if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
  22. if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
  23. if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
  24. // Interpret options
  25. const filename = filenameGiven.trim();
  26. const anonymous = filename === '' || filename === ':memory:';
  27. const readonly = util.getBooleanOption(options, 'readonly');
  28. const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
  29. const timeout = 'timeout' in options ? options.timeout : 5000;
  30. const verbose = 'verbose' in options ? options.verbose : null;
  31. const nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;
  32. // Validate interpreted options
  33. if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
  34. if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
  35. if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
  36. if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
  37. if (nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
  38. // Load the native addon
  39. let addon;
  40. if (nativeBinding == null) {
  41. addon = DEFAULT_ADDON || (DEFAULT_ADDON = require('bindings')('better_sqlite3.node'));
  42. } else if (typeof nativeBinding === 'string') {
  43. // See <https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific>
  44. const requireFunc = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : require;
  45. addon = requireFunc(path.resolve(nativeBinding).replace(/(\.node)?$/, '.node'));
  46. } else {
  47. // See <https://github.com/WiseLibs/better-sqlite3/issues/972>
  48. addon = nativeBinding;
  49. }
  50. if (!addon.isInitialized) {
  51. addon.setErrorConstructor(SqliteError);
  52. addon.isInitialized = true;
  53. }
  54. // Make sure the specified directory exists
  55. if (!anonymous && !filename.startsWith('file:') && !fs.existsSync(path.dirname(filename))) {
  56. throw new TypeError('Cannot open database because the directory does not exist');
  57. }
  58. Object.defineProperties(this, {
  59. [util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
  60. ...wrappers.getters,
  61. });
  62. }
  63. const wrappers = require('./methods/wrappers');
  64. Database.prototype.prepare = wrappers.prepare;
  65. Database.prototype.transaction = require('./methods/transaction');
  66. Database.prototype.pragma = require('./methods/pragma');
  67. Database.prototype.backup = require('./methods/backup');
  68. Database.prototype.serialize = require('./methods/serialize');
  69. Database.prototype.function = require('./methods/function');
  70. Database.prototype.aggregate = require('./methods/aggregate');
  71. Database.prototype.table = require('./methods/table');
  72. Database.prototype.loadExtension = wrappers.loadExtension;
  73. Database.prototype.exec = wrappers.exec;
  74. Database.prototype.close = wrappers.close;
  75. Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
  76. Database.prototype.unsafeMode = wrappers.unsafeMode;
  77. Database.prototype[util.inspect] = require('./methods/inspect');
  78. module.exports = Database;