rearrange factory usage
authorJustin Wind <justin.wind+git@gmail.com>
Fri, 12 Jan 2024 22:34:01 +0000 (14:34 -0800)
committerJustin Wind <justin.wind+git@gmail.com>
Fri, 12 Jan 2024 23:49:16 +0000 (15:49 -0800)
lib/factory.js
lib/postgres-creator.js
test-integration/abstract.js
test-integration/index.js [new file with mode: 0644]
test-integration/postgresql/index.js [moved from test-integration/postgres/index.js with 100% similarity]
test-integration/postgresql/sql/almanac-get-all.sql [moved from test-integration/postgres/sql/almanac-get-all.sql with 100% similarity]
test-integration/postgresql/sql/almanac-get.sql [moved from test-integration/postgres/sql/almanac-get.sql with 100% similarity]
test-integration/postgresql/sql/almanac-upsert.sql [moved from test-integration/postgres/sql/almanac-upsert.sql with 100% similarity]
test-integration/postgresql/sql/schema/1.0.0/apply.sql [moved from test-integration/postgres/sql/schema/1.0.0/apply.sql with 100% similarity]
test/integration.js
test/lib/factory.js

index acaf47f697e8de9a580fc8ea197dff0022f0ae35..4e58d6dafdb1a194bb4fbde245b01853ca178ef2 100644 (file)
@@ -1,6 +1,7 @@
 'use strict';
 
 const { UnsupportedEngine } = require('./errors');
+const path = require('node:path');
 
 /**
  * Instantiate a database engine based on the configured connection string.
@@ -11,47 +12,39 @@ class DatabaseFactory {
    * @param {Object} options
    * @param {Object} options.db
    * @param {String} options.db.connectionString
-   * @param  {...any} engineArguments 
+   * @param  {...any} engineArguments
    * @returns {Database}
    */
