okmodel 0.3.0 → 0.5.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 +263 -23
- package/dist/contracts/catalog/document.d.ts +26 -2
- package/dist/contracts/driver.d.ts +7 -0
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/index.js +3 -3
- package/dist/dialects/pg/introspect.d.ts +6 -0
- package/dist/dialects/pg/role/sql.d.ts +21 -4
- package/dist/dialects/pg/schema.d.ts +15 -6
- package/dist/dialects/pg/table.d.ts +17 -1
- package/dist/dialects/pg/view/index.d.ts +20 -6
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/dialects/pg/view/scratch.d.ts +2 -1
- package/dist/runtime/catalog-cache.d.ts +17 -0
- package/dist/runtime/compat-words.d.ts +23 -0
- package/dist/runtime/drift-detail.d.ts +20 -4
- package/dist/runtime/drift.d.ts +4 -2
- package/dist/runtime/pg/bun.d.ts +12 -7
- package/dist/runtime/pg/bun.js +5 -2
- package/dist/runtime/pg/pg.d.ts +12 -6
- package/dist/runtime/pg/pg.js +5 -2
- package/dist/runtime/pg/pglite.d.ts +11 -3
- package/dist/runtime/pg/pglite.js +5 -2
- package/dist/runtime/pg/postgresjs.d.ts +12 -6
- package/dist/runtime/pg/postgresjs.js +5 -2
- package/dist/runtime/plan.d.ts +3 -1
- package/dist/runtime/tenancy/index.js +1 -1
- package/dist/runtime/topology.d.ts +191 -0
- package/dist/runtime/traits/index.js +7 -6
- package/dist/runtime/types.d.ts +59 -2
- package/dist/runtime/validate/index.js +2 -2
- package/dist/shared/{x6wysh83.js → 3p4b1fg0.js} +3 -5
- package/dist/shared/{ty3v3hfk.js → 47xzb9fc.js} +2 -2
- package/dist/shared/{fs0ex00p.js → 4ef7mmqf.js} +2 -2
- package/dist/shared/{qybh48nd.js → 5fqx9yh4.js} +6 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{999ade2q.js → 5vdm4sgp.js} +1 -1
- package/dist/shared/{bqha5cg6.js → 6p5k20sm.js} +2 -2
- package/dist/shared/{t616ynfn.js → 8bwbwy8h.js} +71 -13
- package/dist/shared/{th14ygv2.js → 8ktwd3rh.js} +29 -1
- package/dist/shared/{wekze34d.js → 8xsbagad.js} +74 -2
- package/dist/shared/{bryqk9k9.js → 922qbgnw.js} +3 -3
- package/dist/shared/{meck53jv.js → 990a291j.js} +6 -5
- package/dist/shared/{jns2wx4t.js → 9tgmr1gh.js} +1 -1
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/{2ssqrv66.js → ayz64vzj.js} +1037 -181
- package/dist/shared/{k34e0xf2.js → bt9sfq0z.js} +16 -14
- package/dist/shared/{scwxrpx2.js → bzsjtd7c.js} +84 -15
- package/dist/shared/{m9tv7xn7.js → ckjbyrt9.js} +4 -4
- package/dist/shared/{ydaz1sv3.js → dxjp14rk.js} +10 -2
- package/dist/shared/{49ypnfwt.js → fancm5pt.js} +24 -229
- package/dist/shared/{6bazvqwm.js → fb00y8fp.js} +2 -2
- package/dist/shared/{1tfdfvhh.js → fyqkk1m0.js} +6 -4
- package/dist/shared/g516zdsb.js +905 -0
- package/dist/shared/{jkc6ws1p.js → g7ez901n.js} +83 -2
- package/dist/shared/{kgnc8grt.js → gdh9mrtp.js} +1 -1
- package/dist/shared/{p24x2334.js → h4nqvjkp.js} +5 -3
- package/dist/shared/{edwqqryd.js → h8ne16fq.js} +1 -1
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/jdgqqx31.js +72 -0
- package/dist/shared/{6w5j844a.js → jsd07prz.js} +2 -2
- package/dist/shared/{m78s7898.js → k7cc9nzk.js} +24 -7
- package/dist/shared/kdkxh3kb.js +758 -0
- package/dist/shared/nkc9sfqb.js +1161 -0
- package/dist/shared/{xva8v7qk.js → p7pfx624.js} +5 -5
- package/dist/shared/{xrfnq5k8.js → qgvt8nx1.js} +11 -2
- package/dist/shared/{ne02ng5c.js → qy9rdq0g.js} +9 -5
- package/dist/shared/{3ekj9x92.js → r6pj4fq2.js} +5 -3
- package/dist/shared/r73pt594.js +426 -0
- package/dist/shared/rasvvzgz.js +21 -0
- package/dist/shared/{01yr20s5.js → sf8m6tfy.js} +2 -2
- package/dist/shared/{hcmdtwgh.js → szm0cksa.js} +4 -1
- package/dist/shared/{axhk06q1.js → tq9afp8d.js} +1 -1
- package/dist/shared/{xw1d69vd.js → wqem4jed.js} +6 -6
- package/dist/shared/wxn4b7pp.js +252 -0
- package/dist/shared/xdpj5kkm.js +2203 -0
- package/dist/shared/xhh1srw3.js +589 -0
- package/dist/shared/{mt5wswjz.js → xsq7v6wp.js} +2 -2
- package/dist/shared/{7fvtrkwr.js → ycatkxmq.js} +1 -1
- package/dist/shared/ykv7wh5b.js +14 -0
- package/dist/shared/{fptpmvxp.js → z2rnngj4.js} +26 -21
- package/dist/tooling/cli.js +46 -17
- package/dist/tooling/migrate/apply.d.ts +61 -5
- package/dist/tooling/migrate/backfill.d.ts +136 -0
- package/dist/tooling/migrate/check.d.ts +65 -0
- package/dist/tooling/migrate/classify.d.ts +108 -0
- package/dist/tooling/migrate/commands.d.ts +2 -2
- package/dist/tooling/migrate/config.d.ts +22 -0
- package/dist/tooling/migrate/doctor.d.ts +3 -0
- package/dist/tooling/migrate/drift.d.ts +18 -2
- package/dist/tooling/migrate/estimate.d.ts +50 -0
- package/dist/tooling/migrate/extensions.d.ts +2 -0
- package/dist/tooling/migrate/files.d.ts +19 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +69 -1
- package/dist/tooling/migrate/lint-rules.d.ts +51 -0
- package/dist/tooling/migrate/lint.d.ts +71 -0
- package/dist/tooling/migrate/managed.d.ts +1 -1
- package/dist/tooling/migrate/plan.d.ts +64 -9
- package/dist/tooling/migrate/project.d.ts +42 -7
- package/dist/tooling/migrate/provision.d.ts +18 -0
- package/dist/tooling/migrate/reference.d.ts +40 -0
- package/dist/tooling/migrate/runner.d.ts +108 -0
- package/dist/tooling/migrate/safe.d.ts +77 -0
- package/dist/tooling/migrate/seed.d.ts +20 -0
- package/dist/tooling/migrate/snapshot.d.ts +78 -0
- package/dist/tooling/migrate/status.d.ts +25 -6
- package/dist/tooling/testing/factories.d.ts +117 -0
- package/dist/tooling/testing/facts.d.ts +75 -0
- package/dist/tooling/testing/index.d.ts +89 -0
- package/dist/tooling/testing/index.js +8 -0
- package/dist/tooling/testing/isolation.d.ts +30 -0
- package/dist/tooling/testing/random.d.ts +40 -0
- package/dist/tooling/testing/record.d.ts +38 -0
- package/package.json +6 -2
- package/dist/shared/5nmdenb6.js +0 -1229
- package/dist/shared/dbjej1tw.js +0 -456
- package/dist/shared/g4f5kcx9.js +0 -37
- package/dist/shared/qbxzvwwc.js +0 -88
- package/dist/shared/zwmqxb0g.js +0 -79
- /package/dist/shared/{75xkjv0t.js → fa9vt245.js} +0 -0
- /package/dist/shared/{0jc3ffzf.js → zvbjc949.js} +0 -0
|
@@ -34,10 +34,15 @@ export type ViewOptions = {
|
|
|
34
34
|
*
|
|
35
35
|
* `contribute` builds the catalog record. Column dependencies are filled
|
|
36
36
|
* from `pg_depend` by scratch verification, not at this call.
|
|
37
|
+
*
|
|
38
|
+
* @typeParam N - View name
|
|
39
|
+
* @typeParam C - Declared output columns
|
|
37
40
|
*/
|
|
38
|
-
export type ViewDeclaration = {
|
|
39
|
-
readonly name:
|
|
41
|
+
export type ViewDeclaration<N extends string = string, C extends readonly ViewColumnInput[] = readonly ViewColumnInput[]> = {
|
|
42
|
+
readonly name: N;
|
|
40
43
|
readonly schema: string;
|
|
44
|
+
/** Declared columns, for types only. `db.views` reads them. */
|
|
45
|
+
readonly "~columns"?: C;
|
|
41
46
|
/**
|
|
42
47
|
* Catalog record for this declaration.
|
|
43
48
|
*
|
|
@@ -73,10 +78,15 @@ export type MaterializedViewOptions = ViewOptions & {
|
|
|
73
78
|
* One declared materialized view.
|
|
74
79
|
*
|
|
75
80
|
* Identity is `(namespace, name)`. Indexes are separate catalog objects.
|
|
81
|
+
*
|
|
82
|
+
* @typeParam N - Materialized view name
|
|
83
|
+
* @typeParam C - Declared output columns
|
|
76
84
|
*/
|
|
77
|
-
export type MaterializedViewDeclaration = {
|
|
78
|
-
readonly name:
|
|
85
|
+
export type MaterializedViewDeclaration<N extends string = string, C extends readonly ViewColumnInput[] = readonly ViewColumnInput[]> = {
|
|
86
|
+
readonly name: N;
|
|
79
87
|
readonly schema: string;
|
|
88
|
+
/** Declared columns, for types only. `db.views` reads them. */
|
|
89
|
+
readonly "~columns"?: C;
|
|
80
90
|
/**
|
|
81
91
|
* Catalog records for this declaration.
|
|
82
92
|
*
|
|
@@ -100,7 +110,9 @@ export type MaterializedViewDeclaration = {
|
|
|
100
110
|
* @param options - Columns and query
|
|
101
111
|
* @returns The definition object `schema({ views })` stores
|
|
102
112
|
*/
|
|
103
|
-
export declare function view(name:
|
|
113
|
+
export declare function view<const N extends string, const C extends readonly ViewColumnInput[]>(name: N, options: ViewOptions & {
|
|
114
|
+
readonly columns: C;
|
|
115
|
+
}): ViewDeclaration<N, C>;
|
|
104
116
|
/**
|
|
105
117
|
* Declares a materialized view.
|
|
106
118
|
*
|
|
@@ -111,4 +123,6 @@ export declare function view(name: string, options: ViewOptions): ViewDeclaratio
|
|
|
111
123
|
* @param options - Columns, query, indexes, and refresh mode
|
|
112
124
|
* @returns The definition object `schema({ views })` stores
|
|
113
125
|
*/
|
|
114
|
-
export declare function materializedView(name:
|
|
126
|
+
export declare function materializedView<const N extends string, const C extends readonly ViewColumnInput[]>(name: N, options: MaterializedViewOptions & {
|
|
127
|
+
readonly columns: C;
|
|
128
|
+
}): MaterializedViewDeclaration<N, C>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Verifies declared views on a scratch schema.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Domain and enum types from the catalog are created there, then the tables,
|
|
5
|
+
* then the functions a view may call, then each view. `pg_get_viewdef`
|
|
5
6
|
* replaces the author query and `pg_depend` supplies column edges (D117).
|
|
6
7
|
* The scratch schema is dropped before this returns. Plans never use it.
|
|
7
8
|
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One in-flight catalog load per key.
|
|
3
|
+
*
|
|
4
|
+
* Concurrent `connect()` calls in one process share the parse. A failure is
|
|
5
|
+
* dropped so the next call can try again. Success stays for the process.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Runs `load` once for `key`.
|
|
9
|
+
*
|
|
10
|
+
* The map is filled before `load` starts, so a second call on the same tick
|
|
11
|
+
* waits on the first promise instead of parsing again.
|
|
12
|
+
*
|
|
13
|
+
* @param key - Directory and hash, or the artifact hash
|
|
14
|
+
* @param load - Reads and trusts the catalog
|
|
15
|
+
* @returns The shared load
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadOnce(key: string, load: () => Promise<void>): Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Words shared by `connect()` and `okm migrate status` (D197).
|
|
3
|
+
*
|
|
4
|
+
* The startup check and the status command name the same situations.
|
|
5
|
+
* A failed step adds the resume hint status prints.
|
|
6
|
+
*/
|
|
7
|
+
/** The database and the app record the same catalog. */
|
|
8
|
+
export declare const CURRENT = "current";
|
|
9
|
+
/** Pending migrations are expand only. */
|
|
10
|
+
export declare const BEHIND_EXPAND = "behind by expand";
|
|
11
|
+
/** A pending migration is not expand. */
|
|
12
|
+
export declare const BEHIND_CONTRACT = "behind by contract";
|
|
13
|
+
/** The database has expand migrations the app does not. */
|
|
14
|
+
export declare const AHEAD_EXPAND = "ahead by expand";
|
|
15
|
+
/** The database has a contract migration the app does not. */
|
|
16
|
+
export declare const AHEAD_CONTRACT = "ahead by contract";
|
|
17
|
+
/**
|
|
18
|
+
* Status text for a migration that stopped mid-way.
|
|
19
|
+
*
|
|
20
|
+
* @param step - Zero-based step that has no `okm_history` row
|
|
21
|
+
* @returns The state, including the resume hint
|
|
22
|
+
*/
|
|
23
|
+
export declare function failedAt(step: number): string;
|
|
@@ -2,25 +2,41 @@
|
|
|
2
2
|
* Compatibility check used only when the catalog hashes differ.
|
|
3
3
|
*
|
|
4
4
|
* Ahead by expand is compatible. Ahead by a contract step, or behind, fails
|
|
5
|
-
* closed (OKM1520).
|
|
5
|
+
* closed (OKM1520). The class is the value stored in `okm_history`.
|
|
6
6
|
*/
|
|
7
7
|
import type { DriverPool, ExecuteOptions } from "../contracts/driver.js";
|
|
8
8
|
/** One applied migration, in history order. */
|
|
9
9
|
export type DriftMigration = {
|
|
10
10
|
readonly id: string;
|
|
11
11
|
readonly catalogHash: string;
|
|
12
|
-
/** True when every step is expand
|
|
12
|
+
/** True when every stored step class is `expand`. */
|
|
13
13
|
readonly expand: boolean;
|
|
14
14
|
};
|
|
15
|
+
/** How far the database and the app have diverged. */
|
|
16
|
+
export type DriftVerdict = {
|
|
17
|
+
readonly state: "ok";
|
|
18
|
+
} | {
|
|
19
|
+
readonly state: "ahead by contract";
|
|
20
|
+
readonly migrationId: string;
|
|
21
|
+
} | {
|
|
22
|
+
readonly state: "behind by expand";
|
|
23
|
+
readonly migrationId: string;
|
|
24
|
+
} | {
|
|
25
|
+
readonly state: "behind by contract";
|
|
26
|
+
readonly migrationId: string;
|
|
27
|
+
} | {
|
|
28
|
+
readonly state: "behind";
|
|
29
|
+
readonly migrationId: string;
|
|
30
|
+
};
|
|
15
31
|
/**
|
|
16
|
-
* Classifies a hash mismatch.
|
|
32
|
+
* Classifies a hash mismatch from stored history classes.
|
|
17
33
|
*
|
|
18
34
|
* @param codeHash - Hash of the code's catalog
|
|
19
35
|
* @param recordedHash - Hash stored in `okm_meta`
|
|
20
36
|
* @param migrations - Applied migrations, oldest first
|
|
21
37
|
* @returns `ok` when the database is ahead by expand only
|
|
22
38
|
*/
|
|
23
|
-
export declare function driftVerdict(codeHash: string, recordedHash: string, migrations: readonly DriftMigration[]):
|
|
39
|
+
export declare function driftVerdict(codeHash: string, recordedHash: string, migrations: readonly DriftMigration[]): DriftVerdict;
|
|
24
40
|
/**
|
|
25
41
|
* Reads history and throws OKM1520 when the database is not expand-ahead.
|
|
26
42
|
*
|
package/dist/runtime/drift.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Startup catalog check.
|
|
3
3
|
*
|
|
4
|
-
* The fast path compares two hashes. History
|
|
5
|
-
*
|
|
4
|
+
* The fast path compares two hashes and returns. History and
|
|
5
|
+
* `.okm/catalog.json` load only when those hashes differ. A hash read from
|
|
6
|
+
* `catalog.hash` requires that JSON file; a missing file or a hash that does
|
|
7
|
+
* not match is OKM1027. Concurrent loads share one parse.
|
|
6
8
|
*/
|
|
7
9
|
import type { DriverPool, ExecuteOptions } from "../contracts/driver.js";
|
|
8
10
|
import type { QuerySchema } from "../dialects/pg/model.js";
|
package/dist/runtime/pg/bun.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `connect` for Bun.sql (`okmodel/pg/bun`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* inside the adapter.
|
|
4
|
+
* A string or an existing pool is one endpoint. A `{ primary, replicas }` object
|
|
5
|
+
* loads the topology module. The client is typed by the schema passed in.
|
|
6
|
+
* This entry runs on Bun. Node cannot load the `bun` import inside the adapter.
|
|
7
7
|
*/
|
|
8
8
|
import type { DriverPool } from "../../contracts/driver.js";
|
|
9
9
|
import type { QuerySchema } from "../../dialects/pg/model.js";
|
|
10
10
|
import { type BunSqlConfig } from "../../adapters/pg/bunsql.js";
|
|
11
|
+
import type { RoutedClient, TopologyInput, TopologyOptions } from "../topology.js";
|
|
11
12
|
import type { ConnectOptions, Connected } from "../types.js";
|
|
12
13
|
export { open, type BunSqlConfig, type BunSqlTls } from "../../adapters/pg/bunsql.js";
|
|
13
14
|
export { capabilities, hasCapability, readCapability } from "../../adapters/pg/bunsql.js";
|
|
@@ -15,16 +16,20 @@ export { DriverError } from "../../adapters/error.js";
|
|
|
15
16
|
/** A connection string or a pool from {@link open}. */
|
|
16
17
|
export type BunSqlTarget = string | DriverPool;
|
|
17
18
|
/** Driver options `connect` forwards to {@link open}. */
|
|
18
|
-
export type BunSqlConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<BunSqlConfig, "url"
|
|
19
|
+
export type BunSqlConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<BunSqlConfig, "url"> & TopologyOptions;
|
|
19
20
|
/**
|
|
20
|
-
* Connects one Postgres endpoint through Bun.sql
|
|
21
|
+
* Connects one Postgres endpoint through Bun.sql, or a primary and its replicas.
|
|
22
|
+
*
|
|
23
|
+
* A string or a pool is one endpoint. A topology loads on demand and the promise
|
|
24
|
+
* resolves to the client. Reads use the first healthy replica.
|
|
21
25
|
*
|
|
22
26
|
* Named prepared statements are off unless `prepared` is `"named"`.
|
|
23
27
|
* `prepared: "named"` is not for transaction-mode poolers.
|
|
24
28
|
*
|
|
25
29
|
* @typeParam S - Schema
|
|
26
|
-
* @param target - URL
|
|
30
|
+
* @param target - URL, an existing pool, or `{ primary, replicas }`
|
|
27
31
|
* @param options - Schema, errors, logger, and driver options
|
|
28
|
-
* @returns The client. Await `connected` for the dialect check
|
|
32
|
+
* @returns The client. A topology returns a promise. Await `connected` for the dialect check
|
|
29
33
|
*/
|
|
34
|
+
export declare function connect<const S extends QuerySchema>(target: TopologyInput, options: BunSqlConnectOptions<S>): Promise<RoutedClient<S>>;
|
|
30
35
|
export declare function connect<const S extends QuerySchema>(target: BunSqlTarget, options: BunSqlConnectOptions<S>): Connected<S>;
|
package/dist/runtime/pg/bun.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/kyxb62mc.js";
|
|
4
4
|
import {
|
|
5
5
|
open5
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/sf8m6tfy.js";
|
|
7
7
|
import {
|
|
8
8
|
BUNSQL_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,10 +11,13 @@ import {
|
|
|
11
11
|
} from "../../shared/rrstp3kb.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/bt9sfq0z.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/bun.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
|
+
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
+
return import("../../shared/nkc9sfqb.js").then((mod) => mod.default(target, options, open5));
|
|
20
|
+
}
|
|
18
21
|
const owned = !isPool(target);
|
|
19
22
|
const pool = isPool(target) ? target : open5({
|
|
20
23
|
url: target,
|
package/dist/runtime/pg/pg.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `connect` for node-postgres (`okmodel/pg/pg`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* schema passed in, not
|
|
4
|
+
* A string or an existing pool is one endpoint. A `{ primary, replicas }` object
|
|
5
|
+
* loads the topology module. The client is typed by the schema passed in, not
|
|
6
|
+
* by `Register`.
|
|
6
7
|
*/
|
|
7
8
|
import type { DriverPool } from "../../contracts/driver.js";
|
|
8
9
|
import type { QuerySchema } from "../../dialects/pg/model.js";
|
|
9
10
|
import { type NodePostgresConfig } from "../../adapters/pg/nodepostgres.js";
|
|
11
|
+
import type { RoutedClient, TopologyInput, TopologyOptions } from "../topology.js";
|
|
10
12
|
import type { ConnectOptions, Connected } from "../types.js";
|
|
11
13
|
export { open, type NodePostgresConfig } from "../../adapters/pg/nodepostgres.js";
|
|
12
14
|
export { capabilities, hasCapability, readCapability } from "../../adapters/pg/nodepostgres.js";
|
|
@@ -14,16 +16,20 @@ export { DriverError } from "../../adapters/error.js";
|
|
|
14
16
|
/** A connection string or a pool from {@link open}. */
|
|
15
17
|
export type NodePostgresTarget = string | DriverPool;
|
|
16
18
|
/** Driver options `connect` forwards to {@link open}. */
|
|
17
|
-
export type NodePostgresConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<NodePostgresConfig, "url"
|
|
19
|
+
export type NodePostgresConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<NodePostgresConfig, "url"> & TopologyOptions;
|
|
18
20
|
/**
|
|
19
|
-
* Connects one Postgres endpoint through node-postgres
|
|
21
|
+
* Connects one Postgres endpoint through node-postgres, or a primary and its replicas.
|
|
22
|
+
*
|
|
23
|
+
* A string or a pool is one endpoint. A topology loads on demand and the promise
|
|
24
|
+
* resolves to the client. Reads use the first healthy replica.
|
|
20
25
|
*
|
|
21
26
|
* Named prepared statements are off unless `prepared` is `"named"`.
|
|
22
27
|
* `prepared: "named"` is not for transaction-mode poolers.
|
|
23
28
|
*
|
|
24
29
|
* @typeParam S - Schema
|
|
25
|
-
* @param target - URL
|
|
30
|
+
* @param target - URL, an existing pool, or `{ primary, replicas }`
|
|
26
31
|
* @param options - Schema, errors, logger, and driver options
|
|
27
|
-
* @returns The client. Await `connected` for the dialect check
|
|
32
|
+
* @returns The client. A topology returns a promise. Await `connected` for the dialect check
|
|
28
33
|
*/
|
|
34
|
+
export declare function connect<const S extends QuerySchema>(target: TopologyInput, options: NodePostgresConnectOptions<S>): Promise<RoutedClient<S>>;
|
|
29
35
|
export declare function connect<const S extends QuerySchema>(target: NodePostgresTarget, options: NodePostgresConnectOptions<S>): Connected<S>;
|
package/dist/runtime/pg/pg.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/kyxb62mc.js";
|
|
4
4
|
import {
|
|
5
5
|
open4
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/6p5k20sm.js";
|
|
7
7
|
import {
|
|
8
8
|
NODE_POSTGRES_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,10 +11,13 @@ import {
|
|
|
11
11
|
} from "../../shared/rrstp3kb.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/bt9sfq0z.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/pg.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
|
+
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
+
return import("../../shared/nkc9sfqb.js").then((mod) => mod.default(target, options, open4));
|
|
20
|
+
}
|
|
18
21
|
const owned = !isPool(target);
|
|
19
22
|
const pool = isPool(target) ? target : open4({
|
|
20
23
|
url: target,
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* `connect` for PGlite (`okmodel/pg/pglite`).
|
|
3
3
|
*
|
|
4
4
|
* Opening a database is async. An existing pool is reused and not closed.
|
|
5
|
+
* A `{ primary, replicas }` object loads the topology module. A replica URL is
|
|
6
|
+
* that endpoint's data directory.
|
|
5
7
|
*/
|
|
6
8
|
import type { DriverPool } from "../../contracts/driver.js";
|
|
7
9
|
import type { QuerySchema } from "../../dialects/pg/model.js";
|
|
8
10
|
import { type PgliteConfig } from "../../adapters/pg/pglite.js";
|
|
11
|
+
import type { RoutedClient, TopologyInput, TopologyOptions } from "../topology.js";
|
|
9
12
|
import type { ConnectOptions, Connected } from "../types.js";
|
|
10
13
|
export { open, type PgliteConfig } from "../../adapters/pg/pglite.js";
|
|
11
14
|
export { capabilities, hasCapability, readCapability } from "../../adapters/pg/pglite.js";
|
|
@@ -13,13 +16,18 @@ export { DriverError } from "../../adapters/error.js";
|
|
|
13
16
|
/** A data directory, a pool from {@link open}, or omitted for memory. */
|
|
14
17
|
export type PgliteTarget = string | DriverPool | undefined;
|
|
15
18
|
/** Driver options `connect` forwards to {@link open}. */
|
|
16
|
-
export type PgliteConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<PgliteConfig, "dataDir"
|
|
19
|
+
export type PgliteConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<PgliteConfig, "dataDir"> & TopologyOptions;
|
|
17
20
|
/**
|
|
18
|
-
* Connects one PGlite endpoint and returns a client for `schema`.
|
|
21
|
+
* Connects one PGlite endpoint, or a primary and its replicas, and returns a client for `schema`.
|
|
22
|
+
*
|
|
23
|
+
* A string, a pool, or an omitted target is one endpoint. A topology loads on
|
|
24
|
+
* demand. Reads use the first healthy replica. A replica `url` is that
|
|
25
|
+
* endpoint's data directory.
|
|
19
26
|
*
|
|
20
27
|
* @typeParam S - Schema
|
|
21
|
-
* @param target - Data directory, existing pool,
|
|
28
|
+
* @param target - Data directory, existing pool, omitted for memory, or `{ primary, replicas }`
|
|
22
29
|
* @param options - Schema, errors, and logger
|
|
23
30
|
* @returns The client
|
|
24
31
|
*/
|
|
32
|
+
export declare function connect<const S extends QuerySchema>(target: TopologyInput, options: PgliteConnectOptions<S>): Promise<RoutedClient<S>>;
|
|
25
33
|
export declare function connect<const S extends QuerySchema>(target: PgliteTarget, options: PgliteConnectOptions<S>): Promise<Connected<S>>;
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/kyxb62mc.js";
|
|
4
4
|
import {
|
|
5
5
|
open3
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/fa9vt245.js";
|
|
7
7
|
import {
|
|
8
8
|
PGLITE_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,10 +11,13 @@ import {
|
|
|
11
11
|
} from "../../shared/rrstp3kb.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/bt9sfq0z.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/pglite.ts
|
|
17
17
|
async function connect(target, options) {
|
|
18
|
+
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
+
return import("../../shared/nkc9sfqb.js").then((mod) => mod.default(target, options, open3));
|
|
20
|
+
}
|
|
18
21
|
const pool = isPool(target) ? target : await open3({
|
|
19
22
|
...target !== undefined ? { dataDir: target } : {},
|
|
20
23
|
...options.timeouts !== undefined ? { timeouts: options.timeouts } : {}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `connect` for postgres.js (`okmodel/pg/postgresjs`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* schema passed in, not
|
|
4
|
+
* A string or an existing pool is one endpoint. A `{ primary, replicas }` object
|
|
5
|
+
* loads the topology module. The client is typed by the schema passed in, not
|
|
6
|
+
* by `Register`.
|
|
6
7
|
*/
|
|
7
8
|
import type { DriverPool } from "../../contracts/driver.js";
|
|
8
9
|
import type { QuerySchema } from "../../dialects/pg/model.js";
|
|
9
10
|
import { type PostgresJsConfig } from "../../adapters/pg/postgresjs.js";
|
|
11
|
+
import type { RoutedClient, TopologyInput, TopologyOptions } from "../topology.js";
|
|
10
12
|
import type { ConnectOptions, Connected } from "../types.js";
|
|
11
13
|
export { open, type PostgresJsConfig } from "../../adapters/pg/postgresjs.js";
|
|
12
14
|
export { capabilities, hasCapability, readCapability } from "../../adapters/pg/postgresjs.js";
|
|
@@ -14,16 +16,20 @@ export { DriverError } from "../../adapters/error.js";
|
|
|
14
16
|
/** A connection string or a pool from {@link open}. */
|
|
15
17
|
export type PostgresTarget = string | DriverPool;
|
|
16
18
|
/** Driver options `connect` forwards to {@link open}. */
|
|
17
|
-
export type PostgresConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<PostgresJsConfig, "url"
|
|
19
|
+
export type PostgresConnectOptions<S extends QuerySchema> = ConnectOptions<S> & Omit<PostgresJsConfig, "url"> & TopologyOptions;
|
|
18
20
|
/**
|
|
19
|
-
* Connects one Postgres endpoint and returns a client for `schema`.
|
|
21
|
+
* Connects one Postgres endpoint, or a primary and its replicas, and returns a client for `schema`.
|
|
22
|
+
*
|
|
23
|
+
* A string or a pool is one endpoint. A topology loads on demand and the promise
|
|
24
|
+
* resolves to the client. Reads use the first healthy replica.
|
|
20
25
|
*
|
|
21
26
|
* Named prepared statements are off unless `prepared` is `"named"`.
|
|
22
27
|
* `prepared: "named"` is not for transaction-mode poolers.
|
|
23
28
|
*
|
|
24
29
|
* @typeParam S - Schema
|
|
25
|
-
* @param target - URL
|
|
30
|
+
* @param target - URL, an existing pool, or `{ primary, replicas }`
|
|
26
31
|
* @param options - Schema, errors, logger, and driver options
|
|
27
|
-
* @returns The client. Await `connected` for the dialect check
|
|
32
|
+
* @returns The client. A topology returns a promise. Await `connected` for the dialect check
|
|
28
33
|
*/
|
|
34
|
+
export declare function connect<const S extends QuerySchema>(target: TopologyInput, options: PostgresConnectOptions<S>): Promise<RoutedClient<S>>;
|
|
29
35
|
export declare function connect<const S extends QuerySchema>(target: PostgresTarget, options: PostgresConnectOptions<S>): Connected<S>;
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/kyxb62mc.js";
|
|
4
4
|
import {
|
|
5
5
|
open2
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/wqem4jed.js";
|
|
7
7
|
import {
|
|
8
8
|
POSTGRESJS_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,10 +11,13 @@ import {
|
|
|
11
11
|
} from "../../shared/rrstp3kb.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/bt9sfq0z.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/postgresjs.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
|
+
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
+
return import("../../shared/nkc9sfqb.js").then((mod) => mod.default(target, options, open2));
|
|
20
|
+
}
|
|
18
21
|
const owned = !isPool(target);
|
|
19
22
|
const pool = isPool(target) ? target : open2({
|
|
20
23
|
url: target,
|
package/dist/runtime/plan.d.ts
CHANGED
|
@@ -41,9 +41,11 @@ export type ReadCall = {
|
|
|
41
41
|
readonly build?: ReadBuild;
|
|
42
42
|
/** Writes the end of the statement, after `limit`. A row lock sets it. */
|
|
43
43
|
readonly tail?: (sink: Sink) => void;
|
|
44
|
-
/** The caller's `signal` and `
|
|
44
|
+
/** The caller's `signal`, `timeout`, and `route`. They never enter the plan or its key. */
|
|
45
45
|
readonly signal?: AbortSignal;
|
|
46
46
|
readonly timeout?: number;
|
|
47
|
+
/** `"primary"` or `"replica"`. Absent means the router classifies the statement. */
|
|
48
|
+
readonly route?: "primary" | "replica";
|
|
47
49
|
/** Set by `for()` or `unscoped()`. Absent on a schema with no tenancy. */
|
|
48
50
|
readonly scope?: CallScope;
|
|
49
51
|
/** Inspect lines from the tenancy object. Absent when the schema has no tenancy. */
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primary and replica endpoints (spec §15.1).
|
|
3
|
+
*
|
|
4
|
+
* Loaded only when `connect` is given a topology object. The string and pool
|
|
5
|
+
* paths do not import this module. An automatic read chooses among eligible
|
|
6
|
+
* replicas. One watermark on this handle covers the root, `for()`, `unscoped()`,
|
|
7
|
+
* `using()`, and `reserve()`.
|
|
8
|
+
*/
|
|
9
|
+
import type { DriverPool, DriverTimeouts } from "../contracts/driver.js";
|
|
10
|
+
import type { QuerySchema } from "../dialects/pg/model.js";
|
|
11
|
+
import type { ConnectOptions, Connected } from "./types.js";
|
|
12
|
+
/** `"primary"` or `"replica"`. `using` and `route` accept only these. */
|
|
13
|
+
export type RouteName = "primary" | "replica";
|
|
14
|
+
/**
|
|
15
|
+
* One routing choice.
|
|
16
|
+
*
|
|
17
|
+
* `onRoute` receives this. `inspect()` does not, until the dev inspector (M2).
|
|
18
|
+
*/
|
|
19
|
+
export type RouteEvent = {
|
|
20
|
+
/** What the statement was classified as. */
|
|
21
|
+
readonly op: "read" | "write" | "tx" | "lock";
|
|
22
|
+
/** Endpoint name. The primary is `"primary"`. */
|
|
23
|
+
readonly endpoint: string;
|
|
24
|
+
/**
|
|
25
|
+
* `primary-required`, `constraint:primary`, `constraint:replica`,
|
|
26
|
+
* `auto:<name>`, or `fallback:<no-replicas | unhealthy | position-unknown | saturated | behind>`.
|
|
27
|
+
*/
|
|
28
|
+
readonly reason: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* One replica passed to a custom `routing.select`.
|
|
32
|
+
*
|
|
33
|
+
* `lag` is the replica's byte lag, or `null` when the primary insert position
|
|
34
|
+
* or the replica replay position has not been seen. `latencyMs` stays `null`
|
|
35
|
+
* until a probe or a successful read has been timed.
|
|
36
|
+
*/
|
|
37
|
+
export type ReplicaCandidate = {
|
|
38
|
+
/** Endpoint name. */
|
|
39
|
+
readonly name: string;
|
|
40
|
+
/** Configured weight. Zero and below are OKM1120 at connect. */
|
|
41
|
+
readonly weight: number;
|
|
42
|
+
/** In-flight statements this router is running on the replica. */
|
|
43
|
+
readonly inflight: number;
|
|
44
|
+
/** EWMA of observed round-trip time, in milliseconds, or `null`. */
|
|
45
|
+
readonly latencyMs: number | null;
|
|
46
|
+
/** Byte lag behind the primary, or `null` when either position is unknown. */
|
|
47
|
+
readonly lag: number | null;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* A topology client.
|
|
51
|
+
*
|
|
52
|
+
* `using` returns a client that forces one route. That client has no `close`
|
|
53
|
+
* and no `using`. Only the root closes the pools.
|
|
54
|
+
*/
|
|
55
|
+
export type RoutedClient<S extends QuerySchema> = Connected<S> & {
|
|
56
|
+
/**
|
|
57
|
+
* Forces later operations onto the primary or a replica.
|
|
58
|
+
*
|
|
59
|
+
* @param route - `"primary"` or `"replica"`
|
|
60
|
+
* @returns A client with no `close` and no `using`
|
|
61
|
+
*/
|
|
62
|
+
using(route: RouteName): Omit<Connected<S>, "close">;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Replay position for one replica.
|
|
66
|
+
*
|
|
67
|
+
* Tests supply this over independent databases. The probe still runs `SELECT 1`
|
|
68
|
+
* on the replica's pool. The position does not come from a mocked driver.
|
|
69
|
+
*/
|
|
70
|
+
export type ReplicaState = {
|
|
71
|
+
/**
|
|
72
|
+
* @param endpoint - The replica being probed
|
|
73
|
+
* @returns The replay LSN, or `null` when the replica has not replayed
|
|
74
|
+
*/
|
|
75
|
+
replayLsn(endpoint: {
|
|
76
|
+
readonly name: string;
|
|
77
|
+
}): string | null | Promise<string | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Replay timestamp for a time `maxLag`.
|
|
80
|
+
*
|
|
81
|
+
* Omitted, and with no seam, the probe reads `pg_last_xact_replay_timestamp()`
|
|
82
|
+
* only when `maxLag` is a duration.
|
|
83
|
+
*
|
|
84
|
+
* @param endpoint - The replica being probed
|
|
85
|
+
* @returns A timestamp, or `null` when the replica has not replayed a transaction
|
|
86
|
+
*/
|
|
87
|
+
replayTime?(endpoint: {
|
|
88
|
+
readonly name: string;
|
|
89
|
+
}): Date | string | null | Promise<Date | string | null>;
|
|
90
|
+
};
|
|
91
|
+
/** One replica in `{ primary, replicas }`. A string is a URL with weight 1. */
|
|
92
|
+
export type ReplicaInput = {
|
|
93
|
+
readonly url: string;
|
|
94
|
+
readonly weight?: number;
|
|
95
|
+
readonly name?: string;
|
|
96
|
+
readonly pool?: {
|
|
97
|
+
readonly max?: number;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
/** The first argument of `connect` when it is a topology. */
|
|
101
|
+
export type TopologyInput = {
|
|
102
|
+
readonly primary: string;
|
|
103
|
+
readonly replicas?: readonly (string | ReplicaInput)[];
|
|
104
|
+
};
|
|
105
|
+
/** Options only the topology module reads. */
|
|
106
|
+
export type TopologyOptions = {
|
|
107
|
+
/**
|
|
108
|
+
* Background probe interval. `"1s"` when omitted.
|
|
109
|
+
*
|
|
110
|
+
* `select` chooses among eligible replicas. The default is `"weighted"`.
|
|
111
|
+
* `consistency` is `"session"` (the default) or `"eventual"`. `maxLag` is a
|
|
112
|
+
* duration (`"5s"`, `"500ms"`, `"2m"`) or a size (`"16MB"`, `"512KB"`,
|
|
113
|
+
* `"1GB"`, `"4096B"`). `fallback` is `"primary"` (the default) or `"error"`.
|
|
114
|
+
*/
|
|
115
|
+
readonly routing?: {
|
|
116
|
+
readonly probe?: string | number;
|
|
117
|
+
readonly select?: "weighted" | "roundRobin" | "leastConnections" | "latencyAware" | ((candidates: readonly ReplicaCandidate[], ctx: {
|
|
118
|
+
readonly op: "read";
|
|
119
|
+
}) => ReplicaCandidate | string);
|
|
120
|
+
readonly consistency?: "session" | "eventual";
|
|
121
|
+
readonly fallback?: "primary" | "error";
|
|
122
|
+
readonly maxLag?: string;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Called after an endpoint is chosen.
|
|
126
|
+
*
|
|
127
|
+
* A throw is swallowed. The operation still runs.
|
|
128
|
+
*/
|
|
129
|
+
readonly onRoute?: (event: RouteEvent) => void;
|
|
130
|
+
/** Test seam for replay positions. Omitted, the probe reads `pg_last_wal_replay_lsn()`. */
|
|
131
|
+
readonly replicaState?: ReplicaState;
|
|
132
|
+
};
|
|
133
|
+
/** One endpoint after connect. Tests read this. It is not the query path. */
|
|
134
|
+
export type EndpointView = {
|
|
135
|
+
readonly name: string;
|
|
136
|
+
readonly role: "primary" | "replica";
|
|
137
|
+
readonly weight: number;
|
|
138
|
+
/** `max` passed to the driver. Absent when connect did not set one. */
|
|
139
|
+
readonly max: number | undefined;
|
|
140
|
+
/** Whether `replication.position` was detected on this endpoint. */
|
|
141
|
+
readonly position: boolean;
|
|
142
|
+
readonly circuit: "closed" | "open";
|
|
143
|
+
readonly failures: number;
|
|
144
|
+
readonly replayLsn: string | null;
|
|
145
|
+
/** Delay until the next probe. The primary is 0. */
|
|
146
|
+
readonly nextDelayMs: number;
|
|
147
|
+
};
|
|
148
|
+
/** The topology a client was built with. */
|
|
149
|
+
export type TopologyView = {
|
|
150
|
+
readonly endpoints: readonly EndpointView[];
|
|
151
|
+
};
|
|
152
|
+
/** Fields each driver's `open` may read. Extra keys are ignored by that driver. */
|
|
153
|
+
type EndpointConfig = {
|
|
154
|
+
readonly url: string;
|
|
155
|
+
readonly dataDir: string;
|
|
156
|
+
readonly max?: number;
|
|
157
|
+
readonly timeouts?: DriverTimeouts;
|
|
158
|
+
readonly prepared?: "named" | "unnamed";
|
|
159
|
+
readonly searchPath?: string;
|
|
160
|
+
readonly ssl?: unknown;
|
|
161
|
+
};
|
|
162
|
+
/** Opens one endpoint. postgres.js reads `url`. PGlite reads `dataDir`. */
|
|
163
|
+
export type EndpointOpen = (config: EndpointConfig) => DriverPool | Promise<DriverPool>;
|
|
164
|
+
/**
|
|
165
|
+
* Opens one pool per endpoint, detects `replication.position`, and starts replica probes.
|
|
166
|
+
*
|
|
167
|
+
* An automatic read runs the selection pipeline and `routing.select`.
|
|
168
|
+
* `close()` stops the probes and closes every pool this call opened,
|
|
169
|
+
* including clients from `using`.
|
|
170
|
+
*
|
|
171
|
+
* @param target - `{ primary, replicas }`
|
|
172
|
+
* @param options - Schema, pool default, probe interval, and the optional seam
|
|
173
|
+
* @param open - The driver's `open`
|
|
174
|
+
* @returns The client
|
|
175
|
+
*/
|
|
176
|
+
export declare function connectTopology<S extends QuerySchema>(target: object, options: ConnectOptions<S> & TopologyOptions & {
|
|
177
|
+
readonly max?: number;
|
|
178
|
+
readonly prepared?: "named" | "unnamed";
|
|
179
|
+
readonly searchPath?: string;
|
|
180
|
+
readonly ssl?: unknown;
|
|
181
|
+
}, open: EndpointOpen): Promise<RoutedClient<S>>;
|
|
182
|
+
/**
|
|
183
|
+
* Reads the endpoints recorded for a client this module built.
|
|
184
|
+
*
|
|
185
|
+
* A string `connect` has no record. Routing does not call this.
|
|
186
|
+
*
|
|
187
|
+
* @param client - The value `connect` returned
|
|
188
|
+
* @returns The endpoints, or `undefined` when `client` is not a topology client
|
|
189
|
+
*/
|
|
190
|
+
export declare function readTopology(client: object): TopologyView | undefined;
|
|
191
|
+
export default connectTopology;
|