104 lines
2.5 KiB
TypeScript
104 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;
|