From c62ac2267e729bc66c59b7208323f80954a4edb5 Mon Sep 17 00:00:00 2001 From: Karol Szymanowski Date: Mon, 27 Mar 2023 16:50:15 +0200 Subject: [PATCH] Add new configuration method --- README.md | 56 ++++++++++++++++++++++++++++++++++++++++++-------- index.js | 41 ++++++++++++++++++++++++++++-------- tests/tests.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 394bf37..51fc09d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,58 @@ # Postache -## Example +## Configuration -Instead of ```js -db.query("select * from articles offset $1 limit $2", - [params.offset, params.limit]) +const postache = require("postache") + +// this is a pg config object, check the offical documentation: https://node-postgres.com/features/connecting#programmatic +const pgConfig = { + connectionString: "postgres://localhost:5432/mydb", + ssl: { + ca: fs.readFileSync("ca.pem").toString(), + } +} + +const db = postache( + postache.loadDir(path.join(__dirname, "queries")), + { + articlesTable: "articles", + }, + pgConfig +) ``` -you simply define your db like this: +> Note: Older version of this library used custom connection strings which is no longer supported. +> You can pass a [pg config object](https://node-postgres.com/features/connecting#programmatic) to the +> `postache` function instead. +> +> ```js +> const postache = require("postache") +> +> const connectionString = "postgres://localhost:5432/mydb" +> +> const pgConfig = { +> ssl: { +> ca: fs.readFileSync("ca.pem").toString(), +> } +> } +> +> const db = postache( +> postache.loadDir(path.join(__dirname, "queries")), +> { +> articlesTable: "articles", +> }, +> connectionString, +> pgConfig // <--- this is optional parameter that will override pg config created from connection string +> ) +> +## Usage + +Instead of ```js -const db = postache(postache.loadDir(path.join(__dirname, "queries")), { - articlesTable: "articles", -}, connectionString) -db.getLatestArticles(params) +db.query("select * from articles offset $1 limit $2", + [params.offset, params.limit]) ``` and in the queries fold your have a file `getArticles.sql`: diff --git a/index.js b/index.js index 6f55ff3..38d99f2 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ const obscurePassword = (conStr, password) => { return conStr.replace(password, "\x1B[31m{password omitted}\x1B[39m"); }; +// Deprecated: Parse a connection string to a pg configuration object const urlToObj = conStr => { if (typeof conStr !== "string") { return conStr; @@ -37,8 +38,9 @@ const urlToObj = conStr => { auth.username = conParams.auth; info("No password supplied, using only username"); } else { - auth.username = conParams.auth.split(":")[0]; - auth.password = conParams.auth.split(":")[1]; + const [username, password] = conParams.auth.split(":"); + auth.username = username; + auth.password = password; } } else { info("No username or password supplied, using blank name and password"); @@ -71,8 +73,30 @@ But you gave me: }; }; -module.exports = (queries, context, databaseUrl) => { - const db = new pg.Pool(urlToObj(databaseUrl)); +// Parse a config object or a string to support old and new ways of configuring postache +const parseConfig = urlOrPgConfig => { + if (typeof urlOrPgConfig === "string") { + info( + "String database URL is deprecated, use an object instead! More info: https://github.com/omninews/node-postache#configuration" + ); + + return urlToObj(urlOrPgConfig); + } + + if (typeof urlOrPgConfig === "object") { + return urlOrPgConfig; + } + + throw new Error("Invalid database URL!"); +}; + +module.exports = (queries, context, urlOrPgConfig, pgConfig = {}) => { + const pgConfigObj = { + ...parseConfig(urlOrPgConfig), + ...parseConfig(pgConfig) + }; + + const db = new pg.Pool(pgConfigObj); db.on("error", err => { error("idle client error: %s %j", err.message, err.stack); @@ -97,10 +121,11 @@ module.exports = (queries, context, databaseUrl) => { }); }; - return Object.assign( - { query: db.query.bind(db), db }, - R.mapObjIndexed(queryWithObj, renderedQueries) - ); + return { + query: db.query.bind(db), + db, + ...R.mapObjIndexed(queryWithObj, renderedQueries) + }; }; module.exports.loadDir = (dir, extOption) => { diff --git a/tests/tests.js b/tests/tests.js index f9b39c7..586b599 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -25,6 +25,60 @@ describe("postache", () => { postache([], [], "postgres://username:password@some.url/omni"); done(); }); + + it("should override configs passed", done => { + const config = { + user: "user", + password: "password", + port: 1234 + }; + + const result = postache( + [], + [], + "postgres://username:test@test:5432/test", + config + ); + + assert.equal(result.db.options.user, config.user); + assert.equal(result.db.options.password, config.password); + assert.equal(result.db.options.host, "test"); + assert.equal(result.db.options.port, config.port); + assert.equal(result.db.options.database, "test"); + + done(); + }); + + it("should accept an object as pg connection configuration", done => { + const config = { + user: "user", + password: "password", + port: 1234 + }; + + const result = postache([], [], config); + + assert.equal(result.db.options.user, config.user); + assert.equal(result.db.options.password, config.password); + assert.equal(result.db.options.port, config.port); + + done(); + }); + + it("should accept connection string url", done => { + const result = postache( + [], + [], + "postgres://username:password@some.url/omni" + ); + + assert.equal(result.db.options.user, "username"); + assert.equal(result.db.options.password, "password"); + assert.equal(result.db.options.host, "some.url"); + assert.equal(result.db.options.database, "omni"); + + done(); + }); }); describe("loadDir", () => {