From: Justin Wind Date: Fri, 12 Jan 2024 22:34:01 +0000 (-0800) Subject: rearrange factory usage X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=1252c72bcd9382ad501e0fe584bd61bc3fb82b27;p=squeep-db-helper rearrange factory usage --- diff --git a/lib/factory.js b/lib/factory.js index acaf47f..4e58d6d 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -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); } } diff --git a/lib/postgres-creator.js b/lib/postgres-creator.js index 29c6fe6..a5dc477 100644 --- a/lib/postgres-creator.js +++ b/lib/postgres-creator.js @@ -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; } diff --git a/test-integration/abstract.js b/test-integration/abstract.js index c968603..2f38580 100644 --- a/test-integration/abstract.js +++ b/test-integration/abstract.js @@ -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 index 0000000..1427823 --- /dev/null +++ b/test-integration/index.js @@ -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; diff --git a/test-integration/postgres/index.js b/test-integration/postgresql/index.js similarity index 100% rename from test-integration/postgres/index.js rename to test-integration/postgresql/index.js diff --git a/test-integration/postgres/sql/almanac-get-all.sql b/test-integration/postgresql/sql/almanac-get-all.sql similarity index 100% rename from test-integration/postgres/sql/almanac-get-all.sql rename to test-integration/postgresql/sql/almanac-get-all.sql diff --git a/test-integration/postgres/sql/almanac-get.sql b/test-integration/postgresql/sql/almanac-get.sql similarity index 100% rename from test-integration/postgres/sql/almanac-get.sql rename to test-integration/postgresql/sql/almanac-get.sql diff --git a/test-integration/postgres/sql/almanac-upsert.sql b/test-integration/postgresql/sql/almanac-upsert.sql similarity index 100% rename from test-integration/postgres/sql/almanac-upsert.sql rename to test-integration/postgresql/sql/almanac-upsert.sql diff --git a/test-integration/postgres/sql/schema/1.0.0/apply.sql b/test-integration/postgresql/sql/schema/1.0.0/apply.sql similarity index 100% rename from test-integration/postgres/sql/schema/1.0.0/apply.sql rename to test-integration/postgresql/sql/schema/1.0.0/apply.sql diff --git a/test/integration.js b/test/integration.js index 63e755f..8b38038 100644 --- a/test/integration.js +++ b/test/integration.js @@ -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}`, diff --git a/test/lib/factory.js b/test/lib/factory.js index e92691f..12e7be6 100644 --- a/test/lib/factory.js +++ b/test/lib/factory.js @@ -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