graphile-build-pg
Version:
Build a GraphQL schema by reflection over a PostgreSQL schema. Easy to customize since it's built with plugins on graphile-build
95 lines (92 loc) • 3.59 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getPgClientAndReleaserFromConfig = exports.default = void 0;
exports.quacksLikePgPool = quacksLikePgPool;
var _pg = _interopRequireDefault(require("pg"));
var _debug = _interopRequireDefault(require("debug"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug.default)("graphile-build-pg");
function constructorName(obj) {
return obj && typeof obj.constructor === "function" && obj.constructor.name;
}
// Some duck-typing
function quacksLikePgClient(pgConfig) {
// A diagnosis of exclusion
if (!pgConfig || typeof pgConfig !== "object") return false;
if (constructorName(pgConfig) !== "Client") return false;
if (typeof pgConfig.connect !== "function") return false;
if (typeof pgConfig.end !== "function") return false;
if (typeof pgConfig.escapeLiteral !== "function") return false;
if (typeof pgConfig.escapeIdentifier !== "function") return false;
return true;
}
function quacksLikePgPool(pgConfig) {
// A diagnosis of exclusion
if (!pgConfig || typeof pgConfig !== "object") return false;
if (constructorName(pgConfig) !== "Pool" && constructorName(pgConfig) !== "BoundPool") {
return false;
}
if (!pgConfig.Client) return false;
if (!pgConfig.options) return false;
if (typeof pgConfig.connect !== "function") return false;
if (typeof pgConfig.end !== "function") return false;
if (typeof pgConfig.query !== "function") return false;
return true;
}
const getPgClientAndReleaserFromConfig = async (pgConfig = process.env.DATABASE_URL) => {
let releasePgClient = () => {};
let pgClient;
if (pgConfig instanceof _pg.default.Client || quacksLikePgClient(pgConfig)) {
pgClient = pgConfig;
if (!pgClient.release) {
throw new Error("We only support PG clients from a PG pool (because otherwise the `await` call can hang indefinitely if an error occurs and there's no error handler)");
}
} else if (pgConfig instanceof _pg.default.Pool || quacksLikePgPool(pgConfig)) {
const pgPool = pgConfig;
pgClient = await pgPool.connect();
releasePgClient = () => pgClient.release();
} else if (pgConfig === undefined || typeof pgConfig === "string") {
pgClient = new _pg.default.Client(pgConfig);
pgClient.on("error", e => {
debug("pgClient error occurred: %s", e);
});
releasePgClient = () => new Promise((resolve, reject) => pgClient.end(err => err ? reject(err) : resolve()));
await new Promise((resolve, reject) => pgClient.connect(err => err ? reject(err) : resolve()));
} else {
throw new Error("You must provide either a pg.Pool or pg.Client instance or a PostgreSQL connection string.");
}
return {
pgClient,
releasePgClient
};
};
exports.getPgClientAndReleaserFromConfig = getPgClientAndReleaserFromConfig;
const withPgClient = async (pgConfig, fn) => {
if (!fn) {
throw new Error("Nothing to do!");
}
const {
pgClient,
releasePgClient
} = await getPgClientAndReleaserFromConfig(pgConfig);
const errorHandler = e => {
// eslint-disable-next-line no-console
console.error("withPgClient client error:", e.message);
};
pgClient.on("error", errorHandler);
try {
return await fn(pgClient);
} finally {
pgClient.removeListener("error", errorHandler);
try {
await releasePgClient();
} catch (e) {
// Failed to release, assuming success
}
}
};
var _default = withPgClient;
exports.default = _default;
//# sourceMappingURL=withPgClient.js.map