@voxpelli/pg-utils 3.0.1 → 3.1.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/README.md +34 -7
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/lib/csv-folder-to-db.d.ts +5 -1
- package/lib/csv-folder-to-db.d.ts.map +1 -1
- package/lib/csv-folder-to-db.js +53 -3
- package/lib/db-to-csv-folder.d.ts +6 -0
- package/lib/db-to-csv-folder.d.ts.map +1 -0
- package/lib/db-to-csv-folder.js +55 -0
- package/lib/test-helpers.d.ts +1 -0
- package/lib/test-helpers.d.ts.map +1 -1
- package/lib/test-helpers.js +34 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ My personal database utils / helpers for Postgres
|
|
|
7
7
|
[](https://github.com/neostandard/neostandard)
|
|
8
8
|
[](https://github.com/voxpelli/badges-cjs-esm)
|
|
9
9
|
[](https://github.com/voxpelli/types-in-js)
|
|
10
|
+
[](https://deepwiki.com/voxpelli/pg-utils)
|
|
10
11
|
[](https://mastodon.social/@voxpelli)
|
|
11
12
|
|
|
12
13
|
## Usage
|
|
@@ -14,6 +15,7 @@ My personal database utils / helpers for Postgres
|
|
|
14
15
|
```javascript
|
|
15
16
|
import {
|
|
16
17
|
csvFromFolderToDb,
|
|
18
|
+
dbToCsvFolder,
|
|
17
19
|
PgTestHelpers,
|
|
18
20
|
} from '@voxpelli/pg-utils';
|
|
19
21
|
|
|
@@ -22,9 +24,9 @@ const pgHelpers = new PgTestHelpers({
|
|
|
22
24
|
fixtureFolder: new URL('./fixtures', import.meta.url),
|
|
23
25
|
ignoreTables: ['xyz'],
|
|
24
26
|
schema: new URL('./create-tables.sql', import.meta.url),
|
|
25
|
-
|
|
26
|
-
'abc',
|
|
27
|
+
tableLoadOrder: [
|
|
27
28
|
['foo', 'bar'],
|
|
29
|
+
'abc',
|
|
28
30
|
]
|
|
29
31
|
});
|
|
30
32
|
|
|
@@ -55,7 +57,7 @@ new PgTestHelpers({
|
|
|
55
57
|
// ...
|
|
56
58
|
],
|
|
57
59
|
schema: new URL('./create-tables.sql', import.meta.url),
|
|
58
|
-
|
|
60
|
+
tableLoadOrder: [
|
|
59
61
|
// ...
|
|
60
62
|
]
|
|
61
63
|
});
|
|
@@ -71,13 +73,14 @@ new PgTestHelpers({
|
|
|
71
73
|
* `fixtureFolder` – _`[string | URL]`_ – _optional_ – the path to a folder of `.csv`-file fixtures named by their respective table
|
|
72
74
|
* `ignoreTables` – _`[string[]]`_ – _optional_ – names of tables to ignore when dropping
|
|
73
75
|
* `schema` – _`string | URL | Umzug`_ – an umzug instance that can be used to initialize tables or the schema itself or a `URL` to a text file containing the schema
|
|
74
|
-
* `
|
|
76
|
+
* `tableLoadOrder` – _`[Array<string[] | string>]`_ – _optional_ – tables in parent-first insertion order: the first item is loaded first and dropped last. Use nested arrays to group tables that can be dropped in parallel. Mutually exclusive with `tablesWithDependencies`.
|
|
77
|
+
* `tablesWithDependencies` – _`[Array<string[] | string>]`_ – _optional_ – **Deprecated:** use `tableLoadOrder` instead. Tables in leaf-first deletion order: the first item is dropped first and loaded last.
|
|
75
78
|
|
|
76
79
|
### Methods
|
|
77
80
|
|
|
78
81
|
* `initTables() => Promise<void>` – sets up all of the tables. Automatically acquires an exclusive database lock on first call.
|
|
79
82
|
* `insertFixtures() => Promise<void>` – inserts all the fixtures data into the tables (only usable if `fixtureFolder` has been set). Automatically acquires an exclusive database lock on first call.
|
|
80
|
-
* `removeTables() => Promise<void>` – removes all of the tables (
|
|
83
|
+
* `removeTables() => Promise<void>` – removes all of the tables (respecting `tableLoadOrder` / `tablesWithDependencies` ordering). Automatically acquires an exclusive database lock on first call.
|
|
81
84
|
* `end() => Promise<void>` – releases the database lock (if acquired) and closes all database connections. **Always call this when done** to properly clean up resources.
|
|
82
85
|
|
|
83
86
|
#### Database Locking
|
|
@@ -91,14 +94,38 @@ Imports data into tables from a folder of CSV files. All files will be imported
|
|
|
91
94
|
### Syntax
|
|
92
95
|
|
|
93
96
|
```ts
|
|
94
|
-
csvFromFolderToDb(pool, path, [
|
|
97
|
+
csvFromFolderToDb(pool, path, [options]) => Promise<void>
|
|
95
98
|
```
|
|
96
99
|
|
|
97
100
|
### Arguments
|
|
98
101
|
|
|
99
102
|
* `pool` – _`string | pg.Pool`_ – a postgres pool to use for the queries or a connection string that will be used to create one
|
|
100
103
|
* `path` – _`string | URL`_ – the path to the folder that contains the CSV:s named by their table names
|
|
101
|
-
* `
|
|
104
|
+
* `options` – _`object`_ – _optional_ – ordering options (also accepts a `string[]` for backwards compatibility, treated as `tablesWithDependencies`)
|
|
105
|
+
* `tableLoadOrder` – _`string[]`_ – tables in parent-first insertion order: the first table is loaded first. Mutually exclusive with `tablesWithDependencies`.
|
|
106
|
+
* `tablesWithDependencies` – _`string[]`_ – **Deprecated:** use `tableLoadOrder` instead. Tables in leaf-first deletion order: the first table is loaded last.
|
|
107
|
+
|
|
108
|
+
### Returns
|
|
109
|
+
|
|
110
|
+
`Promise` that resolves on completion
|
|
111
|
+
|
|
112
|
+
## dbToCsvFolder()
|
|
113
|
+
|
|
114
|
+
Exports database tables to CSV files in a folder. Each table is written as `<table>.csv` with a header row.
|
|
115
|
+
|
|
116
|
+
### Syntax
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
dbToCsvFolder(connection, outputPath, tables, [options]) => Promise<void>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Arguments
|
|
123
|
+
|
|
124
|
+
* `connection` – _`string | pg.Pool`_ – a postgres pool to use for the queries or a connection string that will be used to create one
|
|
125
|
+
* `outputPath` – _`string | URL`_ – the directory to write CSV files into (created if it does not exist)
|
|
126
|
+
* `tables` – _`string[]`_ – explicit list of table names to export
|
|
127
|
+
* `options` – _`object`_ – _optional_
|
|
128
|
+
* `orderBy` – _`string`_ – SQL `ORDER BY` expression for deterministic output (default: `'1'`, i.e. the first column)
|
|
102
129
|
|
|
103
130
|
### Returns
|
|
104
131
|
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
export function csvFromFolderToDb(connection: string | Pool, path: string | URL,
|
|
1
|
+
export function csvFromFolderToDb(connection: string | Pool, path: string | URL, options?: string[] | CsvFromFolderToDbOptions): Promise<void>;
|
|
2
|
+
export type CsvFromFolderToDbOptions = {
|
|
3
|
+
tableLoadOrder?: string[];
|
|
4
|
+
tablesWithDependencies?: string[];
|
|
5
|
+
};
|
|
2
6
|
import type { Pool } from 'pg';
|
|
3
7
|
//# sourceMappingURL=csv-folder-to-db.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csv-folder-to-db.d.ts","sourceRoot":"","sources":["csv-folder-to-db.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"csv-folder-to-db.d.ts","sourceRoot":"","sources":["csv-folder-to-db.js"],"names":[],"mappings":"AAkHA,8CALW,MAAM,GAAG,IAAI,QACb,MAAM,GAAG,GAAG,YACZ,MAAM,EAAE,GAAG,wBAAwB,GACjC,OAAO,CAAC,IAAI,CAAC,CA2BzB;;qBA1Ea,MAAM,EAAE;6BACR,MAAM,EAAE;;0BAvDI,IAAI"}
|
package/lib/csv-folder-to-db.js
CHANGED
|
@@ -5,6 +5,7 @@ import { pipeline as promisedPipeline } from 'node:stream/promises';
|
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
|
|
7
7
|
import { from as copyFrom } from 'pg-copy-streams';
|
|
8
|
+
import pg from 'pg';
|
|
8
9
|
|
|
9
10
|
import { createPgPool } from './utils.js';
|
|
10
11
|
|
|
@@ -57,13 +58,62 @@ async function getFilesOrderedByDependencies (path, tablesWithDependencies) {
|
|
|
57
58
|
];
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
/** @type {boolean} */
|
|
62
|
+
let hasWarnedDeprecation = false;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @typedef CsvFromFolderToDbOptions
|
|
66
|
+
* @property {string[]} [tableLoadOrder] Tables in parent-first insertion order (first item loaded first, dropped last)
|
|
67
|
+
* @property {string[]} [tablesWithDependencies] Deprecated: use `tableLoadOrder` instead. Tables in leaf-first deletion order (first item dropped first, loaded last)
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string[] | CsvFromFolderToDbOptions | undefined} options
|
|
72
|
+
* @returns {string[]}
|
|
73
|
+
*/
|
|
74
|
+
function resolveTableOrder (options) {
|
|
75
|
+
if (!options) return [];
|
|
76
|
+
if (Array.isArray(options)) {
|
|
77
|
+
warnDeprecation();
|
|
78
|
+
return options;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { tableLoadOrder, tablesWithDependencies } = options;
|
|
82
|
+
|
|
83
|
+
if (tableLoadOrder && tablesWithDependencies) {
|
|
84
|
+
throw new Error('Cannot specify both tableLoadOrder and tablesWithDependencies');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (tablesWithDependencies) {
|
|
88
|
+
warnDeprecation();
|
|
89
|
+
return tablesWithDependencies;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (tableLoadOrder) {
|
|
93
|
+
// tableLoadOrder is parent-first; reverse to get the leaf-first
|
|
94
|
+
// order that getFilesOrderedByDependencies expects via unshift()
|
|
95
|
+
return [...tableLoadOrder].reverse();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function warnDeprecation () {
|
|
102
|
+
if (!hasWarnedDeprecation) {
|
|
103
|
+
hasWarnedDeprecation = true;
|
|
104
|
+
// eslint-disable-next-line no-console
|
|
105
|
+
console.warn('@voxpelli/pg-utils: tablesWithDependencies is deprecated, use tableLoadOrder instead (parent-first insertion order)');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
60
109
|
/**
|
|
61
110
|
* @param {string | Pool} connection
|
|
62
111
|
* @param {string | URL} path
|
|
63
|
-
* @param {string[] |
|
|
112
|
+
* @param {string[] | CsvFromFolderToDbOptions} [options]
|
|
64
113
|
* @returns {Promise<void>}
|
|
65
114
|
*/
|
|
66
|
-
export async function csvFromFolderToDb (connection, path,
|
|
115
|
+
export async function csvFromFolderToDb (connection, path, options) {
|
|
116
|
+
const tablesWithDependencies = resolveTableOrder(options);
|
|
67
117
|
const files = await getFilesOrderedByDependencies(path, tablesWithDependencies);
|
|
68
118
|
|
|
69
119
|
const pool = (typeof connection === 'object' && 'connect' in connection) ? connection : createPgPool(connection);
|
|
@@ -73,7 +123,7 @@ export async function csvFromFolderToDb (connection, path, tablesWithDependencie
|
|
|
73
123
|
try {
|
|
74
124
|
for (const file of files) {
|
|
75
125
|
const name = pathModule.basename(file, '.csv');
|
|
76
|
-
const dbCopy = client.query(copyFrom(`COPY ${name} FROM STDIN WITH (FORMAT csv, HEADER MATCH)`));
|
|
126
|
+
const dbCopy = client.query(copyFrom(`COPY ${pg.escapeIdentifier(name)} FROM STDIN WITH (FORMAT csv, HEADER MATCH)`));
|
|
77
127
|
|
|
78
128
|
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
79
129
|
const csvContent = createReadStream(file);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export function dbToCsvFolder(connection: string | Pool, outputPath: string | URL, tables: string[], options?: DbToCsvFolderOptions): Promise<void>;
|
|
2
|
+
export type DbToCsvFolderOptions = {
|
|
3
|
+
orderBy?: string;
|
|
4
|
+
};
|
|
5
|
+
import type { Pool } from 'pg';
|
|
6
|
+
//# sourceMappingURL=db-to-csv-folder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-to-csv-folder.d.ts","sourceRoot":"","sources":["db-to-csv-folder.js"],"names":[],"mappings":"AA8BA,0CANW,MAAM,GAAG,IAAI,cACb,MAAM,GAAG,GAAG,UACZ,MAAM,EAAE,YACR,oBAAoB,GAClB,OAAO,CAAC,IAAI,CAAC,CA0BzB;;cAvCa,MAAM;;0BAJM,IAAI"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
|
+
import pathModule from 'node:path';
|
|
4
|
+
import { pipeline } from 'node:stream/promises';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
import pg from 'pg';
|
|
8
|
+
import { to as copyTo } from 'pg-copy-streams';
|
|
9
|
+
|
|
10
|
+
import { createPgPool } from './utils.js';
|
|
11
|
+
|
|
12
|
+
/** @import { Pool } from 'pg' */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef DbToCsvFolderOptions
|
|
16
|
+
* @property {string} [orderBy]
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Exports database tables to CSV files in a folder.
|
|
21
|
+
*
|
|
22
|
+
* Each table is exported as `<table>.csv` with a header row, ordered by
|
|
23
|
+
* the specified column (default: first column) for deterministic output.
|
|
24
|
+
*
|
|
25
|
+
* @param {string | Pool} connection
|
|
26
|
+
* @param {string | URL} outputPath
|
|
27
|
+
* @param {string[]} tables
|
|
28
|
+
* @param {DbToCsvFolderOptions} [options]
|
|
29
|
+
* @returns {Promise<void>}
|
|
30
|
+
*/
|
|
31
|
+
export async function dbToCsvFolder (connection, outputPath, tables, options = {}) {
|
|
32
|
+
const { orderBy = '1' } = options;
|
|
33
|
+
|
|
34
|
+
const dirPath = typeof outputPath === 'string' ? outputPath : fileURLToPath(outputPath);
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
37
|
+
await mkdir(dirPath, { recursive: true });
|
|
38
|
+
|
|
39
|
+
const pool = (typeof connection === 'object' && 'connect' in connection) ? connection : createPgPool(connection);
|
|
40
|
+
|
|
41
|
+
const client = await pool.connect();
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
for (const table of tables) {
|
|
45
|
+
const sql = `COPY (SELECT * FROM ${pg.escapeIdentifier(table)} ORDER BY ${orderBy}) TO STDOUT WITH (FORMAT csv, HEADER true)`;
|
|
46
|
+
const copyToStream = client.query(copyTo(sql));
|
|
47
|
+
const filePath = pathModule.join(dirPath, `${table}.csv`);
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
50
|
+
await pipeline(copyToStream, createWriteStream(filePath));
|
|
51
|
+
}
|
|
52
|
+
} finally {
|
|
53
|
+
client.release();
|
|
54
|
+
}
|
|
55
|
+
}
|
package/lib/test-helpers.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type PgTestHelpersOptions = {
|
|
|
12
12
|
fixtureFolder?: string | URL;
|
|
13
13
|
ignoreTables?: string[];
|
|
14
14
|
schema: string | URL | ((pool: Pool) => import("umzug").Umzug<import("umzeption").UmzeptionContext<"pg", import("umzeption").FastifyPostgresStyleDb>>);
|
|
15
|
+
tableLoadOrder?: Array<string[] | string>;
|
|
15
16
|
tablesWithDependencies?: Array<string[] | string>;
|
|
16
17
|
};
|
|
17
18
|
import type { Pool } from 'pg';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["test-helpers.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["test-helpers.js"],"names":[],"mappings":"AAuBA;IAuBE,qBADY,oBAAoB,EAoD/B;IAtDD,cADW,IAAI,CAAC,OAAO,CAAC,CACX;IA8Hb,cADc,OAAO,CAAC,IAAI,CAAC,CAmB1B;IAGD,kBADc,OAAO,CAAC,IAAI,CAAC,CAkB1B;IAGD,gBADc,OAAO,CAAC,IAAI,CAAC,CAgB1B;IAGD,OADc,OAAO,CAAC,IAAI,CAAC,CAO1B;;CACF;;sBA5Na,MAAM;oBACN,MAAM,GAAG,GAAG;mBACZ,MAAM,EAAE;YACR,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,OAAO,EAAE,KAAK,CAAC,OAAO,WAAW,EAAE,gBAAgB,CAAC,IAAI,EAAE,OAAO,WAAW,EAAE,sBAAsB,CAAC,CAAC,CAAC;qBAC9I,KAAK,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC;6BACxB,KAAK,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC;;0BATJ,IAAI"}
|
package/lib/test-helpers.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
|
|
3
|
+
import pg from 'pg';
|
|
3
4
|
import {
|
|
4
5
|
createUmzeptionPgContext,
|
|
5
6
|
pgInstallSchemaFromString,
|
|
@@ -16,7 +17,8 @@ import { createPgPool, createAndLockConnection, releaseLock, isStringArray, Type
|
|
|
16
17
|
* @property {string | URL} [fixtureFolder]
|
|
17
18
|
* @property {string[]} [ignoreTables]
|
|
18
19
|
* @property {string | URL | ((pool: Pool) => import('umzug').Umzug<import('umzeption').UmzeptionContext<'pg', import('umzeption').FastifyPostgresStyleDb>>)} schema
|
|
19
|
-
* @property {Array<string[] | string>} [tablesWithDependencies
|
|
20
|
+
* @property {Array<string[] | string>} [tableLoadOrder] Tables in parent-first insertion order. First item loaded first, dropped last. Mutually exclusive with `tablesWithDependencies`.
|
|
21
|
+
* @property {Array<string[] | string>} [tablesWithDependencies] Deprecated: use `tableLoadOrder` instead. Tables in leaf-first deletion order. First item dropped first, loaded last.
|
|
20
22
|
*/
|
|
21
23
|
|
|
22
24
|
export class PgTestHelpers {
|
|
@@ -36,6 +38,8 @@ export class PgTestHelpers {
|
|
|
36
38
|
#schema;
|
|
37
39
|
/** @type {Array<string[] | string> | undefined} */
|
|
38
40
|
#tablesWithDependencies;
|
|
41
|
+
/** @type {string[] | undefined} */
|
|
42
|
+
#tableLoadOrder;
|
|
39
43
|
/** @type {Pool['query']} */
|
|
40
44
|
queryPromise;
|
|
41
45
|
|
|
@@ -50,6 +54,7 @@ export class PgTestHelpers {
|
|
|
50
54
|
fixtureFolder,
|
|
51
55
|
ignoreTables,
|
|
52
56
|
schema,
|
|
57
|
+
tableLoadOrder,
|
|
53
58
|
tablesWithDependencies,
|
|
54
59
|
} = options;
|
|
55
60
|
|
|
@@ -65,16 +70,28 @@ export class PgTestHelpers {
|
|
|
65
70
|
if (typeof schema !== 'string' && typeof schema !== 'object' && typeof schema !== 'function') {
|
|
66
71
|
throw new TypeNeverError(schema, 'Invalid schema, expected a string, object or function');
|
|
67
72
|
}
|
|
73
|
+
if (tableLoadOrder && tablesWithDependencies) {
|
|
74
|
+
throw new Error('Cannot specify both tableLoadOrder and tablesWithDependencies');
|
|
75
|
+
}
|
|
76
|
+
if (tableLoadOrder && !Array.isArray(tableLoadOrder)) {
|
|
77
|
+
throw new TypeNeverError(tableLoadOrder, 'Invalid tableLoadOrder, expected an array');
|
|
78
|
+
}
|
|
68
79
|
if (tablesWithDependencies && !Array.isArray(tablesWithDependencies)) {
|
|
69
80
|
throw new TypeNeverError(tablesWithDependencies, 'Invalid tablesWithDependencies, expected an array');
|
|
70
81
|
}
|
|
71
82
|
|
|
72
83
|
const pool = createPgPool(connectionString);
|
|
73
84
|
|
|
85
|
+
// tableLoadOrder is parent-first; reverse to get the leaf-first
|
|
86
|
+
// order that internal methods expect (drop first item first, load last)
|
|
87
|
+
this.#tablesWithDependencies = tableLoadOrder
|
|
88
|
+
? [...tableLoadOrder].reverse()
|
|
89
|
+
: tablesWithDependencies;
|
|
90
|
+
this.#tableLoadOrder = tableLoadOrder?.flat();
|
|
91
|
+
|
|
74
92
|
this.#connectionString = connectionString;
|
|
75
93
|
this.#fixtureFolder = fixtureFolder;
|
|
76
94
|
this.#ignoreTables = ignoreTables;
|
|
77
|
-
this.#tablesWithDependencies = tablesWithDependencies;
|
|
78
95
|
this.#pool = pool;
|
|
79
96
|
this.#schema = schema;
|
|
80
97
|
this.queryPromise = pool.query.bind(pool);
|
|
@@ -94,7 +111,7 @@ export class PgTestHelpers {
|
|
|
94
111
|
async #removeTablesByName (tables, allowParallelRemoval = false) {
|
|
95
112
|
if (allowParallelRemoval && isStringArray(tables)) {
|
|
96
113
|
await Promise.all(
|
|
97
|
-
tables.map(name => this.queryPromise('DROP TABLE IF EXISTS ' + name + ' CASCADE'))
|
|
114
|
+
tables.map(name => this.queryPromise('DROP TABLE IF EXISTS ' + pg.escapeIdentifier(/** @type {string} */ (name)) + ' CASCADE'))
|
|
98
115
|
).catch(cause => {
|
|
99
116
|
throw new Error(`Failed to drop tables: ${tables}`, { cause });
|
|
100
117
|
});
|
|
@@ -103,7 +120,7 @@ export class PgTestHelpers {
|
|
|
103
120
|
await (
|
|
104
121
|
Array.isArray(name)
|
|
105
122
|
? this.#removeTablesByName(name, true)
|
|
106
|
-
: this.queryPromise('DROP TABLE IF EXISTS ' + name + ' CASCADE').catch(cause => {
|
|
123
|
+
: this.queryPromise('DROP TABLE IF EXISTS ' + pg.escapeIdentifier(/** @type {string} */ (name)) + ' CASCADE').catch(cause => {
|
|
107
124
|
throw new Error(`Failed to drop table: ${name}`, { cause });
|
|
108
125
|
})
|
|
109
126
|
);
|
|
@@ -132,6 +149,9 @@ export class PgTestHelpers {
|
|
|
132
149
|
this.#lockClient = createAndLockConnection(this.#connectionString).then(result => {
|
|
133
150
|
this.#lockClient = result;
|
|
134
151
|
return result;
|
|
152
|
+
}, (err) => {
|
|
153
|
+
this.#lockClient = undefined;
|
|
154
|
+
throw err;
|
|
135
155
|
});
|
|
136
156
|
}
|
|
137
157
|
|
|
@@ -175,7 +195,16 @@ export class PgTestHelpers {
|
|
|
175
195
|
|
|
176
196
|
await this.#ensureLocked();
|
|
177
197
|
|
|
178
|
-
|
|
198
|
+
/** @type {import('./csv-folder-to-db.js').CsvFromFolderToDbOptions | undefined} */
|
|
199
|
+
let options;
|
|
200
|
+
|
|
201
|
+
if (this.#tableLoadOrder) {
|
|
202
|
+
options = { tableLoadOrder: this.#tableLoadOrder };
|
|
203
|
+
} else if (this.#tablesWithDependencies) {
|
|
204
|
+
options = { tablesWithDependencies: this.#tablesWithDependencies.flat() };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return csvFromFolderToDb(this.#pool, this.#fixtureFolder, options);
|
|
179
208
|
}
|
|
180
209
|
|
|
181
210
|
/** @returns {Promise<void>} */
|