@devmoods/express-extras 0.16.0 → 0.17.0
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.
- package/dist/__tests__/__migrations__/1_a.d.ts +3 -0
- package/dist/__tests__/__migrations__/1_a.js +8 -0
- package/dist/email.d.ts +1 -0
- package/dist/email.js +1 -1
- package/dist/migrate.d.ts +4 -4
- package/dist/migrate.js +44 -16
- package/dist/postgres.d.ts +5 -3
- package/dist/postgres.js +5 -3
- package/dist/sentry.d.ts +4 -1
- package/package.json +22 -22
- package/dist/__tests__/__migrations__/1_test.d.ts +0 -2
- package/dist/__tests__/__migrations__/1_test.js +0 -7
package/dist/email.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export interface SendEmailOptions extends nodemailer.SendMailOptions {
|
|
|
12
12
|
}
|
|
13
13
|
export declare function createEmail({ host, port, user, pass, senderName, senderAddress, }: EmailOptions): {
|
|
14
14
|
send: ({ to, subject, message, ...rest }: SendEmailOptions) => Promise<void>;
|
|
15
|
+
transporter: nodemailer.Transporter<import("nodemailer/lib/smtp-transport/index.js").SentMessageInfo>;
|
|
15
16
|
};
|
package/dist/email.js
CHANGED
package/dist/migrate.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPostgres } from './postgres.js';
|
|
1
|
+
import { type Connection, createPostgres } from './postgres.js';
|
|
2
2
|
interface Migration {
|
|
3
3
|
name: string;
|
|
4
4
|
filename: string;
|
|
@@ -23,9 +23,9 @@ export declare class Migrator {
|
|
|
23
23
|
runMigrations(direction: 'up' | 'down'): Promise<number>;
|
|
24
24
|
log(...args: any[]): void;
|
|
25
25
|
executeMigration(migrations: Migration[], currentVersion: number, direction: 'up' | 'down'): Promise<number>;
|
|
26
|
-
|
|
27
|
-
migrate(migration: Migration, direction: 'up' | 'down'): Promise<
|
|
28
|
-
updateCurrentVersion(version: number): Promise<import("pg").QueryResult<import("pg").QueryResultRow>>;
|
|
26
|
+
readMigrationFile(filename: string): Promise<any>;
|
|
27
|
+
migrate(tx: Connection, migration: Migration, direction: 'up' | 'down'): Promise<void>;
|
|
28
|
+
updateCurrentVersion(connection: Connection, version: number): Promise<import("pg").QueryResult<import("pg").QueryResultRow>>;
|
|
29
29
|
getCurrentVersion(): Promise<number>;
|
|
30
30
|
getMigrations(): Promise<{
|
|
31
31
|
filename: string;
|
package/dist/migrate.js
CHANGED
|
@@ -54,7 +54,7 @@ Usage
|
|
|
54
54
|
}
|
|
55
55
|
export class Migrator {
|
|
56
56
|
constructor({ postgres = createPostgres(), pathToMigrations = path.resolve(process.cwd(), 'db', 'migrations'), migrationTableName = 'migrations', verbose = true, } = {}) {
|
|
57
|
-
this.filenameRegExp = /(\d+)_(.*)\.(js|ts|mjs|mts)/;
|
|
57
|
+
this.filenameRegExp = /(\d+)_(.*)\.(js|ts|mjs|mts|sql)/;
|
|
58
58
|
this.postgres = postgres;
|
|
59
59
|
this.pathToMigrations = pathToMigrations;
|
|
60
60
|
this.migrationTableName = migrationTableName;
|
|
@@ -104,8 +104,10 @@ export class Migrator {
|
|
|
104
104
|
}
|
|
105
105
|
for (const migration of pendingMigrations) {
|
|
106
106
|
this.log('Running migration', migration.filename);
|
|
107
|
-
await this.
|
|
108
|
-
|
|
107
|
+
await this.postgres.transaction(async (tx) => {
|
|
108
|
+
await this.migrate(tx, migration, direction);
|
|
109
|
+
await this.updateCurrentVersion(tx, migration.version);
|
|
110
|
+
});
|
|
109
111
|
}
|
|
110
112
|
this.log(chalk.green('Done!'));
|
|
111
113
|
return await this.getCurrentVersion();
|
|
@@ -120,29 +122,55 @@ export class Migrator {
|
|
|
120
122
|
return currentVersion;
|
|
121
123
|
}
|
|
122
124
|
this.log('Rolling back migration', migrationToRollback.filename);
|
|
123
|
-
await this.
|
|
124
|
-
|
|
125
|
+
await this.postgres.transaction(async (tx) => {
|
|
126
|
+
await this.migrate(tx, migrationToRollback, 'down');
|
|
127
|
+
await this.updateCurrentVersion(tx, updatedVersion);
|
|
128
|
+
});
|
|
125
129
|
return await this.getCurrentVersion();
|
|
126
130
|
}
|
|
127
131
|
throw new Error(`Invalid direction ${direction}`);
|
|
128
132
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
async readMigrationFile(filename) {
|
|
134
|
+
if (!filename.endsWith('.sql')) {
|
|
135
|
+
return import(filename);
|
|
136
|
+
}
|
|
137
|
+
const content = await fs.readFile(filename, 'utf-8');
|
|
138
|
+
const [up, down] = content.split('-- ROLLBACK --');
|
|
139
|
+
return {
|
|
140
|
+
up() {
|
|
141
|
+
return up.trim();
|
|
142
|
+
},
|
|
143
|
+
down() {
|
|
144
|
+
return (down || '').trim();
|
|
145
|
+
},
|
|
146
|
+
};
|
|
132
147
|
}
|
|
133
|
-
async migrate(migration, direction) {
|
|
134
|
-
const migrator = await
|
|
148
|
+
async migrate(tx, migration, direction) {
|
|
149
|
+
const migrator = await this.readMigrationFile(migration.filename);
|
|
135
150
|
if (!migrator.up || !migrator.down) {
|
|
136
151
|
throw new Error('Migrations must export both an up() and a down() function.');
|
|
137
152
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
153
|
+
try {
|
|
154
|
+
const queryWithLog = (sql) => {
|
|
155
|
+
this.log(chalk.yellow(sql.toString()));
|
|
156
|
+
return tx.query(sql);
|
|
157
|
+
};
|
|
158
|
+
const returnValue = await migrator[direction](queryWithLog.bind(tx));
|
|
159
|
+
if (typeof returnValue === 'string') {
|
|
160
|
+
if (returnValue !== '') {
|
|
161
|
+
await queryWithLog(returnValue);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
await returnValue;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw new Error(`Migration failed: ${error.message}`);
|
|
141
170
|
}
|
|
142
|
-
return returnValue;
|
|
143
171
|
}
|
|
144
|
-
updateCurrentVersion(version) {
|
|
145
|
-
return
|
|
172
|
+
updateCurrentVersion(connection, version) {
|
|
173
|
+
return connection.query(`INSERT INTO ${this.migrationTableName} (version, run_at) VALUES ($1, $2)`, [version, new Date()]);
|
|
146
174
|
}
|
|
147
175
|
async getCurrentVersion() {
|
|
148
176
|
const result = await this.postgres.first(`SELECT version FROM ${this.migrationTableName} ORDER BY run_at DESC LIMIT 1`);
|
package/dist/postgres.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare class MultipleRowsReturnedError extends Error {
|
|
|
10
10
|
constructor(message: string);
|
|
11
11
|
}
|
|
12
12
|
type Value = null | string | number | Date;
|
|
13
|
-
declare class
|
|
13
|
+
export declare class Connection {
|
|
14
14
|
client: PoolClient;
|
|
15
15
|
constructor(client: PoolClient);
|
|
16
16
|
query<T extends QueryResultRow>(text: string | SQLStatement, values?: Value[]): Promise<QueryResult<T>>;
|
|
@@ -19,6 +19,8 @@ declare class API {
|
|
|
19
19
|
first<T>(text: string | SQLStatement, values?: Value[]): Promise<T | null>;
|
|
20
20
|
get<T>(text: string | SQLStatement, values?: Value[]): Promise<T>;
|
|
21
21
|
}
|
|
22
|
+
export declare class Transaction extends Connection {
|
|
23
|
+
}
|
|
22
24
|
/**
|
|
23
25
|
* Create a new Postgres connection pool with
|
|
24
26
|
* conveience methods for executing queries using
|
|
@@ -32,8 +34,8 @@ export declare function createPostgres({ onError, ...config }?: PostgresOptions)
|
|
|
32
34
|
first: <T_2>(text: string | SQLStatement, values?: Value[] | undefined) => Promise<T_2 | null>;
|
|
33
35
|
all: <T_3>(text: string | SQLStatement, values?: Value[] | undefined) => Promise<T_3[]>;
|
|
34
36
|
get: <T_4>(text: string | SQLStatement, values?: Value[] | undefined) => Promise<T_4>;
|
|
35
|
-
withConnection: <T_5>(callback: (connection:
|
|
36
|
-
transaction: <T_6>(callback: (connection:
|
|
37
|
+
withConnection: <T_5>(callback: (connection: Connection) => Promise<T_5>) => Promise<T_5>;
|
|
38
|
+
transaction: <T_6>(callback: (connection: Transaction) => T_6 | Promise<T_6>) => Promise<T_6>;
|
|
37
39
|
instance: pg.Pool;
|
|
38
40
|
clear: (force?: boolean) => Promise<void>;
|
|
39
41
|
end(): Promise<void>;
|
package/dist/postgres.js
CHANGED
|
@@ -12,7 +12,7 @@ export class MultipleRowsReturnedError extends Error {
|
|
|
12
12
|
this.name = 'MultipleRowsReturnedError';
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
class
|
|
15
|
+
export class Connection {
|
|
16
16
|
constructor(client) {
|
|
17
17
|
this.client = client;
|
|
18
18
|
}
|
|
@@ -44,6 +44,8 @@ class API {
|
|
|
44
44
|
return result.rows[0];
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
export class Transaction extends Connection {
|
|
48
|
+
}
|
|
47
49
|
/**
|
|
48
50
|
* Create a new Postgres connection pool with
|
|
49
51
|
* conveience methods for executing queries using
|
|
@@ -57,7 +59,7 @@ export function createPostgres({ onError = () => { }, ...config } = {}) {
|
|
|
57
59
|
async function withConnection(callback) {
|
|
58
60
|
const client = await pool.connect();
|
|
59
61
|
try {
|
|
60
|
-
const result = await callback(new
|
|
62
|
+
const result = await callback(new Connection(client));
|
|
61
63
|
return result;
|
|
62
64
|
}
|
|
63
65
|
finally {
|
|
@@ -82,7 +84,7 @@ export function createPostgres({ onError = () => { }, ...config } = {}) {
|
|
|
82
84
|
const client = await pool.connect();
|
|
83
85
|
try {
|
|
84
86
|
await client.query('BEGIN');
|
|
85
|
-
const result = await callback(new
|
|
87
|
+
const result = await callback(new Transaction(client));
|
|
86
88
|
await client.query('COMMIT');
|
|
87
89
|
return result;
|
|
88
90
|
}
|
package/dist/sentry.d.ts
CHANGED
|
@@ -22,9 +22,9 @@ export declare function createSentryOptions(app: Application | null, options?: S
|
|
|
22
22
|
release?: string | undefined;
|
|
23
23
|
environment?: string | undefined;
|
|
24
24
|
debug?: boolean | undefined;
|
|
25
|
-
dsn: string | undefined;
|
|
26
25
|
instrumenter?: import("@sentry/types").Instrumenter | undefined;
|
|
27
26
|
sampleRate?: number | undefined;
|
|
27
|
+
dsn: string | undefined;
|
|
28
28
|
enabled?: boolean | undefined;
|
|
29
29
|
attachStacktrace?: boolean | undefined;
|
|
30
30
|
autoSessionTracking?: boolean | undefined;
|
|
@@ -32,6 +32,7 @@ export declare function createSentryOptions(app: Application | null, options?: S
|
|
|
32
32
|
dist?: string | undefined;
|
|
33
33
|
transportOptions?: Partial<import("@sentry/node/types/transports/http.js").NodeTransportOptions> | undefined;
|
|
34
34
|
tracesSampleRate: number;
|
|
35
|
+
enableTracing?: boolean | undefined;
|
|
35
36
|
initialScope?: import("@sentry/types").CaptureContext | undefined;
|
|
36
37
|
maxBreadcrumbs?: number | undefined;
|
|
37
38
|
maxValueLength?: number | undefined;
|
|
@@ -39,6 +40,7 @@ export declare function createSentryOptions(app: Application | null, options?: S
|
|
|
39
40
|
normalizeMaxBreadth?: number | undefined;
|
|
40
41
|
shutdownTimeout?: number | undefined;
|
|
41
42
|
ignoreErrors?: (string | RegExp)[] | undefined;
|
|
43
|
+
ignoreTransactions?: (string | RegExp)[] | undefined;
|
|
42
44
|
tunnel?: string | undefined;
|
|
43
45
|
sendDefaultPii?: boolean | undefined;
|
|
44
46
|
_metadata?: import("@sentry/types").SdkMetadata | undefined;
|
|
@@ -52,6 +54,7 @@ export declare function createSentryOptions(app: Application | null, options?: S
|
|
|
52
54
|
beforeSendTransaction?: ((event: import("@sentry/types").TransactionEvent, hint: Sentry.EventHint) => Sentry.Event | PromiseLike<Sentry.Event | null> | null) | undefined;
|
|
53
55
|
beforeBreadcrumb?: ((breadcrumb: Sentry.Breadcrumb, hint?: Sentry.BreadcrumbHint | undefined) => Sentry.Breadcrumb | null) | undefined;
|
|
54
56
|
profilesSampleRate?: number | undefined;
|
|
57
|
+
profilesSampler?: ((samplingContext: import("@sentry/types").SamplingContext) => number | boolean) | undefined;
|
|
55
58
|
serverName?: string | undefined;
|
|
56
59
|
includeLocalVariables?: boolean | undefined;
|
|
57
60
|
tracePropagationTargets?: import("@sentry/types").TracePropagationTargets | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/express-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
],
|
|
35
35
|
"license": "ISC",
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@devmoods/eslint-config": "^1.
|
|
38
|
-
"@types/node": "
|
|
37
|
+
"@devmoods/eslint-config": "^1.1.0",
|
|
38
|
+
"@types/node": "20.2.5",
|
|
39
39
|
"@types/supertest": "2.0.12",
|
|
40
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
41
|
-
"@typescript-eslint/parser": "^5.
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
|
41
|
+
"@typescript-eslint/parser": "^5.59.7",
|
|
42
42
|
"chalk": "^5.2.0",
|
|
43
|
-
"eslint": "^8.
|
|
43
|
+
"eslint": "^8.41.0",
|
|
44
44
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
45
45
|
"eslint-plugin-prettier": "^4.2.1",
|
|
46
46
|
"eslint-plugin-react": "^7.32.2",
|
|
@@ -48,26 +48,26 @@
|
|
|
48
48
|
"import-sort-cli": "6.0.0",
|
|
49
49
|
"import-sort-style-module": "6.0.0",
|
|
50
50
|
"isomorphic-fetch": "3.0.0",
|
|
51
|
-
"prettier": "2.8.
|
|
51
|
+
"prettier": "2.8.8",
|
|
52
52
|
"supertest": "6.3.3",
|
|
53
53
|
"ts-node": "10.9.1",
|
|
54
|
-
"typescript": "
|
|
55
|
-
"vitest": "^0.
|
|
54
|
+
"typescript": "5.0.4",
|
|
55
|
+
"vitest": "^0.31.1"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@devmoods/fetch": "^3.3.0",
|
|
59
|
-
"@godaddy/terminus": "^4.
|
|
60
|
-
"@sentry/node": "^7.
|
|
61
|
-
"@sentry/tracing": "^7.
|
|
59
|
+
"@godaddy/terminus": "^4.12.0",
|
|
60
|
+
"@sentry/node": "^7.53.1",
|
|
61
|
+
"@sentry/tracing": "^7.53.1",
|
|
62
62
|
"@types/bcrypt": "^5.0.0",
|
|
63
63
|
"@types/bunyan": "^1.8.8",
|
|
64
64
|
"@types/cls-hooked": "^4.3.3",
|
|
65
65
|
"@types/cookie-parser": "^1.4.3",
|
|
66
|
-
"@types/express": "^4.17.
|
|
67
|
-
"@types/jsonwebtoken": "^9.0.
|
|
68
|
-
"@types/nodemailer": "^6.4.
|
|
69
|
-
"@types/pg": "^8.
|
|
70
|
-
"@types/uuid": "^9.0.
|
|
66
|
+
"@types/express": "^4.17.17",
|
|
67
|
+
"@types/jsonwebtoken": "^9.0.2",
|
|
68
|
+
"@types/nodemailer": "^6.4.8",
|
|
69
|
+
"@types/pg": "^8.10.1",
|
|
70
|
+
"@types/uuid": "^9.0.1",
|
|
71
71
|
"ajv": "^8.12.0",
|
|
72
72
|
"bcrypt": "^5.1.0",
|
|
73
73
|
"bunyan": "^1.8.15",
|
|
@@ -76,12 +76,12 @@
|
|
|
76
76
|
"cookie-parser": "^1.4.6",
|
|
77
77
|
"dotenv": "^16.0.3",
|
|
78
78
|
"express": "^4.18.2",
|
|
79
|
-
"helmet": "^
|
|
79
|
+
"helmet": "^7.0.0",
|
|
80
80
|
"jsonwebtoken": "^9.0.0",
|
|
81
|
-
"meow": "^
|
|
82
|
-
"nodemailer": "^6.9.
|
|
83
|
-
"pg": "^8.
|
|
84
|
-
"redis": "^4.6.
|
|
81
|
+
"meow": "^12.0.1",
|
|
82
|
+
"nodemailer": "^6.9.3",
|
|
83
|
+
"pg": "^8.11.0",
|
|
84
|
+
"redis": "^4.6.6",
|
|
85
85
|
"sql-template-strings": "^2.2.2",
|
|
86
86
|
"uuid": "^9.0.0"
|
|
87
87
|
},
|