link-stack/packages/hapi-pg-promise/src/index.ts

103 lines
2.5 KiB
TypeScript

import * as Hapi from "@hapi/hapi";
import * as Hoek from "@hapi/hoek";
import pgPromise from "pg-promise";
import * as pgMonitor from "pg-monitor";
import type { IConnectionParameters } from "pg-promise/typescript/pg-subset";
import type { IMain, IInitOptions } from "pg-promise";
import { IPGPPluginOptions, ExtendedProtocol } from "./types";
export * from "./types";
const defaultOptions: IPGPPluginOptions<unknown> = {
connection: undefined,
pgpInit: {},
logSql: false,
decorateAs: {
pgp: "pgp",
db: "db",
},
};
export const startDiagnostics = <T>(
logSql: boolean,
initOpts: IInitOptions<T>
): void => {
if (logSql) {
pgMonitor.attach(initOpts);
} else {
pgMonitor.attach(initOpts, ["error"]);
}
};
export const stopDiagnostics = (): void => pgMonitor.detach();
const startPgp = async <T>(initOptions: IInitOptions<T>): Promise<IMain> => {
const pgp: IMain = pgPromise(initOptions);
return pgp;
};
const startDb = async <T>(
pgp,
connection: string | IConnectionParameters
): Promise<ExtendedProtocol<T>> => {
const db: ExtendedProtocol<T> = pgp(connection);
return db;
};
const register = async <T>(
server: Hapi.Server,
userOpts?: IPGPPluginOptions<T>
): Promise<void> => {
const options: IPGPPluginOptions<T> = Hoek.applyToDefaults(
defaultOptions,
userOpts
) as IPGPPluginOptions<T>;
if (!options.connection) {
throw new Error(
"hapi-pg-promise: connection details are not defined. You must specify a valid connection for the plugin to boot."
);
}
if ("pgp" in options && "pgpInit" in options) {
throw new Error(
"hapi-pg-promise: options pgp and pgpInit are mutually exclusive"
);
}
let pgp: IMain;
if ("pgp" in options) {
pgp = options.pgp;
} else {
pgp = await startPgp(options.pgpInit);
startDiagnostics(options.logSql, options.pgpInit);
}
const db = await startDb(pgp, options.connection);
if (options.decorateAs) {
if (options.decorateAs) {
server.decorate("request", options.decorateAs.pgp, pgp);
server.decorate("server", options.decorateAs.pgp, pgp);
}
if (options.decorateAs.db) {
server.decorate("server", options.decorateAs.db, () => db);
server.decorate("request", options.decorateAs.db, () => db);
}
}
server.ext("onPostStop", async () => {
stopDiagnostics();
await db.$pool.end();
});
};
const pgPromisePlugin = {
register,
name: "pg-promise",
version: "0.0.1",
};
export default pgPromisePlugin;