okmodel 0.0.0 → 0.1.1
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 +246 -1
- package/dist/adapters/capabilities.d.ts +62 -0
- package/dist/adapters/error.d.ts +91 -0
- package/dist/adapters/failure.d.ts +39 -0
- package/dist/adapters/pg/batch.d.ts +36 -0
- package/dist/adapters/pg/call.d.ts +59 -0
- package/dist/adapters/pg/pglite.d.ts +21 -0
- package/dist/adapters/pg/postgres-extra.d.ts +43 -0
- package/dist/adapters/pg/postgresjs.d.ts +95 -0
- package/dist/adapters/pg/result.d.ts +30 -0
- package/dist/contracts/catalog/build.d.ts +18 -0
- package/dist/contracts/catalog/document.d.ts +79 -0
- package/dist/contracts/catalog/enum.d.ts +35 -0
- package/dist/contracts/catalog/identifier.d.ts +71 -0
- package/dist/contracts/catalog/identity.d.ts +98 -0
- package/dist/contracts/catalog/index.d.ts +11 -0
- package/dist/contracts/catalog/json.d.ts +17 -0
- package/dist/contracts/catalog/object.d.ts +142 -0
- package/dist/contracts/catalog/order.d.ts +43 -0
- package/dist/contracts/catalog/rewrite.d.ts +18 -0
- package/dist/contracts/catalog/types.d.ts +292 -0
- package/dist/contracts/catalog/words.d.ts +13 -0
- package/dist/contracts/connection.d.ts +33 -0
- package/dist/contracts/driver.d.ts +163 -0
- package/dist/contracts/error.d.ts +298 -0
- package/dist/contracts/index.d.ts +11 -0
- package/dist/contracts/index.js +16 -0
- package/dist/contracts/internal.d.ts +15 -0
- package/dist/contracts/internal.js +68 -0
- package/dist/contracts/nearest.d.ts +15 -0
- package/dist/contracts/rows.d.ts +84 -0
- package/dist/contracts/sha256.d.ts +14 -0
- package/dist/contracts/utf8.d.ts +33 -0
- package/dist/dialects/pg/array-literal.d.ts +25 -0
- package/dist/dialects/pg/bool.d.ts +46 -0
- package/dist/dialects/pg/column.d.ts +386 -0
- package/dist/dialects/pg/compile.d.ts +81 -0
- package/dist/dialects/pg/custom.d.ts +21 -0
- package/dist/dialects/pg/ddl.d.ts +70 -0
- package/dist/dialects/pg/decimal.d.ts +62 -0
- package/dist/dialects/pg/declarations.d.ts +34 -0
- package/dist/dialects/pg/emit.d.ts +18 -0
- package/dist/dialects/pg/enum.d.ts +30 -0
- package/dist/dialects/pg/errors.d.ts +30 -0
- package/dist/dialects/pg/finite.d.ts +15 -0
- package/dist/dialects/pg/geometry.d.ts +55 -0
- package/dist/dialects/pg/index.d.ts +45 -0
- package/dist/dialects/pg/index.js +1821 -0
- package/dist/dialects/pg/integer.d.ts +96 -0
- package/dist/dialects/pg/introspect.d.ts +43 -0
- package/dist/dialects/pg/json.d.ts +43 -0
- package/dist/dialects/pg/keys.d.ts +32 -0
- package/dist/dialects/pg/misuse.d.ts +31 -0
- package/dist/dialects/pg/model.d.ts +71 -0
- package/dist/dialects/pg/namespace.d.ts +63 -0
- package/dist/dialects/pg/network.d.ts +28 -0
- package/dist/dialects/pg/operators.d.ts +71 -0
- package/dist/dialects/pg/ops/between.d.ts +10 -0
- package/dist/dialects/pg/ops/contains.d.ts +8 -0
- package/dist/dialects/pg/ops/endsWith.d.ts +8 -0
- package/dist/dialects/pg/ops/eq.d.ts +9 -0
- package/dist/dialects/pg/ops/every.d.ts +9 -0
- package/dist/dialects/pg/ops/gt.d.ts +9 -0
- package/dist/dialects/pg/ops/gte.d.ts +9 -0
- package/dist/dialects/pg/ops/has.d.ts +9 -0
- package/dist/dialects/pg/ops/ilike.d.ts +8 -0
- package/dist/dialects/pg/ops/inList.d.ts +9 -0
- package/dist/dialects/pg/ops/inc.d.ts +13 -0
- package/dist/dialects/pg/ops/like.d.ts +8 -0
- package/dist/dialects/pg/ops/lt.d.ts +9 -0
- package/dist/dialects/pg/ops/lte.d.ts +9 -0
- package/dist/dialects/pg/ops/none.d.ts +9 -0
- package/dist/dialects/pg/ops/not.d.ts +9 -0
- package/dist/dialects/pg/ops/notIn.d.ts +9 -0
- package/dist/dialects/pg/ops/or.d.ts +9 -0
- package/dist/dialects/pg/ops/startsWith.d.ts +8 -0
- package/dist/dialects/pg/quote.d.ts +24 -0
- package/dist/dialects/pg/range.d.ts +50 -0
- package/dist/dialects/pg/relations.d.ts +45 -0
- package/dist/dialects/pg/schema.d.ts +77 -0
- package/dist/dialects/pg/search.d.ts +23 -0
- package/dist/dialects/pg/table.d.ts +201 -0
- package/dist/dialects/pg/temporal.d.ts +211 -0
- package/dist/dialects/pg/text.d.ts +44 -0
- package/dist/dialects/pg/time.d.ts +46 -0
- package/dist/okm.js +2 -0
- package/dist/okmodel.js +2 -0
- package/dist/runtime/client.d.ts +47 -0
- package/dist/runtime/conflict.d.ts +38 -0
- package/dist/runtime/drift-detail.d.ts +32 -0
- package/dist/runtime/drift.d.ts +29 -0
- package/dist/runtime/include.d.ts +15 -0
- package/dist/runtime/pg/pglite.d.ts +25 -0
- package/dist/runtime/pg/pglite.js +48 -0
- package/dist/runtime/pg/postgresjs.d.ts +29 -0
- package/dist/runtime/pg/postgresjs.js +62 -0
- package/dist/runtime/plan.d.ts +167 -0
- package/dist/runtime/tx.d.ts +29 -0
- package/dist/runtime/types.d.ts +385 -0
- package/dist/runtime/write.d.ts +48 -0
- package/dist/shared/05w44d8g.js +1524 -0
- package/dist/shared/523ft3e8.js +171 -0
- package/dist/shared/8b04d28c.js +14 -0
- package/dist/shared/cn0n68ft.js +16 -0
- package/dist/shared/dkn3y60a.js +374 -0
- package/dist/shared/dynq16vb.js +81 -0
- package/dist/shared/fgqgsb5z.js +281 -0
- package/dist/shared/g5fhqmwe.js +188 -0
- package/dist/shared/gk7cs7sp.js +566 -0
- package/dist/shared/hadrfb9h.js +398 -0
- package/dist/shared/hd293j9g.js +98 -0
- package/dist/shared/j5cn2963.js +701 -0
- package/dist/shared/jjb7yht9.js +37 -0
- package/dist/shared/kprcwaha.js +30 -0
- package/dist/shared/m3ypagh5.js +347 -0
- package/dist/shared/mkjmqjv4.js +456 -0
- package/dist/shared/mtkwv8wx.js +18 -0
- package/dist/shared/ngk8gj61.js +40 -0
- package/dist/shared/p0cbr3g2.js +79 -0
- package/dist/shared/qk3hxfja.js +83 -0
- package/dist/shared/rgs0st28.js +1066 -0
- package/dist/shared/w8samvk1.js +18 -0
- package/dist/shared/x5x59srr.js +566 -0
- package/dist/shared/xqbhg6cn.js +119 -0
- package/dist/shared/xy79j5hq.js +177 -0
- package/dist/shared/y9m15dfv.js +888 -0
- package/dist/shared/ycwz42az.js +412 -0
- package/dist/shared/yd1kzwn2.js +148 -0
- package/dist/shared/zhc5vmgf.js +257 -0
- package/dist/tooling/cli.d.ts +1 -0
- package/dist/tooling/cli.js +193 -0
- package/dist/tooling/errors/registry.d.ts +33 -0
- package/dist/tooling/migrate/apply.d.ts +86 -0
- package/dist/tooling/migrate/commands.d.ts +21 -0
- package/dist/tooling/migrate/config.d.ts +48 -0
- package/dist/tooling/migrate/dev.d.ts +16 -0
- package/dist/tooling/migrate/equal.d.ts +15 -0
- package/dist/tooling/migrate/files.d.ts +19 -0
- package/dist/tooling/migrate/index.d.ts +7 -0
- package/dist/tooling/migrate/index.js +7 -0
- package/dist/tooling/migrate/plan.d.ts +76 -0
- package/dist/tooling/migrate/policy.d.ts +78 -0
- package/dist/tooling/migrate/project.d.ts +69 -0
- package/dist/tooling/migrate/status.d.ts +74 -0
- package/dist/tooling/migrate/values.d.ts +29 -0
- package/package.json +109 -7
- package/dist/index.js +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
open2
|
|
3
|
+
} from "./dkn3y60a.js";
|
|
4
|
+
import"./y9m15dfv.js";
|
|
5
|
+
import {
|
|
6
|
+
loadMigrations
|
|
7
|
+
} from "./jjb7yht9.js";
|
|
8
|
+
import {
|
|
9
|
+
assertTargetPolicy,
|
|
10
|
+
listTargets,
|
|
11
|
+
loadConfig
|
|
12
|
+
} from "./05w44d8g.js";
|
|
13
|
+
import {
|
|
14
|
+
OkmError2
|
|
15
|
+
} from "./ycwz42az.js";
|
|
16
|
+
|
|
17
|
+
// src/tooling/migrate/status.ts
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
function describeStatus(migrations, history, recorded) {
|
|
20
|
+
const done = new Set(history.map((row) => `${row.migrationId}:${String(row.stepIndex)}`));
|
|
21
|
+
const known = new Set(migrations.map((migration) => migration.id));
|
|
22
|
+
for (const migration of migrations) {
|
|
23
|
+
let have = 0;
|
|
24
|
+
let missing = -1;
|
|
25
|
+
for (let index = 0;index < migration.steps.length; index += 1) {
|
|
26
|
+
if (done.has(`${migration.id}:${String(index)}`))
|
|
27
|
+
have += 1;
|
|
28
|
+
else if (missing < 0)
|
|
29
|
+
missing = index;
|
|
30
|
+
}
|
|
31
|
+
if (have > 0 && missing >= 0) {
|
|
32
|
+
return {
|
|
33
|
+
version: migration.id,
|
|
34
|
+
catalogHash: recorded?.hash ?? "-",
|
|
35
|
+
state: `failed at step ${String(missing)}`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const extra = history.some((row) => !known.has(row.migrationId));
|
|
40
|
+
const pending = migrations.filter((migration) => migration.steps.some((_, index) => !done.has(`${migration.id}:${String(index)}`)));
|
|
41
|
+
const finished = lastComplete(migrations, done);
|
|
42
|
+
const version = recorded?.version ?? finished ?? "-";
|
|
43
|
+
const catalogHash = recorded?.hash ?? "-";
|
|
44
|
+
if (extra)
|
|
45
|
+
return { version, catalogHash, state: "ahead" };
|
|
46
|
+
if (pending.length > 0) {
|
|
47
|
+
const contract = pending.some((migration) => migration.steps.some((step) => step.class !== "expand"));
|
|
48
|
+
return {
|
|
49
|
+
version,
|
|
50
|
+
catalogHash,
|
|
51
|
+
state: contract ? "behind by contract" : "behind by expand"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const last = migrations.at(-1);
|
|
55
|
+
if (last !== undefined && recorded !== undefined && recorded.hash !== last.catalogHash) {
|
|
56
|
+
return { version, catalogHash, state: "ahead" };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
version: recorded?.version ?? last?.id ?? "-",
|
|
60
|
+
catalogHash: recorded?.hash ?? last?.catalogHash ?? "-",
|
|
61
|
+
state: "current"
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function readTargetStatus(input) {
|
|
65
|
+
assertTargetPolicy({ name: input.target, protected: input.protected }, "status");
|
|
66
|
+
const pool = open2({
|
|
67
|
+
url: input.url,
|
|
68
|
+
max: 1,
|
|
69
|
+
...input.searchPath !== undefined ? { searchPath: input.searchPath } : {}
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
const present = await pool.execute("select (to_regclass('okm_meta') is not null), (to_regclass('okm_history') is not null)");
|
|
73
|
+
const meta = wireTrue(present.rows[0]?.[0] ?? null);
|
|
74
|
+
const history = wireTrue(present.rows[0]?.[1] ?? null);
|
|
75
|
+
const recorded = meta ? await readMeta(pool) : undefined;
|
|
76
|
+
const rows = history ? await readHistory(pool) : [];
|
|
77
|
+
const described = describeStatus(input.migrations, rows, recorded);
|
|
78
|
+
return {
|
|
79
|
+
target: input.target,
|
|
80
|
+
version: described.version,
|
|
81
|
+
catalogHash: described.catalogHash,
|
|
82
|
+
state: described.state,
|
|
83
|
+
protected: input.protected
|
|
84
|
+
};
|
|
85
|
+
} finally {
|
|
86
|
+
await pool.close();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function statusProject(cwd, flags) {
|
|
90
|
+
const config = await loadConfig(cwd);
|
|
91
|
+
const targets = chosen(listTargets(config), flags.target);
|
|
92
|
+
const migrations = loadMigrations(join(cwd, config.migrations ?? "migrations"));
|
|
93
|
+
const rows = [];
|
|
94
|
+
for (const target of targets) {
|
|
95
|
+
rows.push(await readTargetStatus({
|
|
96
|
+
url: target.url,
|
|
97
|
+
target: target.name,
|
|
98
|
+
protected: target.protected,
|
|
99
|
+
migrations
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
return formatStatus(rows);
|
|
103
|
+
}
|
|
104
|
+
function formatStatus(rows) {
|
|
105
|
+
const lines = ["target\tversion\tcatalog\tstate\tprotected"];
|
|
106
|
+
for (const row of rows) {
|
|
107
|
+
lines.push([row.target, row.version, row.catalogHash, row.state, row.protected ? "true" : "false"].join("\t"));
|
|
108
|
+
}
|
|
109
|
+
return `${lines.join(`
|
|
110
|
+
`)}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
function chosen(targets, name) {
|
|
114
|
+
if (targets.length === 0) {
|
|
115
|
+
throw new OkmError2("OKM1845", "No target is configured.", {
|
|
116
|
+
fix: { summary: "Set database or targets in okmodel.config.ts." }
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (name === undefined)
|
|
120
|
+
return targets;
|
|
121
|
+
const found = targets.find((target) => target.name === name);
|
|
122
|
+
if (found === undefined) {
|
|
123
|
+
throw new OkmError2("OKM1845", `Target ${name} is not configured.`, {
|
|
124
|
+
fix: { summary: "Pass a name from targets." }
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return [found];
|
|
128
|
+
}
|
|
129
|
+
function lastComplete(migrations, done) {
|
|
130
|
+
let version;
|
|
131
|
+
for (const migration of migrations) {
|
|
132
|
+
if (migration.steps.length === 0)
|
|
133
|
+
continue;
|
|
134
|
+
const complete = migration.steps.every((_, index) => done.has(`${migration.id}:${String(index)}`));
|
|
135
|
+
if (!complete)
|
|
136
|
+
break;
|
|
137
|
+
version = migration.id;
|
|
138
|
+
}
|
|
139
|
+
return version;
|
|
140
|
+
}
|
|
141
|
+
async function readMeta(pool) {
|
|
142
|
+
const result = await pool.execute("select catalog_hash, migration_id from okm_meta where id = 'head'");
|
|
143
|
+
const hash = result.rows[0]?.[0];
|
|
144
|
+
const version = result.rows[0]?.[1];
|
|
145
|
+
if (hash === null || hash === undefined || version === null || version === undefined)
|
|
146
|
+
return;
|
|
147
|
+
return { hash, version };
|
|
148
|
+
}
|
|
149
|
+
async function readHistory(pool) {
|
|
150
|
+
const result = await pool.execute("select migration_id, step_index::text, class from okm_history order by migration_id, step_index");
|
|
151
|
+
const rows = [];
|
|
152
|
+
for (const row of result.rows) {
|
|
153
|
+
const migrationId = row[0];
|
|
154
|
+
const step = row[1];
|
|
155
|
+
const stepClass = row[2];
|
|
156
|
+
if (migrationId == null || step == null || stepClass == null)
|
|
157
|
+
continue;
|
|
158
|
+
rows.push({
|
|
159
|
+
migrationId,
|
|
160
|
+
stepIndex: Number(step),
|
|
161
|
+
class: stepClass === "contract" || stepClass === "unclassified" ? stepClass : "expand"
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return rows;
|
|
165
|
+
}
|
|
166
|
+
function wireTrue(value) {
|
|
167
|
+
return value === "t" || value === "true";
|
|
168
|
+
}
|
|
169
|
+
export {
|
|
170
|
+
statusProject
|
|
171
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
open3
|
|
3
|
+
} from "./fgqgsb5z.js";
|
|
4
|
+
import {
|
|
5
|
+
PGLITE_CAPABILITIES,
|
|
6
|
+
readCapability2,
|
|
7
|
+
hasCapability2
|
|
8
|
+
} from "./xy79j5hq.js";
|
|
9
|
+
export {
|
|
10
|
+
PGLITE_CAPABILITIES as capabilities,
|
|
11
|
+
hasCapability2 as hasCapability,
|
|
12
|
+
open3 as open,
|
|
13
|
+
readCapability2 as readCapability
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/dialects/pg/operators.ts
|
|
2
|
+
var RUNTIME = Symbol("okmodel.operator");
|
|
3
|
+
function isOperator(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && RUNTIME in value;
|
|
5
|
+
}
|
|
6
|
+
function operatorName(value) {
|
|
7
|
+
return value[RUNTIME];
|
|
8
|
+
}
|
|
9
|
+
function operatorValue(value) {
|
|
10
|
+
return value.value;
|
|
11
|
+
}
|
|
12
|
+
function tag(name, value) {
|
|
13
|
+
return { [RUNTIME]: name, value };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { isOperator, operatorName, operatorValue, tag };
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import {
|
|
2
|
+
POSTGRESJS_CAPABILITIES,
|
|
3
|
+
driverErrors,
|
|
4
|
+
rejectClosed,
|
|
5
|
+
mapFailure,
|
|
6
|
+
nextTransactionDepth,
|
|
7
|
+
runCall,
|
|
8
|
+
EMPTY_NOTICES,
|
|
9
|
+
resultFrom
|
|
10
|
+
} from "./xy79j5hq.js";
|
|
11
|
+
|
|
12
|
+
// src/adapters/pg/postgresjs.ts
|
|
13
|
+
import net from "node:net";
|
|
14
|
+
import postgres from "postgres";
|
|
15
|
+
class PoolSockets {
|
|
16
|
+
held = [];
|
|
17
|
+
busy = 0;
|
|
18
|
+
listeners = 0;
|
|
19
|
+
hostCursor = 0;
|
|
20
|
+
connect(target) {
|
|
21
|
+
const path = typeof target.path === "string" ? target.path : undefined;
|
|
22
|
+
const hosts = target.host;
|
|
23
|
+
const ports = target.port;
|
|
24
|
+
const index = hosts.length === 0 ? 0 : this.hostCursor % hosts.length;
|
|
25
|
+
this.hostCursor += 1;
|
|
26
|
+
const host = hosts[index] ?? "localhost";
|
|
27
|
+
const port = ports[index] ?? ports[0] ?? 5432;
|
|
28
|
+
const socket = path !== undefined ? net.connect(path) : net.connect(port, host);
|
|
29
|
+
this.held.push(socket);
|
|
30
|
+
return socket;
|
|
31
|
+
}
|
|
32
|
+
occupy(run) {
|
|
33
|
+
this.busy += 1;
|
|
34
|
+
this.wake();
|
|
35
|
+
return run().finally(() => {
|
|
36
|
+
this.busy -= 1;
|
|
37
|
+
this.park();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async hold(checkout) {
|
|
41
|
+
this.busy += 1;
|
|
42
|
+
this.wake();
|
|
43
|
+
try {
|
|
44
|
+
const connection = await checkout();
|
|
45
|
+
let released = false;
|
|
46
|
+
const release = connection.release.bind(connection);
|
|
47
|
+
connection.release = () => {
|
|
48
|
+
if (released)
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
released = true;
|
|
51
|
+
return release().finally(() => {
|
|
52
|
+
this.busy -= 1;
|
|
53
|
+
this.park();
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
return connection;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
this.busy -= 1;
|
|
59
|
+
this.park();
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async* stream(open) {
|
|
64
|
+
this.busy += 1;
|
|
65
|
+
this.wake();
|
|
66
|
+
try {
|
|
67
|
+
yield* open();
|
|
68
|
+
} finally {
|
|
69
|
+
this.busy -= 1;
|
|
70
|
+
this.park();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async listen(start) {
|
|
74
|
+
this.listeners += 1;
|
|
75
|
+
this.wake();
|
|
76
|
+
try {
|
|
77
|
+
const stop = await start();
|
|
78
|
+
let stopped = false;
|
|
79
|
+
return async () => {
|
|
80
|
+
if (stopped)
|
|
81
|
+
return;
|
|
82
|
+
stopped = true;
|
|
83
|
+
try {
|
|
84
|
+
await stop();
|
|
85
|
+
} finally {
|
|
86
|
+
this.listeners -= 1;
|
|
87
|
+
this.park();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
this.listeners -= 1;
|
|
92
|
+
this.park();
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
wake() {
|
|
97
|
+
for (const socket of this.held)
|
|
98
|
+
socket.ref();
|
|
99
|
+
}
|
|
100
|
+
park() {
|
|
101
|
+
if (this.busy > 0 || this.listeners > 0)
|
|
102
|
+
return;
|
|
103
|
+
for (const socket of this.held)
|
|
104
|
+
socket.unref();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function driverOptions(config, state) {
|
|
108
|
+
return {
|
|
109
|
+
max: state.max,
|
|
110
|
+
prepare: state.named,
|
|
111
|
+
idle_timeout: state.plain ? 0 : 30,
|
|
112
|
+
...state.plain ? { max_lifetime: null } : {},
|
|
113
|
+
connect_timeout: 5,
|
|
114
|
+
types: WIRE_TYPES,
|
|
115
|
+
...state.plain ? { socket: (options) => state.sockets.connect(options) } : {},
|
|
116
|
+
...config.ssl !== undefined ? { ssl: config.ssl } : {},
|
|
117
|
+
connection: {
|
|
118
|
+
application_name: "okmodel",
|
|
119
|
+
...config.searchPath !== undefined ? { search_path: config.searchPath } : {}
|
|
120
|
+
},
|
|
121
|
+
onnotice(notice) {
|
|
122
|
+
state.notices.push(notice);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function open2(config) {
|
|
127
|
+
const max = config.max ?? 10;
|
|
128
|
+
const acquireMs = config.timeouts?.acquire;
|
|
129
|
+
const counters = { reserved: 0, busy: 0, reservedBusy: 0, waiting: 0 };
|
|
130
|
+
const poolInflight = new Set;
|
|
131
|
+
const notices = noticeBuffer();
|
|
132
|
+
let closed = false;
|
|
133
|
+
const isClosed = () => closed;
|
|
134
|
+
const named = config.prepared === "named";
|
|
135
|
+
const plain = config.ssl === undefined;
|
|
136
|
+
const sockets = new PoolSockets;
|
|
137
|
+
const sql = postgres(config.url, driverOptions(config, {
|
|
138
|
+
max,
|
|
139
|
+
named,
|
|
140
|
+
plain,
|
|
141
|
+
notices,
|
|
142
|
+
sockets
|
|
143
|
+
}));
|
|
144
|
+
const root = new PgSession(sql, counters, "pool", poolInflight, isClosed, undefined, notices, named);
|
|
145
|
+
const held = { sql, acquireMs, counters, isClosed, notices, named, poolInflight };
|
|
146
|
+
return {
|
|
147
|
+
capabilities: POSTGRESJS_CAPABILITIES,
|
|
148
|
+
execute(text, params, options) {
|
|
149
|
+
return sockets.occupy(() => runCall(closed, options, (watch) => root.query(text, params, watch)));
|
|
150
|
+
},
|
|
151
|
+
async batch(statements, options) {
|
|
152
|
+
return sockets.occupy(async () => {
|
|
153
|
+
const { checkout } = await import("./xqbhg6cn.js");
|
|
154
|
+
const connection = await checkout(held);
|
|
155
|
+
try {
|
|
156
|
+
return await connection.batch(statements, options);
|
|
157
|
+
} finally {
|
|
158
|
+
await connection.release();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
reserve() {
|
|
163
|
+
return sockets.hold(async () => {
|
|
164
|
+
const mod = await import("./xqbhg6cn.js");
|
|
165
|
+
return mod.checkout(held);
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
describe: (text, params) => sockets.occupy(() => import("./xqbhg6cn.js").then((mod) => mod.describe(sql, text, params))),
|
|
169
|
+
stream(text, params) {
|
|
170
|
+
return sockets.stream(() => loadStream(sql, text, params));
|
|
171
|
+
},
|
|
172
|
+
listen(channel, onNotify) {
|
|
173
|
+
return sockets.listen(async () => {
|
|
174
|
+
const listening = await sql.listen(channel, onNotify);
|
|
175
|
+
return async () => {
|
|
176
|
+
await listening.unlisten();
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
cancel() {
|
|
181
|
+
for (const pending of poolInflight)
|
|
182
|
+
pending.cancel();
|
|
183
|
+
},
|
|
184
|
+
stats: () => statsOf(counters, max),
|
|
185
|
+
async close() {
|
|
186
|
+
closed = true;
|
|
187
|
+
await sql.end({ timeout: 5 });
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
class PgSession {
|
|
193
|
+
canCancel = true;
|
|
194
|
+
transactionDepth = 0;
|
|
195
|
+
sql;
|
|
196
|
+
counters;
|
|
197
|
+
scope;
|
|
198
|
+
local;
|
|
199
|
+
isClosed;
|
|
200
|
+
shared;
|
|
201
|
+
notices;
|
|
202
|
+
named;
|
|
203
|
+
constructor(sql, counters, scope, local, isClosed, shared, notices, named) {
|
|
204
|
+
this.sql = sql;
|
|
205
|
+
this.counters = counters;
|
|
206
|
+
this.scope = scope;
|
|
207
|
+
this.local = local;
|
|
208
|
+
this.isClosed = isClosed;
|
|
209
|
+
this.shared = shared;
|
|
210
|
+
this.notices = notices;
|
|
211
|
+
this.named = named;
|
|
212
|
+
}
|
|
213
|
+
query(text, params, watch) {
|
|
214
|
+
if (this.isClosed())
|
|
215
|
+
return rejectClosed();
|
|
216
|
+
const start = this.notices.start();
|
|
217
|
+
this.enter();
|
|
218
|
+
const pending = send(this.sql, text, params, this.named);
|
|
219
|
+
if (watch === undefined) {
|
|
220
|
+
return pending.then((result) => {
|
|
221
|
+
this.leave();
|
|
222
|
+
this.note(text);
|
|
223
|
+
return resultFrom(result, this.notices.since(start));
|
|
224
|
+
}, (error) => {
|
|
225
|
+
this.leave();
|
|
226
|
+
return mapFailure(error).then((mapped) => {
|
|
227
|
+
throw mapped;
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return this.watched(pending, watch, start, text);
|
|
232
|
+
}
|
|
233
|
+
inTransaction() {
|
|
234
|
+
return this.transactionDepth > 0;
|
|
235
|
+
}
|
|
236
|
+
abandon() {
|
|
237
|
+
this.transactionDepth = 0;
|
|
238
|
+
}
|
|
239
|
+
depth() {
|
|
240
|
+
return this.transactionDepth;
|
|
241
|
+
}
|
|
242
|
+
cancel() {
|
|
243
|
+
for (const pending of this.local)
|
|
244
|
+
pending.cancel();
|
|
245
|
+
}
|
|
246
|
+
note(text) {
|
|
247
|
+
this.transactionDepth = nextTransactionDepth(this.transactionDepth, text);
|
|
248
|
+
}
|
|
249
|
+
enter() {
|
|
250
|
+
if (this.scope === "pool")
|
|
251
|
+
this.counters.busy += 1;
|
|
252
|
+
else
|
|
253
|
+
this.counters.reservedBusy += 1;
|
|
254
|
+
}
|
|
255
|
+
leave() {
|
|
256
|
+
if (this.scope === "pool")
|
|
257
|
+
this.counters.busy = Math.max(0, this.counters.busy - 1);
|
|
258
|
+
else
|
|
259
|
+
this.counters.reservedBusy = Math.max(0, this.counters.reservedBusy - 1);
|
|
260
|
+
}
|
|
261
|
+
track(pending) {
|
|
262
|
+
this.local.add(pending);
|
|
263
|
+
this.shared?.add(pending);
|
|
264
|
+
}
|
|
265
|
+
untrack(pending) {
|
|
266
|
+
this.local.delete(pending);
|
|
267
|
+
this.shared?.delete(pending);
|
|
268
|
+
}
|
|
269
|
+
watched(pending, watch, start, text) {
|
|
270
|
+
this.track(pending);
|
|
271
|
+
const onAbort = () => {
|
|
272
|
+
pending.cancel();
|
|
273
|
+
};
|
|
274
|
+
if (watch.signal.aborted)
|
|
275
|
+
onAbort();
|
|
276
|
+
else
|
|
277
|
+
watch.signal.addEventListener("abort", onAbort, { once: true });
|
|
278
|
+
return pending.then((result) => {
|
|
279
|
+
this.finishWatched(pending, watch, onAbort);
|
|
280
|
+
const why = watch.reason();
|
|
281
|
+
if (why === "timeout" || why === "cancelled")
|
|
282
|
+
return classify(why, watch);
|
|
283
|
+
this.note(text);
|
|
284
|
+
return resultFrom(result, this.notices.since(start));
|
|
285
|
+
}, (error) => {
|
|
286
|
+
this.finishWatched(pending, watch, onAbort);
|
|
287
|
+
return classify(error, watch);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
finishWatched(pending, watch, onAbort) {
|
|
291
|
+
this.leave();
|
|
292
|
+
this.untrack(pending);
|
|
293
|
+
watch.signal.removeEventListener("abort", onAbort);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async function* loadStream(sql, text, params) {
|
|
297
|
+
const { stream } = await import("./xqbhg6cn.js");
|
|
298
|
+
yield* stream(sql, text, params);
|
|
299
|
+
}
|
|
300
|
+
function send(sql, text, params, named) {
|
|
301
|
+
if (!named && (params === undefined || params.length === 0))
|
|
302
|
+
return sql.unsafe(text).raw();
|
|
303
|
+
return sql.unsafe(text, asParams(params), { prepare: named }).raw();
|
|
304
|
+
}
|
|
305
|
+
function asParams(params) {
|
|
306
|
+
if (params === undefined)
|
|
307
|
+
return [];
|
|
308
|
+
return params;
|
|
309
|
+
}
|
|
310
|
+
async function classify(error, watch) {
|
|
311
|
+
const errors = await driverErrors();
|
|
312
|
+
if (error instanceof errors.DriverError)
|
|
313
|
+
return Promise.reject(error);
|
|
314
|
+
const why = typeof error === "string" ? error : watch.reason();
|
|
315
|
+
if (why === "timeout")
|
|
316
|
+
return Promise.reject(errors.timedOut(typeof error === "string" ? undefined : error));
|
|
317
|
+
const code = errors.errorField(error, "code");
|
|
318
|
+
if (why === "cancelled" || code === "57014") {
|
|
319
|
+
return Promise.reject(errors.cancelled(typeof error === "string" ? undefined : error));
|
|
320
|
+
}
|
|
321
|
+
return Promise.reject(errors.mapDriverError(error));
|
|
322
|
+
}
|
|
323
|
+
function statsOf(counters, size) {
|
|
324
|
+
return {
|
|
325
|
+
size,
|
|
326
|
+
idle: Math.max(0, size - counters.reserved - counters.busy),
|
|
327
|
+
inflight: counters.busy + counters.reservedBusy,
|
|
328
|
+
waiting: counters.waiting
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function noticeBuffer() {
|
|
332
|
+
let notices;
|
|
333
|
+
return {
|
|
334
|
+
push(notice) {
|
|
335
|
+
const severity = typeof notice.severity === "string" ? notice.severity : "";
|
|
336
|
+
const message = typeof notice.message === "string" ? notice.message : "";
|
|
337
|
+
const code = typeof notice.code === "string" && notice.code.length > 0 ? notice.code : undefined;
|
|
338
|
+
const entry = code === undefined ? { severity, message } : { severity, message, code };
|
|
339
|
+
(notices ??= []).push(entry);
|
|
340
|
+
},
|
|
341
|
+
start() {
|
|
342
|
+
return notices?.length ?? 0;
|
|
343
|
+
},
|
|
344
|
+
since(start) {
|
|
345
|
+
if (notices === undefined || notices.length === start)
|
|
346
|
+
return EMPTY_NOTICES;
|
|
347
|
+
return notices.slice(start);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function wire(to, from) {
|
|
352
|
+
return {
|
|
353
|
+
to,
|
|
354
|
+
from: [...from],
|
|
355
|
+
serialize: (value) => value,
|
|
356
|
+
parse: (value) => value
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
var WIRE_TYPES = {
|
|
360
|
+
number: wire(0, [21, 23, 26, 700, 701]),
|
|
361
|
+
boolean: wire(16, [16]),
|
|
362
|
+
bytea: wire(17, [17]),
|
|
363
|
+
json: wire(114, [114, 3802]),
|
|
364
|
+
date: wire(1184, [1082, 1114, 1184]),
|
|
365
|
+
boolArray: wire(1000, [1000]),
|
|
366
|
+
int2Array: wire(1005, [1005]),
|
|
367
|
+
int4Array: wire(1007, [1007]),
|
|
368
|
+
textArray: wire(1009, [1009]),
|
|
369
|
+
int8Array: wire(1016, [1016]),
|
|
370
|
+
numericArray: wire(1231, [1231]),
|
|
371
|
+
jsonbArray: wire(3807, [3807])
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export { open2, PgSession };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DriverError2,
|
|
3
|
+
outcomeUnknown2,
|
|
4
|
+
mapDriverError2
|
|
5
|
+
} from "./hd293j9g.js";
|
|
6
|
+
import {
|
|
7
|
+
isConnectionFailure
|
|
8
|
+
} from "./ngk8gj61.js";
|
|
9
|
+
|
|
10
|
+
// src/adapters/pg/batch.ts
|
|
11
|
+
var savepointIds = 0;
|
|
12
|
+
async function runAtomicBatch(session, statements, watch) {
|
|
13
|
+
if (session.inTransaction())
|
|
14
|
+
return savepoint(session, statements, watch);
|
|
15
|
+
return transaction(session, statements, watch);
|
|
16
|
+
}
|
|
17
|
+
async function transaction(session, statements, watch) {
|
|
18
|
+
try {
|
|
19
|
+
await control(session, "BEGIN", watch);
|
|
20
|
+
const results = await statementsOf(session, statements, watch);
|
|
21
|
+
try {
|
|
22
|
+
await control(session, "COMMIT", watch);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
if (isConnectionFailure(error))
|
|
25
|
+
throw outcomeUnknown2(error);
|
|
26
|
+
throw stamp(error, null);
|
|
27
|
+
}
|
|
28
|
+
return results;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
await rollback(session);
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function savepoint(session, statements, watch) {
|
|
35
|
+
savepointIds += 1;
|
|
36
|
+
const name = `okm_b${String(savepointIds)}`;
|
|
37
|
+
try {
|
|
38
|
+
await control(session, `SAVEPOINT ${name}`, watch);
|
|
39
|
+
const results = await statementsOf(session, statements, watch);
|
|
40
|
+
await control(session, `RELEASE SAVEPOINT ${name}`, watch);
|
|
41
|
+
return results;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
await rollback(session, `ROLLBACK TO SAVEPOINT ${name}`);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function control(session, text, watch) {
|
|
48
|
+
return session.query(text, undefined, watch).then(() => {
|
|
49
|
+
return;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async function rollback(session, text = "ROLLBACK") {
|
|
53
|
+
try {
|
|
54
|
+
await session.query(text, undefined, undefined);
|
|
55
|
+
} catch {
|
|
56
|
+
session.abandon();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function statementsOf(session, statements, watch) {
|
|
60
|
+
const results = Array.from({ length: statements.length });
|
|
61
|
+
for (let index = 0;index < statements.length; index += 1) {
|
|
62
|
+
const statement = statements[index];
|
|
63
|
+
if (statement === undefined)
|
|
64
|
+
continue;
|
|
65
|
+
try {
|
|
66
|
+
results[index] = await session.query(statement.text, statement.params, watch);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw stamp(error, index);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
function stamp(error, batchIndex) {
|
|
74
|
+
const mapped = mapDriverError2(error, batchIndex);
|
|
75
|
+
if (mapped instanceof DriverError2)
|
|
76
|
+
return mapped;
|
|
77
|
+
return error;
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
runAtomicBatch
|
|
81
|
+
};
|