@kern-orm/node-postgres 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +21 -2
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +131 -0
- package/package.json +57 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ilya Semenov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @kern-orm/node-postgres
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[node-postgres](https://node-postgres.com/) driver for [kern-orm](https://github.com/IlyaSemenov/kern-orm).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install kern-orm @kern-orm/node-postgres pg
|
|
9
|
+
npm install --save-dev @types/pg
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { nodePostgresDriver } from "@kern-orm/node-postgres"
|
|
16
|
+
import { createDatabase } from "kern-orm"
|
|
17
|
+
import { Pool } from "pg"
|
|
18
|
+
|
|
19
|
+
const database = createDatabase({
|
|
20
|
+
driver: nodePostgresDriver(new Pool({ connectionString: process.env.DATABASE_URL })),
|
|
21
|
+
})
|
|
22
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Driver } from "kern-orm";
|
|
2
|
+
import { Pool } from "pg";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a kern-orm driver over a node-postgres pool; the pool keeps managing its connections.
|
|
5
|
+
*
|
|
6
|
+
* Closing the driver ends the supplied pool.
|
|
7
|
+
*/
|
|
8
|
+
export declare function nodePostgresDriver(pool: Pool): Driver;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// src/driver.ts
|
|
2
|
+
/** Parsers of a query that keep every value as its text, whatever parsers the client has. */
|
|
3
|
+
const textTypes = { getTypeParser: () => (value) => value };
|
|
4
|
+
/**
|
|
5
|
+
* Returns why the driver cannot read the values of a client as text, if it cannot.
|
|
6
|
+
*
|
|
7
|
+
* `pg` sets `native` and `binary` on a client, though its types omit them.
|
|
8
|
+
*/
|
|
9
|
+
function getUnsupportedClientReason(client) {
|
|
10
|
+
if (client.native) return "nodePostgresDriver requires the JavaScript client: create the pool with pg, not pg.native";
|
|
11
|
+
if (client.binary) return "nodePostgresDriver requires text results: disable binary in the options of the pool and in pg.defaults";
|
|
12
|
+
}
|
|
13
|
+
/** Listener of the `error` event of a pool or a client, for a connection whose loss needs no handling at the event; an `EventEmitter` throws an `error` event without a listener, which terminates the process. */
|
|
14
|
+
function ignoreConnectionError() {}
|
|
15
|
+
/** Handler of the outcome of a statement that the queue of a connection waits for without reading it. */
|
|
16
|
+
function ignoreOutcome() {}
|
|
17
|
+
/**
|
|
18
|
+
* Tells whether PostgreSQL rejected a statement and keeps its connection, such as for a violated constraint.
|
|
19
|
+
*
|
|
20
|
+
* After other failures, such as `query_timeout`, the statement may still run, or the connection is closing.
|
|
21
|
+
* A server with translated messages reports a translated severity, so its connection closes, which only costs a reconnect.
|
|
22
|
+
*/
|
|
23
|
+
function isRejectedStatement(error) {
|
|
24
|
+
return error.severity === "ERROR";
|
|
25
|
+
}
|
|
26
|
+
async function execute(client, statement) {
|
|
27
|
+
const config = {
|
|
28
|
+
text: statement.text,
|
|
29
|
+
values: statement.parameters,
|
|
30
|
+
rowMode: "array",
|
|
31
|
+
types: textTypes,
|
|
32
|
+
queryMode: "extended"
|
|
33
|
+
};
|
|
34
|
+
const result = await client.query(config);
|
|
35
|
+
const { fields } = result;
|
|
36
|
+
const columns = [];
|
|
37
|
+
for (let index = 0; index < fields.length; index++) columns.push(fields[index].name);
|
|
38
|
+
return {
|
|
39
|
+
command: result.command,
|
|
40
|
+
count: result.rowCount ?? 0,
|
|
41
|
+
columns,
|
|
42
|
+
rows: result.rows
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function executeScript(client, text) {
|
|
46
|
+
await client.query({
|
|
47
|
+
text,
|
|
48
|
+
rowMode: "array",
|
|
49
|
+
types: textTypes
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates a kern-orm driver over a node-postgres pool; the pool keeps managing its connections.
|
|
54
|
+
*
|
|
55
|
+
* Closing the driver ends the supplied pool.
|
|
56
|
+
*/
|
|
57
|
+
function nodePostgresDriver(pool) {
|
|
58
|
+
let checkouts = 0;
|
|
59
|
+
let drained;
|
|
60
|
+
let closing;
|
|
61
|
+
pool.on("error", ignoreConnectionError);
|
|
62
|
+
pool.on("acquire", (client) => client.on("error", ignoreConnectionError));
|
|
63
|
+
pool.on("release", (_error, client) => client.off("error", ignoreConnectionError));
|
|
64
|
+
function endCheckout() {
|
|
65
|
+
if (--checkouts === 0) drained?.resolve();
|
|
66
|
+
}
|
|
67
|
+
async function checkOut() {
|
|
68
|
+
if (closing) throw new Error("Cannot acquire a connection: the driver is closed");
|
|
69
|
+
checkouts++;
|
|
70
|
+
try {
|
|
71
|
+
const client = await pool.connect();
|
|
72
|
+
const unsupported = getUnsupportedClientReason(client);
|
|
73
|
+
if (unsupported) {
|
|
74
|
+
client.release();
|
|
75
|
+
throw new Error(unsupported);
|
|
76
|
+
}
|
|
77
|
+
return client;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
endCheckout();
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Returns a client to the pool, which closes it with `destroy` or when its connection is lost. */
|
|
84
|
+
function checkIn(client, destroy) {
|
|
85
|
+
client.release(destroy);
|
|
86
|
+
endCheckout();
|
|
87
|
+
}
|
|
88
|
+
/** Runs a statement or a script on a client of its own, unlike `pool.query`, which closes the connection of any failed statement. */
|
|
89
|
+
async function runOnPool(run) {
|
|
90
|
+
const client = await checkOut();
|
|
91
|
+
let destroy = false;
|
|
92
|
+
try {
|
|
93
|
+
return await run(client);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
destroy = !isRejectedStatement(error);
|
|
96
|
+
throw error;
|
|
97
|
+
} finally {
|
|
98
|
+
checkIn(client, destroy);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function endPool() {
|
|
102
|
+
if (checkouts > 0) {
|
|
103
|
+
drained = Promise.withResolvers();
|
|
104
|
+
await drained.promise;
|
|
105
|
+
}
|
|
106
|
+
await pool.end();
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
execute: (statement) => runOnPool((client) => execute(client, statement)),
|
|
110
|
+
executeScript: (text) => runOnPool((client) => executeScript(client, text)),
|
|
111
|
+
async acquire() {
|
|
112
|
+
const client = await checkOut();
|
|
113
|
+
let last = Promise.resolve();
|
|
114
|
+
function enqueue(run) {
|
|
115
|
+
const result = last.then(run);
|
|
116
|
+
last = result.then(ignoreOutcome, ignoreOutcome);
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
execute: (statement) => enqueue(() => execute(client, statement)),
|
|
121
|
+
executeScript: (text) => enqueue(() => executeScript(client, text)),
|
|
122
|
+
release: (failure) => checkIn(client, failure !== void 0)
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
close() {
|
|
126
|
+
closing ??= endPool();
|
|
127
|
+
return closing;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export { nodePostgresDriver };
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kern-orm/node-postgres",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "node-postgres driver for kern-orm",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"driver",
|
|
7
|
+
"kern-orm",
|
|
8
|
+
"node-postgres",
|
|
9
|
+
"pg",
|
|
10
|
+
"postgres",
|
|
11
|
+
"postgresql"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://ilyasemenov.github.io/kern-orm/",
|
|
14
|
+
"bugs": "https://github.com/IlyaSemenov/kern-orm/issues",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "Ilya Semenov",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/IlyaSemenov/kern-orm.git",
|
|
20
|
+
"directory": "packages/node-postgres"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"README.md",
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"types": "./dist/index.d.mts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./dist/index.mjs",
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown",
|
|
38
|
+
"prepublishOnly": "bun run build"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/pg": "^8.23.1",
|
|
42
|
+
"kern-orm": "workspace:*",
|
|
43
|
+
"pg": "^8.23.1"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@types/pg": "^8.0.0",
|
|
47
|
+
"kern-orm": ">=0.2.0 <1",
|
|
48
|
+
"pg": "^8.23.1"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@types/pg": {
|
|
52
|
+
"optional": true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"bun": ">=1.4",
|
|
57
|
+
"node": ">=24"
|
|
58
|
+
}
|
|
59
|
+
}
|