-  constructor(Abstract, logger, options, ...engineArguments) {
+  constructor(enginePathPrefix, logger, options, ...engineArguments) {
     const connectionString = options.db.connectionString || '';
     const protocol = connectionString.slice(0, connectionString.indexOf('://')).toLowerCase();
-
-    const EngineCreator = DatabaseFactory.requireEngineCreator(protocol);
-    const Engine = EngineCreator(Abstract);
+    const enginePath = this.enginePath(enginePathPrefix, protocol);
+    const Engine = this.localRequire(enginePath);
     return new Engine(logger, options, ...engineArguments);
   }
 
 
   /**
-   * Return the required db class as specified by `protocol`.
-   * @param {String} protocol
-   * @returns {Object}
+   * N.B. Re-implement this so require runs from expected location!
+   * @param {String} enginePath
    */
-  static requireEngineCreator(protocol) {
-    const Engines = DatabaseFactory.Engines;
-    switch (protocol) {
-      case Engines.PostgreSQL:
-        return require('./postgres-creator');
-
-      case Engines.SQLite:
-        return require('./sqlite-creator');
+  localRequire(enginePath) { // eslint-disable-line class-methods-use-this
+    return require(enginePath); // eslint-disable-line security/detect-non-literal-require
+  }
 
-      default:
-        throw new UnsupportedEngine(protocol);
-    }
+  get supportedProtocols() { // eslint-disable-line class-methods-use-this
+    return [
+      'postgresql',
+      'sqlite',
+    ];
   }
 
 
-  /**
-   * Mapping of protocol types.
-   */
-  static get Engines() {
-    return {
-      PostgreSQL: 'postgresql',
-      SQLite: 'sqlite',
-    };
+  enginePath(enginePathPrefix, protocol) {
+    if (!this.supportedProtocols.includes(protocol)) {
+      throw new UnsupportedEngine(protocol);
+    }
+    return [enginePathPrefix, protocol].join(path.sep);
   }
 
 }
index 29c6fe64482bf2b0a8127006d8ae102955b200b0..a5dc477539a1ff704cbf296ceacd0762ca0d515d 100644 (file)
@@ -68,6 +68,9 @@ const PostgresCreator = (Abstract) => {
 
       // Suppress QueryFile warnings when running tests
       this.noWarnings = options.db.noWarnings;
+
+      // Use a schema if provided
+      this.pgSchema = options.db.pgSchema;
     }
 
 
index c9686031db7dfe577e983960c09b010df656e210..2f38580d0fcb56fcc4cf4ba35cf4285632e604bf 100644 (file)
@@ -1,6 +1,6 @@
 'use strict';
 
-const Abstract = require('../lib/abstract');
+const { Abstract } = require('../');
 
 class AbstractIntegration extends Abstract {
   constructor(...args) {
diff --git a/test-integration/index.js b/test-integration/index.js
new file mode 100644 (file)
index 0000000..1427823
--- /dev/null
@@ -0,0 +1,14 @@
+'use strict';
+
+const { Factory: BaseFactory } = require('../');
+
+class Factory extends BaseFactory {
+  constructor(...args) {
+    super('.', ...args);
+  }
+  localRequire(enginePath) {
+    return require(enginePath);
+  }
+}
+
+module.exports = Factory;
index 63e755f40326866f63fe9a864f6a9c59092d1b2d..8b380387fdef81a615e442fcf7e0809e78320dbd 100644 (file)
@@ -30,7 +30,7 @@ describe('Database Integration', function () {
   if (process.env.POSTGRES_TEST_PATH) {
     implementations.push({
       name: 'PostgreSQL',
-      module: '../test-integration/postgres',
+      module: '../test-integration/',
       config: {
         db: {
           connectionString: `postgresql://${process.env.POSTGRES_TEST_PATH}`,
@@ -44,7 +44,7 @@ describe('Database Integration', function () {
   if (process.env.SQLITE_TEST_PATH) {
     implementations.push({
       name: 'SQLite',
-      module: '../test-integration/sqlite',
+      module: '../test-integration/',
       config: {
         db: {
           connectionString: `sqlite://${process.env.SQLITE_TEST_PATH}`,
index e92691f13bdf1a9ff9f373d737d7dabe55c5a70c..12e7be60da44adf5371e3eb663e3b98781f201a5 100644 (file)
@@ -4,14 +4,13 @@
 const assert = require('node:assert');
 const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
 const Factory = require('../../lib/factory');
-const Abstract = require('../../lib/abstract');
 const { UnsupportedEngine } = require('../../lib/errors');
 const pgp = require('pg-promise');
 
 const nop = () => unknown;
 
 describe('Factory', function () {
-  let logger, options;
+  let logger, options, enginePathPrefix;
 
   beforeEach(function () {
     logger = process.env['VERBOSE_TESTS'] ? console : { log: nop, debug: nop };
@@ -20,29 +19,30 @@ describe('Factory', function () {
         connectionString: '',
       },
     };
+    enginePathPrefix = '../test-integration';
   });
 
   it('covers postgres', function () {
     sinon.stub(pgp.utils, 'enumSql').returns({});
     options.db.connectionString = 'postgresql://example';
-    const factory = new Factory(Abstract, logger, options);
+    const factory = new Factory(enginePathPrefix, logger, options);
     assert(factory);
   });
 
   it('covers sqlite', function () {
     options.db.connectionString = 'sqlite://:memory:';
-    const factory = new Factory(Abstract, logger, options);
+    const factory = new Factory(enginePathPrefix, logger, options);
     assert(factory);
   });
 
   it('covers unknown', function () {
     options.db.connectionString = 'redis://example';
-    assert.throws(() => new Factory(Abstract, logger, options), UnsupportedEngine);
+    assert.throws(() => new Factory(enginePathPrefix, logger, options), UnsupportedEngine);
   });
   
   it('covers empty', function () {
     delete options.db.connectionString;
-    assert.throws(() => new Factory(Abstract, logger, options), UnsupportedEngine);
+    assert.throws(() => new Factory(enginePathPrefix, logger, options), UnsupportedEngine);
   });
 
 }); // Factory