@openstax/ts-utils 1.20.5 → 1.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ import postgres, { Sql } from 'postgres';
2
+ import { ConfigProviderForConfig } from '../../config';
3
+ import type { Logger } from '../logger';
4
+ declare type Config = {
5
+ host: string;
6
+ readHost: string;
7
+ port: string;
8
+ database: string;
9
+ username: string;
10
+ password: string;
11
+ };
12
+ interface Initializer<C> {
13
+ configSpace?: C;
14
+ }
15
+ export declare const postgresConnection: <C extends string = "local">(initializer: Initializer<C>) => (configProvider: { [key in C]: {
16
+ host: import("../../config").ConfigValueProvider<string>;
17
+ readHost: import("../../config").ConfigValueProvider<string>;
18
+ port: import("../../config").ConfigValueProvider<string>;
19
+ database: import("../../config").ConfigValueProvider<string>;
20
+ username: import("../../config").ConfigValueProvider<string>;
21
+ password: import("../../config").ConfigValueProvider<string>;
22
+ }; }) => (services: {
23
+ logger: Logger;
24
+ }) => {
25
+ db: () => Promise<postgres.Sql<{}>>;
26
+ dbRead: () => Promise<postgres.Sql<{}>>;
27
+ migrate: (migrations: Migration[]) => Promise<void>;
28
+ down: () => Promise<void[]>;
29
+ };
30
+ export declare type PostgresConnection = ReturnType<ReturnType<ReturnType<typeof postgresConnection>>>;
31
+ export interface Migration {
32
+ name: string;
33
+ up: (db: Sql) => Promise<void>;
34
+ }
35
+ export {};
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.postgresConnection = void 0;
7
+ const postgres_1 = __importDefault(require("postgres"));
8
+ const assertions_1 = require("../../assertions");
9
+ const config_1 = require("../../config");
10
+ const guards_1 = require("../../guards");
11
+ const helpers_1 = require("../../misc/helpers");
12
+ const postgresConnection = (initializer) => (configProvider) => {
13
+ const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'local')];
14
+ const host = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.host));
15
+ const readHost = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.readHost));
16
+ const connectionOptions = (0, helpers_1.once)(async () => ({
17
+ port: (0, assertions_1.assertNotNaN)(parseInt(await (0, config_1.resolveConfigValue)(config.port), 10), new Error('port must be a number')),
18
+ database: await (0, config_1.resolveConfigValue)(config.database),
19
+ username: await (0, config_1.resolveConfigValue)(config.username),
20
+ password: await (0, config_1.resolveConfigValue)(config.password),
21
+ transform: postgres_1.default.camel,
22
+ }));
23
+ const connections = [];
24
+ const sql = (0, helpers_1.once)(async () => {
25
+ const options = await connectionOptions();
26
+ const connection = (0, postgres_1.default)({ ...options, host: await host() });
27
+ connections.push(connection);
28
+ return connection;
29
+ });
30
+ const sqlRead = (0, helpers_1.once)(async () => {
31
+ const options = await connectionOptions();
32
+ const connection = (0, postgres_1.default)({ ...options, host: await readHost() });
33
+ connections.push(connection);
34
+ return connection;
35
+ });
36
+ return (services) => ({
37
+ db: sql,
38
+ dbRead: sqlRead,
39
+ migrate: async (migrations) => {
40
+ await migrate(services, await sql(), migrations);
41
+ },
42
+ down: () => Promise.all(connections.map(c => c.end()))
43
+ });
44
+ };
45
+ exports.postgresConnection = postgresConnection;
46
+ async function migrate(services, db, migrations) {
47
+ await db `
48
+ CREATE TABLE IF NOT EXISTS migrations (
49
+ id SERIAL PRIMARY KEY,
50
+ name TEXT NOT NULL,
51
+ ran_at TIMESTAMP NOT NULL DEFAULT NOW()
52
+ )
53
+ `;
54
+ const ranMigrations = await db `SELECT name FROM migrations`;
55
+ for (const migration of migrations) {
56
+ if (ranMigrations.some(({ name }) => name === migration.name)) {
57
+ continue;
58
+ }
59
+ services.logger.log(`Running migration ${migration.name}`);
60
+ await migration.up(db);
61
+ await db `INSERT INTO migrations (name) VALUES (${migration.name})`;
62
+ }
63
+ }