@coffre/db 0.14.4 → 0.15.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 +2 -1
- package/dist/change-records-_fKvahvs.js +55 -0
- package/dist/connect.d.ts +22 -10
- package/dist/connect.js +74 -12
- package/dist/database-CVteLhp1.d.ts +410 -0
- package/dist/{database-BadNeeN-.js → database-D55ENPX-.js} +46 -25
- package/dist/dialect.d.ts +4 -3
- package/dist/dialect.js +14 -5
- package/dist/grants.d.ts +4 -4
- package/dist/grants.js +4 -4
- package/dist/hyperdrive.d.ts +48 -23
- package/dist/hyperdrive.js +168 -91
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/log-DaD7fyUq.d.ts +722 -0
- package/dist/log.d.ts +2 -596
- package/dist/log.js +224 -10
- package/dist/migrate.d.ts +43 -3
- package/dist/migrate.js +149 -29
- package/dist/migrations/postgres/0021_prune_vault_releases.sql +19 -0
- package/dist/migrations/postgres/0022_log_015.sql +672 -0
- package/dist/migrations/postgres/0023_change_path.sql +153 -0
- package/dist/migrations/postgres/0024_use_015.sql +556 -0
- package/dist/migrations/postgres/0025_app_change.sql +221 -0
- package/dist/migrations/postgres/0026_issue_lock.sql +106 -0
- package/dist/migrations/postgres/0027_retention.sql +118 -0
- package/dist/migrations/postgres/0028_use_stalls.sql +594 -0
- package/dist/migrations/postgres/0029_use_objects.sql +887 -0
- package/dist/migrations/postgres/0030_unarchive_restores.sql +259 -0
- package/dist/migrations/postgres/0031_app_read.sql +65 -0
- package/dist/migrations/postgres/0032_secrets_live_index.sql +4 -0
- package/dist/migrations/postgres/0033_use_generations.sql +582 -0
- package/dist/migrations/postgres/0034_vault_credentials.sql +153 -0
- package/dist/migrations/postgres/0035_first_days.sql +3 -0
- package/dist/migrations/postgres/0036_vault_issues.sql +91 -0
- package/dist/migrations/postgres/0037_vault_bindings.sql +271 -0
- package/dist/migrations/postgres/0040_binding_origin.sql +159 -0
- package/dist/migrations/postgres/0041_cutover.sql +132 -0
- package/dist/migrations/postgres/0042_sign_in_index.sql +7 -0
- package/dist/migrations/postgres/0043_issue_revoke_index.sql +4 -0
- package/dist/migrations/postgres/0044_use_by_name.sql +705 -0
- package/dist/migrations/postgres/0045_decide_first.sql +878 -0
- package/dist/migrations/postgres/0046_way_in_uses.sql +1149 -0
- package/dist/migrations/postgres/0047_cutover_finish.sql +268 -0
- package/dist/migrations/postgres/0048_use_batch.sql +59 -0
- package/dist/migrations/postgres/0049_reads.sql +171 -0
- package/dist/migrations/postgres/meta/0021_snapshot.json +3334 -0
- package/dist/migrations/postgres/meta/0022_snapshot.json +3831 -0
- package/dist/migrations/postgres/meta/0023_snapshot.json +3831 -0
- package/dist/migrations/postgres/meta/0024_snapshot.json +3831 -0
- package/dist/migrations/postgres/meta/0025_snapshot.json +3831 -0
- package/dist/migrations/postgres/meta/0026_snapshot.json +3831 -0
- package/dist/migrations/postgres/meta/0027_snapshot.json +3853 -0
- package/dist/migrations/postgres/meta/0028_snapshot.json +3853 -0
- package/dist/migrations/postgres/meta/0029_snapshot.json +3859 -0
- package/dist/migrations/postgres/meta/0030_snapshot.json +3859 -0
- package/dist/migrations/postgres/meta/0031_snapshot.json +3859 -0
- package/dist/migrations/postgres/meta/0032_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0033_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0034_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0035_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0036_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0037_snapshot.json +3875 -0
- package/dist/migrations/postgres/meta/0038_snapshot.json +3881 -0
- package/dist/migrations/postgres/meta/0039_snapshot.json +3881 -0
- package/dist/migrations/postgres/meta/0040_snapshot.json +3931 -0
- package/dist/migrations/postgres/meta/0041_snapshot.json +3981 -0
- package/dist/migrations/postgres/meta/0042_snapshot.json +3981 -0
- package/dist/migrations/postgres/meta/0043_snapshot.json +3981 -0
- package/dist/migrations/postgres/meta/0044_snapshot.json +3991 -0
- package/dist/migrations/postgres/meta/0045_snapshot.json +3997 -0
- package/dist/migrations/postgres/meta/0046_snapshot.json +3997 -0
- package/dist/migrations/postgres/meta/0047_snapshot.json +4234 -0
- package/dist/migrations/postgres/meta/_journal.json +189 -0
- package/dist/migrations/sqlite/0018_log_015.sql +84 -0
- package/dist/migrations/sqlite/0019_retention.sql +2 -0
- package/dist/migrations/sqlite/0020_ended_references.sql +1 -0
- package/dist/migrations/sqlite/0021_secrets_live_index.sql +1 -0
- package/dist/migrations/sqlite/0022_binding_origin.sql +1 -0
- package/dist/migrations/sqlite/0023_sign_in_index.sql +2 -0
- package/dist/migrations/sqlite/0024_issue_revoke_index.sql +2 -0
- package/dist/migrations/sqlite/0025_way_in_uses.sql +42 -0
- package/dist/migrations/sqlite/0026_cutover_finish.sql +11 -0
- package/dist/migrations/sqlite/0027_reads.sql +38 -0
- package/dist/migrations/sqlite/meta/0018_snapshot.json +3529 -0
- package/dist/migrations/sqlite/meta/0019_snapshot.json +3538 -0
- package/dist/migrations/sqlite/meta/0020_snapshot.json +3545 -0
- package/dist/migrations/sqlite/meta/0021_snapshot.json +3553 -0
- package/dist/migrations/sqlite/meta/0022_snapshot.json +3560 -0
- package/dist/migrations/sqlite/meta/0023_snapshot.json +3579 -0
- package/dist/migrations/sqlite/meta/0024_snapshot.json +3598 -0
- package/dist/migrations/sqlite/meta/0025_snapshot.json +3609 -0
- package/dist/migrations/sqlite/meta/0026_snapshot.json +3616 -0
- package/dist/migrations/sqlite/meta/0027_snapshot.json +3834 -0
- package/dist/migrations/sqlite/meta/_journal.json +70 -0
- package/dist/platform-Y3gICK6n.d.ts +58 -0
- package/dist/portable.d.ts +2 -2
- package/dist/postgres-BI3xTnyw.js +1718 -0
- package/dist/postgres-platform-node.d.ts +14 -0
- package/dist/postgres-platform-node.js +21 -0
- package/dist/postgres-platform-workerd.d.ts +61 -0
- package/dist/postgres-platform-workerd.js +163 -0
- package/dist/{schema-z8GcN_Xu.d.ts → schema-DgoPqqsI.d.ts} +1329 -9
- package/dist/schema-sqlite.d.ts +1308 -8
- package/dist/schema-sqlite.js +156 -20
- package/dist/schema-version.d.ts +1 -1
- package/dist/schema-version.js +261 -2
- package/dist/schema.d.ts +2 -2
- package/dist/schema.js +229 -22
- package/package.json +13 -5
- package/src/active-subject.ts +9 -0
- package/src/change-records.ts +38 -0
- package/src/connect.ts +67 -13
- package/src/database.ts +67 -51
- package/src/dialect.ts +17 -8
- package/src/grants.ts +3 -3
- package/src/hyperdrive.ts +181 -104
- package/src/log.ts +244 -11
- package/src/migrate.ts +157 -30
- package/src/migrations/postgres/0021_prune_vault_releases.sql +19 -0
- package/src/migrations/postgres/0022_log_015.sql +672 -0
- package/src/migrations/postgres/0023_change_path.sql +153 -0
- package/src/migrations/postgres/0024_use_015.sql +556 -0
- package/src/migrations/postgres/0025_app_change.sql +221 -0
- package/src/migrations/postgres/0026_issue_lock.sql +106 -0
- package/src/migrations/postgres/0027_retention.sql +118 -0
- package/src/migrations/postgres/0028_use_stalls.sql +594 -0
- package/src/migrations/postgres/0029_use_objects.sql +887 -0
- package/src/migrations/postgres/0030_unarchive_restores.sql +259 -0
- package/src/migrations/postgres/0031_app_read.sql +65 -0
- package/src/migrations/postgres/0032_secrets_live_index.sql +4 -0
- package/src/migrations/postgres/0033_use_generations.sql +582 -0
- package/src/migrations/postgres/0034_vault_credentials.sql +153 -0
- package/src/migrations/postgres/0035_first_days.sql +3 -0
- package/src/migrations/postgres/0036_vault_issues.sql +91 -0
- package/src/migrations/postgres/0037_vault_bindings.sql +271 -0
- package/src/migrations/postgres/0040_binding_origin.sql +159 -0
- package/src/migrations/postgres/0041_cutover.sql +132 -0
- package/src/migrations/postgres/0042_sign_in_index.sql +7 -0
- package/src/migrations/postgres/0043_issue_revoke_index.sql +4 -0
- package/src/migrations/postgres/0044_use_by_name.sql +705 -0
- package/src/migrations/postgres/0045_decide_first.sql +878 -0
- package/src/migrations/postgres/0046_way_in_uses.sql +1149 -0
- package/src/migrations/postgres/0047_cutover_finish.sql +268 -0
- package/src/migrations/postgres/0048_use_batch.sql +59 -0
- package/src/migrations/postgres/0049_reads.sql +171 -0
- package/src/migrations/postgres/meta/0021_snapshot.json +3334 -0
- package/src/migrations/postgres/meta/0022_snapshot.json +3831 -0
- package/src/migrations/postgres/meta/0023_snapshot.json +3831 -0
- package/src/migrations/postgres/meta/0024_snapshot.json +3831 -0
- package/src/migrations/postgres/meta/0025_snapshot.json +3831 -0
- package/src/migrations/postgres/meta/0026_snapshot.json +3831 -0
- package/src/migrations/postgres/meta/0027_snapshot.json +3853 -0
- package/src/migrations/postgres/meta/0028_snapshot.json +3853 -0
- package/src/migrations/postgres/meta/0029_snapshot.json +3859 -0
- package/src/migrations/postgres/meta/0030_snapshot.json +3859 -0
- package/src/migrations/postgres/meta/0031_snapshot.json +3859 -0
- package/src/migrations/postgres/meta/0032_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0033_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0034_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0035_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0036_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0037_snapshot.json +3875 -0
- package/src/migrations/postgres/meta/0038_snapshot.json +3881 -0
- package/src/migrations/postgres/meta/0039_snapshot.json +3881 -0
- package/src/migrations/postgres/meta/0040_snapshot.json +3931 -0
- package/src/migrations/postgres/meta/0041_snapshot.json +3981 -0
- package/src/migrations/postgres/meta/0042_snapshot.json +3981 -0
- package/src/migrations/postgres/meta/0043_snapshot.json +3981 -0
- package/src/migrations/postgres/meta/0044_snapshot.json +3991 -0
- package/src/migrations/postgres/meta/0045_snapshot.json +3997 -0
- package/src/migrations/postgres/meta/0046_snapshot.json +3997 -0
- package/src/migrations/postgres/meta/0047_snapshot.json +4234 -0
- package/src/migrations/postgres/meta/_journal.json +189 -0
- package/src/migrations/sqlite/0018_log_015.sql +84 -0
- package/src/migrations/sqlite/0019_retention.sql +2 -0
- package/src/migrations/sqlite/0020_ended_references.sql +1 -0
- package/src/migrations/sqlite/0021_secrets_live_index.sql +1 -0
- package/src/migrations/sqlite/0022_binding_origin.sql +1 -0
- package/src/migrations/sqlite/0023_sign_in_index.sql +2 -0
- package/src/migrations/sqlite/0024_issue_revoke_index.sql +2 -0
- package/src/migrations/sqlite/0025_way_in_uses.sql +42 -0
- package/src/migrations/sqlite/0026_cutover_finish.sql +11 -0
- package/src/migrations/sqlite/0027_reads.sql +38 -0
- package/src/migrations/sqlite/meta/0018_snapshot.json +3529 -0
- package/src/migrations/sqlite/meta/0019_snapshot.json +3538 -0
- package/src/migrations/sqlite/meta/0020_snapshot.json +3545 -0
- package/src/migrations/sqlite/meta/0021_snapshot.json +3553 -0
- package/src/migrations/sqlite/meta/0022_snapshot.json +3560 -0
- package/src/migrations/sqlite/meta/0023_snapshot.json +3579 -0
- package/src/migrations/sqlite/meta/0024_snapshot.json +3598 -0
- package/src/migrations/sqlite/meta/0025_snapshot.json +3609 -0
- package/src/migrations/sqlite/meta/0026_snapshot.json +3616 -0
- package/src/migrations/sqlite/meta/0027_snapshot.json +3834 -0
- package/src/migrations/sqlite/meta/_journal.json +70 -0
- package/src/postgres-js/README.md +183 -0
- package/src/postgres-js/UNLICENSE +24 -0
- package/src/postgres-js/bytes.ts +89 -0
- package/src/postgres-js/connection.ts +882 -0
- package/src/postgres-js/errors.ts +84 -0
- package/src/postgres-js/index.ts +516 -0
- package/src/postgres-js/platform.node.ts +29 -0
- package/src/postgres-js/platform.ts +60 -0
- package/src/postgres-js/platform.workerd.ts +225 -0
- package/src/postgres-js/query.ts +123 -0
- package/src/postgres-js/queue.ts +42 -0
- package/src/postgres-js/result.ts +46 -0
- package/src/postgres-js/types.ts +52 -0
- package/src/postgres.ts +375 -26
- package/src/schema-version.ts +2 -2
- package/src/schema.sqlite.ts +200 -9
- package/src/schema.ts +294 -8
- package/src/verify-runtime.ts +18 -29
- package/LICENSE +0 -21
- package/dist/database-CFhTnnzM.d.ts +0 -73
- package/dist/postgres-Bmar8y0q.js +0 -29
- package/dist/relations-BfR3JjT1.js +0 -38
- package/src/relations.ts +0 -40
package/README.md
CHANGED
|
@@ -8,7 +8,8 @@ connections, Hyperdrive's included.
|
|
|
8
8
|
A deployment does not import it. Its own CLI applies the migrations,
|
|
9
9
|
`pnpm exec coffre migrate`, before the deploy; `coffre-server migrate` does
|
|
10
10
|
the same for local SQLite and tests. The server and vault open the same database with
|
|
11
|
-
separate logins, `coffre_runtime` and `coffre_vault_runtime
|
|
11
|
+
separate logins, `coffre_runtime` and `coffre_vault_runtime`, and the vault's
|
|
12
|
+
hot path, 0.15's uses, a third, `coffre_vault_hot`. The migrations
|
|
12
13
|
grant each its own rights; only the owner runs migrations. The owner needs
|
|
13
14
|
`CREATEROLE` and `CREATEDB`, and `ADMIN OPTION` on existing group roles.
|
|
14
15
|
Superuser is not required.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
//#region src/active-subject.ts
|
|
3
|
+
/**
|
|
4
|
+
* `identities.active_subject`: the subject while the account is bound, null
|
|
5
|
+
* once revoked. A unique index on (provider, issuer_hash, active_subject)
|
|
6
|
+
* binds an account to one person at a time. Plain column names, so the
|
|
7
|
+
* expression reads the same on both databases.
|
|
8
|
+
*/
|
|
9
|
+
const ACTIVE_SUBJECT = sql`CASE WHEN revoked_at IS NULL THEN subject END`;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/change-records.ts
|
|
12
|
+
/**
|
|
13
|
+
* What a change of 0.15's log records besides its op, which the audit pages
|
|
14
|
+
* list where 0.14's entry stood (D147): a sign-in through a trust binding
|
|
15
|
+
* (`signIn`, T156); a token the vault issued (`issue`); a credential it
|
|
16
|
+
* revoked by request, or that signed itself out (a revoke's `reason`,
|
|
17
|
+
* T164). Each is known by text its payload holds (`holds`), and by how the
|
|
18
|
+
* payload starts (`starts`): the vault writes it canonical, its keys in
|
|
19
|
+
* order, so an issue's is `{"caller":…` and a revoke's
|
|
20
|
+
* `{"op":"credential.revoke",…`. A string the payload holds has its quotes
|
|
21
|
+
* escaped, but an object's keys need not be the vault's own (a role's
|
|
22
|
+
* name, in the roles' change: review r1), so where the text alone could be
|
|
23
|
+
* one, the start says whose payload it is. The partial indexes of
|
|
24
|
+
* `log_changes` hold each set, and a read that is to use one repeats its
|
|
25
|
+
* condition (`recorded`), word for word and with no parameter.
|
|
26
|
+
*/
|
|
27
|
+
const RECORDS = {
|
|
28
|
+
signIn: { holds: "\"signIn\":{" },
|
|
29
|
+
issue: {
|
|
30
|
+
starts: "{\"caller\":\"",
|
|
31
|
+
holds: "\"issue\":{\"by\":\""
|
|
32
|
+
},
|
|
33
|
+
revoke: {
|
|
34
|
+
starts: "{\"op\":\"credential.revoke\",",
|
|
35
|
+
holds: "\"reason\":\"revoke\""
|
|
36
|
+
},
|
|
37
|
+
signOut: {
|
|
38
|
+
starts: "{\"op\":\"credential.revoke\",",
|
|
39
|
+
holds: "\"reason\":\"sign_out\""
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
/** Whether `payload` holds one of `records`, on Postgres or SQLite: an index's condition, and the reads' that use it. */
|
|
43
|
+
function recorded(engine, payload, ...records) {
|
|
44
|
+
const at = (text) => {
|
|
45
|
+
const marker = sql.raw(`'${text}'`);
|
|
46
|
+
return engine === "postgres" ? sql`strpos(${payload}, ${marker})` : sql`instr(${payload}, ${marker})`;
|
|
47
|
+
};
|
|
48
|
+
const each = records.map((record) => {
|
|
49
|
+
const { starts, holds } = RECORDS[record];
|
|
50
|
+
return starts === void 0 ? sql`${at(holds)} > 0` : sql`(${at(starts)} = 1 AND ${at(holds)} > 0)`;
|
|
51
|
+
});
|
|
52
|
+
return each.length === 1 ? each[0] : sql`(${sql.join(each, sql` OR `)})`;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { recorded as n, ACTIVE_SUBJECT as r, RECORDS as t };
|
package/dist/connect.d.ts
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as quoteIdentifier, d as ClientOptions, f as PostgresClient, g as postgresSession, h as postgresOptions, m as postgresClient, n as Database, p as SessionLost, v as quoteLiteral } from "./database-CVteLhp1.js";
|
|
2
2
|
import { Engine } from "./dialect.js";
|
|
3
|
-
import { ClientConfig } from "pg";
|
|
4
|
-
//#region src/postgres.d.ts
|
|
5
|
-
/** Keep libpq's system-root shortcut from being read as a certificate filename by pg. */
|
|
6
|
-
export declare function postgresConnection(url: string): ClientConfig;
|
|
7
|
-
//#endregion
|
|
8
3
|
//#region src/connect.d.ts
|
|
9
4
|
/**
|
|
10
5
|
* Open a database from its URL, on a Node server:
|
|
11
6
|
*
|
|
12
|
-
* postgres://… or postgresql://…
|
|
7
|
+
* postgres://… or postgresql://… postgres.js, a pool of up to 10 connections
|
|
13
8
|
* file:… or libsql:… @libsql/client (SQLite)
|
|
14
9
|
*
|
|
15
10
|
* The SQLite driver loads only when asked for. The Worker does not
|
|
16
11
|
* come through here; it builds its Postgres database from the Hyperdrive
|
|
17
|
-
* pool with createDatabase.
|
|
12
|
+
* pool with createDatabase. `max`, for a pool of its own beside another,
|
|
13
|
+
* as the vault's checkpointer has (T169).
|
|
18
14
|
*/
|
|
19
|
-
export declare function openDatabase(url: string
|
|
15
|
+
export declare function openDatabase(url: string, options?: {
|
|
16
|
+
max?: number;
|
|
17
|
+
}): Promise<OpenDatabase>;
|
|
18
|
+
/** `close` once what was asked has answered; `cut` at once, what is in flight failing (T169). */
|
|
20
19
|
export type OpenDatabase = {
|
|
21
20
|
engine: Engine;
|
|
22
21
|
db: Database;
|
|
23
22
|
close: () => Promise<void>;
|
|
23
|
+
cut: () => Promise<void>;
|
|
24
24
|
};
|
|
25
25
|
export declare function engineOfUrl(url: string): Engine;
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Whether a lone statement may write: all but a query (SELECT or VALUES, or
|
|
28
|
+
* a WITH whose statement is one) and EXPLAIN, read from its words outside
|
|
29
|
+
* parentheses, strings, quoted names and comments.
|
|
30
|
+
*
|
|
31
|
+
* select … from "mcp_approvals" where … reads
|
|
32
|
+
* WITH policy AS (SELECT …) SELECT json_object(…) reads
|
|
33
|
+
* WITH old AS (SELECT …) DELETE FROM … writes
|
|
34
|
+
* update "mcp_connections" set … writes
|
|
35
|
+
*/
|
|
36
|
+
export declare function writes(statement: string): boolean;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { type ClientOptions, type PostgresClient, SessionLost, postgresClient, postgresOptions, postgresSession, quoteIdentifier, quoteLiteral };
|
package/dist/connect.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { a as quoteIdentifier, i as postgresSession, n as postgresClient, o as quoteLiteral, r as postgresOptions, t as SessionLost } from "./postgres-BI3xTnyw.js";
|
|
2
|
+
import { n as createDatabase } from "./database-D55ENPX-.js";
|
|
2
3
|
import { asPostgresDatabase } from "./portable.js";
|
|
3
|
-
import { t as postgresConnection } from "./postgres-Bmar8y0q.js";
|
|
4
|
-
import pg from "pg";
|
|
5
4
|
import { resolve } from "node:path";
|
|
6
5
|
//#region src/connect.ts
|
|
7
6
|
/**
|
|
8
7
|
* Open a database from its URL, on a Node server:
|
|
9
8
|
*
|
|
10
|
-
* postgres://… or postgresql://…
|
|
9
|
+
* postgres://… or postgresql://… postgres.js, a pool of up to 10 connections
|
|
11
10
|
* file:… or libsql:… @libsql/client (SQLite)
|
|
12
11
|
*
|
|
13
12
|
* The SQLite driver loads only when asked for. The Worker does not
|
|
14
13
|
* come through here; it builds its Postgres database from the Hyperdrive
|
|
15
|
-
* pool with createDatabase.
|
|
14
|
+
* pool with createDatabase. `max`, for a pool of its own beside another,
|
|
15
|
+
* as the vault's checkpointer has (T169).
|
|
16
16
|
*/
|
|
17
|
-
async function openDatabase(url) {
|
|
17
|
+
async function openDatabase(url, options = {}) {
|
|
18
18
|
switch (engineOfUrl(url)) {
|
|
19
19
|
case "postgres": {
|
|
20
|
-
const
|
|
20
|
+
const client = postgresClient(url, {
|
|
21
|
+
max: options.max ?? 10,
|
|
22
|
+
idle_timeout: 10
|
|
23
|
+
});
|
|
21
24
|
return {
|
|
22
25
|
engine: "postgres",
|
|
23
|
-
db: createDatabase(
|
|
24
|
-
close: () =>
|
|
26
|
+
db: createDatabase(client),
|
|
27
|
+
close: () => client.end(),
|
|
28
|
+
cut: () => client.end({ timeout: 0 })
|
|
25
29
|
};
|
|
26
30
|
}
|
|
27
31
|
case "sqlite": {
|
|
@@ -43,7 +47,8 @@ async function openDatabase(url) {
|
|
|
43
47
|
return {
|
|
44
48
|
engine: "sqlite",
|
|
45
49
|
db: asPostgresDatabase(db),
|
|
46
|
-
close: async () => client.close()
|
|
50
|
+
close: async () => client.close(),
|
|
51
|
+
cut: async () => client.close()
|
|
47
52
|
};
|
|
48
53
|
}
|
|
49
54
|
}
|
|
@@ -63,6 +68,16 @@ function engineOfUrl(url) {
|
|
|
63
68
|
* connections reach it. Each begins IMMEDIATE (libsql's default), taking the
|
|
64
69
|
* write lock with its first statement, which is what makes a read inside it
|
|
65
70
|
* as good as a locked one (see forUpdate).
|
|
71
|
+
*
|
|
72
|
+
* A lone statement that writes waits its turn too. It cannot wait for the
|
|
73
|
+
* lock itself: libsql's busy wait blocks the thread, so the transaction
|
|
74
|
+
* holding the lock, in this process, cannot go on to commit, and the write
|
|
75
|
+
* fails after `timeout`. A connection whose write failed that way still
|
|
76
|
+
* reads the file as it was then, until its statement is collected:
|
|
77
|
+
*
|
|
78
|
+
* six MCP calls at once the first's approval, in a transaction BEGIN IMMEDIATE, then awaits
|
|
79
|
+
* another's last_used_at a lone UPDATE, outside the queue the thread blocked 5 s, SQLITE_BUSY
|
|
80
|
+
* it reads the approval on that connection no row
|
|
66
81
|
*/
|
|
67
82
|
var WriteQueue = class {
|
|
68
83
|
#tail = Promise.resolve();
|
|
@@ -84,7 +99,16 @@ function writeQueueFor(url) {
|
|
|
84
99
|
}
|
|
85
100
|
function oneTransactionAtATime(client, queue) {
|
|
86
101
|
return new Proxy(client, { get(target, key) {
|
|
87
|
-
if (key === "execute") return async (...args) =>
|
|
102
|
+
if (key === "execute") return async (...args) => {
|
|
103
|
+
const [statement] = args;
|
|
104
|
+
if (!writes(typeof statement === "string" ? statement : statement.sql)) return numbers(await target.execute(...args));
|
|
105
|
+
const release = await queue.acquire();
|
|
106
|
+
try {
|
|
107
|
+
return numbers(await target.execute(...args));
|
|
108
|
+
} finally {
|
|
109
|
+
release();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
88
112
|
if (key === "transaction") return async (mode) => {
|
|
89
113
|
const release = await queue.acquire();
|
|
90
114
|
try {
|
|
@@ -140,6 +164,44 @@ function settling(tx, release) {
|
|
|
140
164
|
};
|
|
141
165
|
return tx;
|
|
142
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Whether a lone statement may write: all but a query (SELECT or VALUES, or
|
|
169
|
+
* a WITH whose statement is one) and EXPLAIN, read from its words outside
|
|
170
|
+
* parentheses, strings, quoted names and comments.
|
|
171
|
+
*
|
|
172
|
+
* select … from "mcp_approvals" where … reads
|
|
173
|
+
* WITH policy AS (SELECT …) SELECT json_object(…) reads
|
|
174
|
+
* WITH old AS (SELECT …) DELETE FROM … writes
|
|
175
|
+
* update "mcp_connections" set … writes
|
|
176
|
+
*/
|
|
177
|
+
function writes(statement) {
|
|
178
|
+
let depth = 0;
|
|
179
|
+
let first = null;
|
|
180
|
+
for (const [token] of statement.matchAll(/--[^\n]*|\/\*[\s\S]*?(?:\*\/|$)|'(?:[^']|'')*'?|"(?:[^"]|"")*"?|`[^`]*`?|\[[^\]]*\]?|[()]|[A-Za-z_][\w$]*/g)) if (token === "(") depth += 1;
|
|
181
|
+
else if (token === ")") depth -= 1;
|
|
182
|
+
else if (depth === 0 && /^[A-Za-z_]/.test(token)) {
|
|
183
|
+
const word = token.toLowerCase();
|
|
184
|
+
if (first === null) {
|
|
185
|
+
first = word;
|
|
186
|
+
if (word !== "with") return !QUERIES.has(word);
|
|
187
|
+
} else if (STATEMENTS.has(word)) return !QUERIES.has(word);
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
const QUERIES = /* @__PURE__ */ new Set([
|
|
192
|
+
"select",
|
|
193
|
+
"values",
|
|
194
|
+
"explain"
|
|
195
|
+
]);
|
|
196
|
+
/** The words a WITH's own statement starts with. */
|
|
197
|
+
const STATEMENTS = /* @__PURE__ */ new Set([
|
|
198
|
+
"select",
|
|
199
|
+
"values",
|
|
200
|
+
"insert",
|
|
201
|
+
"update",
|
|
202
|
+
"delete",
|
|
203
|
+
"replace"
|
|
204
|
+
]);
|
|
143
205
|
/** Keep large counters exact; Drizzle's booleans and dates still need safe numbers. */
|
|
144
206
|
function numbers(result) {
|
|
145
207
|
result.rows = result.rows.map((row) => {
|
|
@@ -153,4 +215,4 @@ function numbers(result) {
|
|
|
153
215
|
return result;
|
|
154
216
|
}
|
|
155
217
|
//#endregion
|
|
156
|
-
export { engineOfUrl, openDatabase,
|
|
218
|
+
export { SessionLost, engineOfUrl, openDatabase, postgresClient, postgresOptions, postgresSession, quoteIdentifier, quoteLiteral, writes };
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { n as Socket, r as TlsOptions } from "./platform-Y3gICK6n.js";
|
|
2
|
+
import { T as schema_d_exports } from "./schema-DgoPqqsI.js";
|
|
3
|
+
import { Assume, Query, Table } from "drizzle-orm";
|
|
4
|
+
import { PgDatabase, PgQueryResultHKT } from "drizzle-orm/pg-core";
|
|
5
|
+
//#region src/postgres-js/errors.d.ts
|
|
6
|
+
/** What Postgres said in an ErrorResponse or a NoticeResponse, each field by its name. */
|
|
7
|
+
type Notice = Partial<Record<(typeof FIELDS)[keyof typeof FIELDS], string>>;
|
|
8
|
+
/** An ErrorResponse's fields, by their code. `data type_name` is upstream's spelling, kept. */
|
|
9
|
+
declare const FIELDS: {
|
|
10
|
+
readonly 83: "severity_local";
|
|
11
|
+
readonly 86: "severity";
|
|
12
|
+
readonly 67: "code";
|
|
13
|
+
readonly 77: "message";
|
|
14
|
+
readonly 68: "detail";
|
|
15
|
+
readonly 72: "hint";
|
|
16
|
+
readonly 80: "position";
|
|
17
|
+
readonly 112: "internal_position";
|
|
18
|
+
readonly 113: "internal_query";
|
|
19
|
+
readonly 87: "where";
|
|
20
|
+
readonly 115: "schema_name";
|
|
21
|
+
readonly 116: "table_name";
|
|
22
|
+
readonly 99: "column_name";
|
|
23
|
+
readonly 100: "data type_name";
|
|
24
|
+
readonly 110: "constraint_name";
|
|
25
|
+
readonly 70: "file";
|
|
26
|
+
readonly 76: "line";
|
|
27
|
+
readonly 82: "routine";
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/postgres-js/result.d.ts
|
|
31
|
+
/** What Postgres said of a column, in a RowDescription. */
|
|
32
|
+
interface Column {
|
|
33
|
+
name: string;
|
|
34
|
+
/** How its text is read, by its type; as text when there is none. */
|
|
35
|
+
parser: ((text: string) => unknown) | undefined;
|
|
36
|
+
table: number;
|
|
37
|
+
number: number;
|
|
38
|
+
type: number;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/postgres-js/query.d.ts
|
|
42
|
+
/** A statement as sent: its text, its parameters' types (0 for the server to say), and its columns once described. */
|
|
43
|
+
interface Statement {
|
|
44
|
+
string: string;
|
|
45
|
+
types: number[];
|
|
46
|
+
/** Once described: by a RowDescription, or NoData's none. */
|
|
47
|
+
columns: Column[] | null;
|
|
48
|
+
}
|
|
49
|
+
interface QueryOptions {
|
|
50
|
+
/** Sent with the simple protocol, one Query message: what a statement with no parameters is, by default. */
|
|
51
|
+
simple: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* One statement of a group (`group`, index.ts): its text and values, whether
|
|
55
|
+
* its rows come as arrays, and what the connection works out as it sends it.
|
|
56
|
+
*/
|
|
57
|
+
interface Member {
|
|
58
|
+
text: string;
|
|
59
|
+
args: unknown[];
|
|
60
|
+
arrays: boolean;
|
|
61
|
+
parameters: unknown[];
|
|
62
|
+
statement: Statement | null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A statement, sent once awaited (`then`, `catch`, `finally`) or `execute`d,
|
|
66
|
+
* a task later, through the pool or the transaction that made it: its
|
|
67
|
+
* `handler`. A promise of its result, its rows as objects or, after
|
|
68
|
+
* `values()`, as arrays.
|
|
69
|
+
*/
|
|
70
|
+
declare class Query$1<T = unknown> extends Promise<T> {
|
|
71
|
+
#private;
|
|
72
|
+
readonly text: string;
|
|
73
|
+
readonly args: unknown[];
|
|
74
|
+
readonly options: QueryOptions;
|
|
75
|
+
/** Its rows as arrays of values rather than objects. */
|
|
76
|
+
arrays: boolean;
|
|
77
|
+
executed: boolean;
|
|
78
|
+
parameters: unknown[];
|
|
79
|
+
statement: Statement | null;
|
|
80
|
+
/** Whether its parameters' types are asked of the server before its values go (`typedByServer`, connection.ts). */
|
|
81
|
+
describeFirst: boolean;
|
|
82
|
+
/** A transaction's first statement: its BEGIN, sent ahead of it under its Sync (`begin`, index.ts); and whether it took. */
|
|
83
|
+
begin: string | null;
|
|
84
|
+
began: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Coffre: a group's statements, sent under one Sync and answered together, each its own result (`group`, index.ts),
|
|
87
|
+
* and the one answering now. Null for a statement of its own.
|
|
88
|
+
*/
|
|
89
|
+
group: Member[] | null;
|
|
90
|
+
member: number;
|
|
91
|
+
readonly resolve: (value: unknown) => void;
|
|
92
|
+
readonly reject: (error: unknown) => void;
|
|
93
|
+
constructor(text: string, args: unknown[], handler: (query: Query$1) => void, options: QueryOptions, debug: boolean);
|
|
94
|
+
/** Where it was made, for its error's stack: nothing unless the client debugs. */
|
|
95
|
+
get origin(): string;
|
|
96
|
+
/** What `then` and the like make: a plain promise, not another statement. */
|
|
97
|
+
static get [Symbol.species](): PromiseConstructor;
|
|
98
|
+
values(): Query$1<RowList<unknown[][]>>;
|
|
99
|
+
execute(): this;
|
|
100
|
+
then<A = T, B = never>(onfulfilled?: ((value: T) => A | PromiseLike<A>) | null, onrejected?: ((reason: any) => B | PromiseLike<B>) | null): Promise<A | B>;
|
|
101
|
+
catch<B = never>(onrejected?: ((reason: any) => B | PromiseLike<B>) | null): Promise<T | B>;
|
|
102
|
+
finally(onfinally?: (() => void) | null): Promise<T>;
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/postgres-js/types.d.ts
|
|
106
|
+
/** How a column's text is read, by its type's oid. */
|
|
107
|
+
type Parsers = Record<number, ((text: string) => unknown) | undefined>;
|
|
108
|
+
/** How a value is written as text, by its parameter's type's oid. */
|
|
109
|
+
type Serializers = Record<number, ((value: unknown) => unknown) | undefined>;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/postgres-js/index.d.ts
|
|
112
|
+
/** What a client is opened with. Nothing is read from the environment: what is not given is the default named. */
|
|
113
|
+
interface Options {
|
|
114
|
+
/** Default `localhost`. */
|
|
115
|
+
host?: string;
|
|
116
|
+
/** Default 5432. */
|
|
117
|
+
port?: number;
|
|
118
|
+
/** A Unix socket's path, in place of `host` and `port`. */
|
|
119
|
+
path?: string | undefined;
|
|
120
|
+
/** Default the server's: the user's name. */
|
|
121
|
+
database?: string | undefined;
|
|
122
|
+
user?: string;
|
|
123
|
+
pass?: string;
|
|
124
|
+
/** TLS, with Node's options for it; default none. */
|
|
125
|
+
ssl?: false | TlsOptions;
|
|
126
|
+
/** `direct`: TLS from the first byte, with no SSLRequest (Postgres 17). */
|
|
127
|
+
sslnegotiation?: 'direct' | null | undefined;
|
|
128
|
+
/** Connections at most. Default 10. */
|
|
129
|
+
max?: number;
|
|
130
|
+
/** Statements sent on a connection before the first has answered. Default 100. */
|
|
131
|
+
max_pipeline?: number;
|
|
132
|
+
/** Seconds a connection may be idle before it closes. Default none. */
|
|
133
|
+
idle_timeout?: number | null | undefined;
|
|
134
|
+
/** Seconds a connection may take to open. Default 30. */
|
|
135
|
+
connect_timeout?: number | null | undefined;
|
|
136
|
+
/** Seconds a connection may live, or a function that says how many. Default 30 to 60 minutes. */
|
|
137
|
+
max_lifetime?: number | null | (() => number);
|
|
138
|
+
/** Seconds before a closed connection is opened again, by how many in a row closed with an error. */
|
|
139
|
+
backoff?: number | ((retries: number) => number);
|
|
140
|
+
/** Seconds of TCP keep-alive. Default 60. */
|
|
141
|
+
keep_alive?: number | null;
|
|
142
|
+
/** True to keep where each statement was made, for its error's stack, and its text on its error; or a function told each statement. */
|
|
143
|
+
debug?: boolean | ((connection: number, query: string, parameters: unknown[], types: number[]) => void);
|
|
144
|
+
/** Run-time parameters sent as each connection starts. Default `application_name` postgres.js. */
|
|
145
|
+
connection?: Record<string, string | number | boolean | undefined>;
|
|
146
|
+
/** Each notice Postgres sends. Default: logged. */
|
|
147
|
+
onnotice?: (notice: Notice) => void;
|
|
148
|
+
/** Each connection's close, by its id. */
|
|
149
|
+
onclose?: (connectionId: number) => void;
|
|
150
|
+
/** The stream to speak Postgres on, made for each connection, rather than a TCP socket to `host`. */
|
|
151
|
+
socket?: () => Socket | Promise<Socket>;
|
|
152
|
+
}
|
|
153
|
+
/** A client's options, every one settled, and what it keeps beside them: `parsers` and `serializers`, which it may change. */
|
|
154
|
+
interface Settings {
|
|
155
|
+
host: string;
|
|
156
|
+
port: number;
|
|
157
|
+
path: string | undefined;
|
|
158
|
+
database: string | undefined;
|
|
159
|
+
user: string;
|
|
160
|
+
pass: string;
|
|
161
|
+
ssl: false | TlsOptions;
|
|
162
|
+
sslnegotiation: 'direct' | null | undefined;
|
|
163
|
+
max: number;
|
|
164
|
+
max_pipeline: number;
|
|
165
|
+
idle_timeout: number | null | undefined;
|
|
166
|
+
connect_timeout: number | null | undefined;
|
|
167
|
+
max_lifetime: number | null | undefined | (() => number);
|
|
168
|
+
backoff: number | ((retries: number) => number);
|
|
169
|
+
keep_alive: number | null | undefined;
|
|
170
|
+
debug: boolean | ((connection: number, query: string, parameters: unknown[], types: number[]) => void);
|
|
171
|
+
connection: Record<string, string | number | boolean | undefined>;
|
|
172
|
+
onnotice: ((notice: Notice) => void) | undefined;
|
|
173
|
+
onclose: ((connectionId: number) => void) | undefined;
|
|
174
|
+
socket: (() => Socket | Promise<Socket>) | undefined;
|
|
175
|
+
parsers: Parsers;
|
|
176
|
+
serializers: Serializers;
|
|
177
|
+
/** The server's run-time parameters, as its ParameterStatus messages said them. */
|
|
178
|
+
parameters: Record<string, string>;
|
|
179
|
+
/** What the pool's connections share: how many in a row closed with an error, which backs off reopening. */
|
|
180
|
+
shared: {
|
|
181
|
+
retries: number;
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/** A row, by its columns' names: whatever a hand-written statement selects, as upstream types it. */
|
|
185
|
+
type Row = Record<string, any>;
|
|
186
|
+
/** What a statement's CommandComplete said, beside its rows. */
|
|
187
|
+
interface ResultMeta {
|
|
188
|
+
/** Rows inserted, updated, deleted or returned; null for a command that counts none. */
|
|
189
|
+
readonly count: number | null;
|
|
190
|
+
readonly command: string;
|
|
191
|
+
/** The backend that ran it: its process id and secret key, what a CancelRequest names. */
|
|
192
|
+
readonly state: {
|
|
193
|
+
readonly pid: number;
|
|
194
|
+
readonly secret: number;
|
|
195
|
+
};
|
|
196
|
+
readonly columns: Column[] | null;
|
|
197
|
+
}
|
|
198
|
+
/** A statement's rows, with what Postgres said of it. */
|
|
199
|
+
type RowList<T extends readonly unknown[]> = T & ResultMeta;
|
|
200
|
+
/** A statement, sent once awaited or `execute`d. */
|
|
201
|
+
type PendingQuery<T extends readonly unknown[]> = Query$1<RowList<T>>;
|
|
202
|
+
/** A transaction's statements, and its savepoints. */
|
|
203
|
+
interface TransactionSql {
|
|
204
|
+
unsafe<T extends readonly unknown[] = Row[]>(query: string, parameters?: unknown[], options?: {
|
|
205
|
+
simple?: boolean;
|
|
206
|
+
}): PendingQuery<T>;
|
|
207
|
+
/** A savepoint, rolled back to if `fn` fails. */
|
|
208
|
+
savepoint<T>(fn: (sql: TransactionSql) => T | Promise<T>): Promise<Settled<T>>;
|
|
209
|
+
}
|
|
210
|
+
/** A connection held until `release()`. */
|
|
211
|
+
interface ReservedSql {
|
|
212
|
+
unsafe<T extends readonly unknown[] = Row[]>(query: string, parameters?: unknown[], options?: {
|
|
213
|
+
simple?: boolean;
|
|
214
|
+
}): PendingQuery<T>;
|
|
215
|
+
release(): void;
|
|
216
|
+
}
|
|
217
|
+
/** A pool of connections to Postgres. */
|
|
218
|
+
interface Sql {
|
|
219
|
+
/**
|
|
220
|
+
* A statement: with `parameters`, the extended protocol, one round trip;
|
|
221
|
+
* without, the simple one, unless `simple: false`.
|
|
222
|
+
*/
|
|
223
|
+
unsafe<T extends readonly unknown[] = Row[]>(query: string, parameters?: unknown[], options?: {
|
|
224
|
+
simple?: boolean;
|
|
225
|
+
}): PendingQuery<T>;
|
|
226
|
+
/**
|
|
227
|
+
* A transaction, on a connection held for it: BEGIN (`options` after it,
|
|
228
|
+
* `isolation level serializable` and the like), `fn`, then COMMIT, or
|
|
229
|
+
* ROLLBACK if `fn` fails, or a statement of it did that `fn` did not wait for.
|
|
230
|
+
*/
|
|
231
|
+
begin<T>(fn: (sql: TransactionSql) => T | Promise<T>): Promise<Settled<T>>;
|
|
232
|
+
begin<T>(options: string, fn: (sql: TransactionSql) => T | Promise<T>): Promise<Settled<T>>;
|
|
233
|
+
/**
|
|
234
|
+
* Coffre: statements sent together under one Sync, a round trip in all
|
|
235
|
+
* through a pooler that sends a client's Syncs on one at a time, as
|
|
236
|
+
* Hyperdrive does; answered once the last has, each with its own rows,
|
|
237
|
+
* as an array (`arrays` for a statement's rows as arrays of values). They
|
|
238
|
+
* run as one implicit transaction: if one fails, Postgres skips those
|
|
239
|
+
* after it, and the group fails, with that error. Plain reads alone
|
|
240
|
+
* (`select …`), on the pool alone, never in a transaction, whose
|
|
241
|
+
* statements each go under its own; each with the extended protocol, as
|
|
242
|
+
* a statement with parameters.
|
|
243
|
+
*/
|
|
244
|
+
group(statements: readonly {
|
|
245
|
+
query: string;
|
|
246
|
+
parameters?: unknown[];
|
|
247
|
+
arrays?: boolean;
|
|
248
|
+
}[]): PendingQuery<RowList<Row[]>[]>;
|
|
249
|
+
/** A connection of the pool, held for the caller until it releases it. */
|
|
250
|
+
reserve(): Promise<ReservedSql>;
|
|
251
|
+
/** Close every connection once what it was sent has answered; after `timeout` seconds, at once. */
|
|
252
|
+
end(options?: {
|
|
253
|
+
timeout?: number | null;
|
|
254
|
+
}): Promise<void>;
|
|
255
|
+
readonly options: Settings;
|
|
256
|
+
}
|
|
257
|
+
/** What a transaction's work answers: an array of promises, each awaited. */
|
|
258
|
+
type Settled<T> = T extends readonly unknown[] ? { -readonly [K in keyof T]: Awaited<T[K]>; } : Awaited<T>;
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/postgres.d.ts
|
|
261
|
+
/**
|
|
262
|
+
* A client of coffre's postgres.js (`./postgres-js`): statements (`unsafe`),
|
|
263
|
+
* transactions (`begin`), a connection held (`reserve`), and closing it.
|
|
264
|
+
*/
|
|
265
|
+
type PostgresClient = Sql;
|
|
266
|
+
/** What a client may be opened with beside its URL. */
|
|
267
|
+
type ClientOptions = Pick<Options, 'max' | 'idle_timeout' | 'connect_timeout' | 'max_lifetime' | 'onnotice' | 'debug' | 'onclose'> & {
|
|
268
|
+
/** The stream to speak Postgres on, made for each connection, rather than a TCP socket: a tunnel's. */
|
|
269
|
+
socket?: Options['socket'];
|
|
270
|
+
/** Postgres's `application_name` for the connection. */
|
|
271
|
+
application_name?: string;
|
|
272
|
+
/** Run-time parameters sent when the connection starts, `statement_timeout` and the like. */
|
|
273
|
+
connection?: Record<string, string | number | boolean>;
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* A client for `url`, as coffre opens every one: the driver's defaults (10
|
|
277
|
+
* connections, every statement unnamed, as node-postgres sends them), but
|
|
278
|
+
*
|
|
279
|
+
* - notices dropped rather than logged;
|
|
280
|
+
* - no connection closed for its age (`max_lifetime`), as node-postgres
|
|
281
|
+
* closed none: a backup's session holds its snapshot while pg_dump reads.
|
|
282
|
+
*
|
|
283
|
+
* The driver reads no array type from `pg_type` (postgres.js's
|
|
284
|
+
* `fetch_types`, a round trip more per connection), and would answer one as
|
|
285
|
+
* its text: Postgres's own are taken as known instead (`ARRAYS`). Arrays and
|
|
286
|
+
* dates go as node-postgres sends them (`asPgSends`).
|
|
287
|
+
*/
|
|
288
|
+
declare function postgresClient(url: string, options?: ClientOptions): PostgresClient;
|
|
289
|
+
/** A statement asked of a session that lost its connection, and with it its transaction, its locks and its settings. */
|
|
290
|
+
declare class SessionLost extends Error {
|
|
291
|
+
constructor();
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* One connection to `url`, kept as a session, as node-postgres's Client
|
|
295
|
+
* kept one: what a statement sets (SET, BEGIN, a session's advisory lock)
|
|
296
|
+
* holds for every statement after. A client of postgres.js would dial a new
|
|
297
|
+
* connection for the next statement once its own closed, which holds none of
|
|
298
|
+
* it: a migration going on without its lock, a probe meant to be rolled back
|
|
299
|
+
* committed, a backup read outside its snapshot. A session does not: once
|
|
300
|
+
* its connection has closed, by the server, the network or `end`, every
|
|
301
|
+
* statement after fails, `SessionLost`.
|
|
302
|
+
*/
|
|
303
|
+
declare function postgresSession(url: string, options?: Omit<ClientOptions, 'max'>): PostgresClient;
|
|
304
|
+
/**
|
|
305
|
+
* The connection `url` names, as node-postgres and its pg-connection-string
|
|
306
|
+
* read one. The driver reads no URL: it is given the parts. (Upstream
|
|
307
|
+
* postgres.js read URLs otherwise: it sent every query parameter it did not
|
|
308
|
+
* know to the server as a setting, which refused the connection over one it
|
|
309
|
+
* did not know either, `sslrootcert` or `uselibpqcompat`; its
|
|
310
|
+
* `sslmode=require` skipped the certificate check, where coffre's URLs, as
|
|
311
|
+
* pg reads them, verify; and it checked an IP address against `localhost`.)
|
|
312
|
+
*
|
|
313
|
+
* TLS is:
|
|
314
|
+
*
|
|
315
|
+
* no sslmode, sslmode=disable none
|
|
316
|
+
* sslmode=prefer, require, verify-ca, the certificate chain and the host verified
|
|
317
|
+
* verify-full; ssl=true or 1
|
|
318
|
+
* sslmode=no-verify TLS, nothing verified
|
|
319
|
+
* uselibpqcompat=true libpq's modes: prefer and require verify nothing
|
|
320
|
+
* (require with a sslrootcert, the chain), verify-ca
|
|
321
|
+
* the chain, verify-full the chain and the host
|
|
322
|
+
* sslrootcert=system Node's trusted CAs; only with verify-full or no sslmode
|
|
323
|
+
* sslrootcert, sslcert, sslkey (files) read from disk, as pg does
|
|
324
|
+
*
|
|
325
|
+
* The host is verified against the URL's own, an IP address included.
|
|
326
|
+
*/
|
|
327
|
+
declare function postgresOptions(url: string): Partial<Options> & {
|
|
328
|
+
connection: Record<string, string>;
|
|
329
|
+
};
|
|
330
|
+
/** `name` as a Postgres identifier, quoted, as node-postgres's `escapeIdentifier` writes one. */
|
|
331
|
+
declare function quoteIdentifier(name: string): string;
|
|
332
|
+
/** `text` as a Postgres string literal, as node-postgres's `escapeLiteral` writes one: `E'…'` when it holds a backslash. */
|
|
333
|
+
declare function quoteLiteral(text: string): string;
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/prepared.d.ts
|
|
336
|
+
/** The part of a select builder `prepared` reads, once. */
|
|
337
|
+
type Select = PromiseLike<unknown> & {
|
|
338
|
+
toSQL(): Query;
|
|
339
|
+
prepare(...name: never[]): unknown;
|
|
340
|
+
};
|
|
341
|
+
/**
|
|
342
|
+
* A select built once per process, or once per isolate on Workers, and run
|
|
343
|
+
* with new values each time. Drizzle rebuilds a query's SQL from its
|
|
344
|
+
* builder at every run, and that was most of a short query's CPU; this
|
|
345
|
+
* builds it from `build` the first time a database of its dialect asks,
|
|
346
|
+
* then hands the SQL and its columns to that call's own session
|
|
347
|
+
* (`session.prepareQuery`), which binds `values` to the placeholders
|
|
348
|
+
* (`sql.placeholder`) and maps the rows as the builder would.
|
|
349
|
+
*
|
|
350
|
+
* `build` must not depend on anything but the database's dialect, and the
|
|
351
|
+
* values go to the driver as they are, not through a column's encoding:
|
|
352
|
+
* strings, numbers, bigints and bytes.
|
|
353
|
+
*
|
|
354
|
+
* const member = prepared((db) => db.select().from(tablesOf(db).vaultMembers).where(eq(…, sql.placeholder('principal'))));
|
|
355
|
+
* const [row] = await member(db, { principal });
|
|
356
|
+
*/
|
|
357
|
+
declare function prepared<Q extends Select>(build: (db: Queryable) => Q): (db: Queryable, values?: Record<string, unknown>) => Promise<Awaited<Q>>;
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region src/database.d.ts
|
|
360
|
+
/** What a hand-written statement answers on Postgres: its rows, with `count` and `command`. */
|
|
361
|
+
interface QueryResult extends PgQueryResultHKT {
|
|
362
|
+
type: RowList<Assume<this['row'], Row>[]>;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* A database, typed as Postgres whichever it is; see portable.ts for why
|
|
366
|
+
* that holds. connect.ts opens one of each from a URL.
|
|
367
|
+
*/
|
|
368
|
+
type Database = PgDatabase<QueryResult, typeof schema_d_exports, NoRelations>;
|
|
369
|
+
type Transaction = Parameters<Parameters<Database['transaction']>[0]>[0];
|
|
370
|
+
/** Anything a read can run on: the database, or an open transaction. */
|
|
371
|
+
type Queryable = Database | Transaction;
|
|
372
|
+
/**
|
|
373
|
+
* A query made on the database from inside one of its own transactions,
|
|
374
|
+
* rather than through the transaction. With one connection per call, as on
|
|
375
|
+
* Workers, it would wait for the transaction, which waits for it: a call
|
|
376
|
+
* Cloudflare cancels as hung, and nothing says why. So it is refused at
|
|
377
|
+
* once, with this, wherever the database runs.
|
|
378
|
+
*/
|
|
379
|
+
declare class QueryOutsideTransaction extends Error {
|
|
380
|
+
constructor();
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Coffre runs no relational query (`db.query.*`), and Drizzle's work out of
|
|
384
|
+
* them, `extractTablesRelationalConfig` and a query builder per table for
|
|
385
|
+
* every database, was 4 to 11 ms of a cold isolate's CPU and 0.1 ms of each
|
|
386
|
+
* later call on Workers, where a database is made per call. So the database
|
|
387
|
+
* has none: `db.query` is empty, in type and at run time, and a `db.query.x`
|
|
388
|
+
* fails the typecheck. Only the tables stay, for `tablesOf`.
|
|
389
|
+
*/
|
|
390
|
+
type NoRelations = Record<never, never>;
|
|
391
|
+
/**
|
|
392
|
+
* What a database runs on: a postgres.js client (`postgresClient`), or
|
|
393
|
+
* Workers' `HyperdrivePool`, which makes them. Drizzle asks it for
|
|
394
|
+
* statements (`unsafe`) and transactions (`begin`).
|
|
395
|
+
*/
|
|
396
|
+
type Client = Pick<PostgresClient, 'unsafe' | 'begin'>;
|
|
397
|
+
declare function createDatabase(client: Client): Database;
|
|
398
|
+
/**
|
|
399
|
+
* The tables of the database's own dialect: the Postgres ones on Postgres,
|
|
400
|
+
* the SQLite ones on SQLite. Every query builds on these.
|
|
401
|
+
*/
|
|
402
|
+
declare function tablesOf(db: Queryable): typeof schema_d_exports;
|
|
403
|
+
/**
|
|
404
|
+
* The database's own twin of `table`, which may be another dialect's: the
|
|
405
|
+
* server names tables by importing schema.ts, and the database decides
|
|
406
|
+
* which one that means.
|
|
407
|
+
*/
|
|
408
|
+
declare function own<T extends Table>(db: Queryable, table: T): T;
|
|
409
|
+
//#endregion
|
|
410
|
+
export { quoteIdentifier as _, Queryable as a, own as c, ClientOptions as d, PostgresClient as f, postgresSession as g, postgresOptions as h, QueryResult as i, tablesOf as l, postgresClient as m, Database as n, Transaction as o, SessionLost as p, QueryOutsideTransaction as r, createDatabase as s, Client as t, prepared as u, quoteLiteral as v };
|