okmodel 0.5.0 → 0.6.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 +36 -18
- package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
- package/dist/adapters/pg/postgres-extra.d.ts +22 -0
- package/dist/contracts/catalog/document.d.ts +19 -5
- package/dist/contracts/catalog/object.d.ts +2 -1
- package/dist/contracts/catalog/policy.d.ts +48 -0
- package/dist/contracts/catalog/types.d.ts +25 -1
- package/dist/contracts/catalog/view.d.ts +2 -0
- package/dist/contracts/internal.js +1 -1
- package/dist/contracts/location.d.ts +10 -0
- package/dist/dialects/pg/column.d.ts +13 -2
- package/dist/dialects/pg/ddl.d.ts +37 -1
- package/dist/dialects/pg/emit.d.ts +19 -1
- package/dist/dialects/pg/errors.d.ts +32 -1
- 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/filter-parse.d.ts +10 -3
- package/dist/dialects/pg/fn/index.js +10 -2
- package/dist/dialects/pg/index.d.ts +2 -1
- package/dist/dialects/pg/index.js +29 -17
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/model.d.ts +7 -2
- package/dist/dialects/pg/ops/or.d.ts +1 -1
- package/dist/dialects/pg/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/role/check.d.ts +3 -0
- package/dist/dialects/pg/role/index.d.ts +71 -6
- package/dist/dialects/pg/role/sql.d.ts +11 -0
- package/dist/dialects/pg/schema.d.ts +2 -0
- package/dist/dialects/pg/table.d.ts +25 -3
- package/dist/dialects/pg/temporal.d.ts +5 -76
- package/dist/dialects/pg/tenancy.d.ts +45 -3
- package/dist/dialects/pg/view/client.d.ts +19 -1
- package/dist/dialects/pg/view/index.d.ts +4 -0
- package/dist/dialects/pg/view/index.js +21 -178
- package/dist/dialects/pg/view/refresh.d.ts +24 -0
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/client.d.ts +6 -1
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/pg/bun.js +6 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.js +6 -5
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +22 -1
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/safety/index.js +1 -1
- package/dist/runtime/tenancy/composite.d.ts +26 -0
- package/dist/runtime/tenancy/context.d.ts +16 -0
- package/dist/runtime/tenancy/index.d.ts +9 -5
- package/dist/runtime/tenancy/index.js +1508 -37
- package/dist/runtime/tenancy/path.d.ts +87 -0
- package/dist/runtime/tenancy/rls.d.ts +67 -0
- package/dist/runtime/tenancy/via.d.ts +22 -0
- package/dist/runtime/traits/index.js +17 -11
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/write.d.ts +1 -1
- package/dist/shared/09p049xa.js +702 -0
- package/dist/shared/{ykv7wh5b.js → 1f0xa3cb.js} +5 -5
- package/dist/shared/1nw1f3vs.js +23 -0
- package/dist/shared/{6p5k20sm.js → 1z04fa85.js} +21 -11
- package/dist/shared/{p7pfx624.js → 2cg3wnxc.js} +314 -65
- package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
- package/dist/shared/{qgvt8nx1.js → 2z7wv5tj.js} +21 -5
- package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
- package/dist/shared/{sf8m6tfy.js → 32cnm7kn.js} +8 -3
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/{jdgqqx31.js → 3fqwmr09.js} +38 -14
- package/dist/shared/{922qbgnw.js → 3qnhc7w5.js} +16 -9
- package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
- package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
- package/dist/shared/{k7cc9nzk.js → 5d8t84hg.js} +15 -3
- package/dist/shared/{fa9vt245.js → 5j36z8dn.js} +17 -6
- package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
- package/dist/shared/8dqhth8c.js +12 -0
- package/dist/shared/8etn7d8w.js +62 -0
- package/dist/shared/{g516zdsb.js → 8x72s86k.js} +476 -30
- package/dist/shared/{nkc9sfqb.js → 929h19xp.js} +145 -7
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/{b066g80h.js → ag4c7516.js} +2 -2
- package/dist/shared/b3awxn7h.js +45 -0
- package/dist/shared/b4v57v3x.js +9 -0
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{s6gqfn5j.js → c58secgj.js} +125 -8
- package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
- package/dist/shared/d5azex6s.js +6 -0
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/{wxn4b7pp.js → f0f1n281.js} +59 -12
- package/dist/shared/{gdh9mrtp.js → g90m9b0g.js} +3 -2
- package/dist/shared/{tbszx8mz.js → gwn6v667.js} +2 -2
- package/dist/shared/{c8aghh05.js → h15jx9bc.js} +8 -2
- package/dist/shared/{3p4b1fg0.js → hazqqecq.js} +17 -93
- package/dist/shared/{4ef7mmqf.js → j3rkk835.js} +34 -11
- package/dist/shared/{bt9sfq0z.js → j60w0dvr.js} +56 -21
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/k68eedmy.js +85 -0
- package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
- package/dist/shared/{ckjbyrt9.js → mb2ycs1p.js} +7 -9
- package/dist/shared/{tq9afp8d.js → n076ydsc.js} +1 -1
- package/dist/shared/{xhh1srw3.js → nx9hh281.js} +50 -32
- package/dist/shared/{kdkxh3kb.js → p248q79y.js} +58 -59
- package/dist/shared/{990a291j.js → p6bjzq9q.js} +14 -9
- package/dist/shared/{h4nqvjkp.js → pjr6xrm5.js} +2 -2
- package/dist/shared/pz6rj8ay.js +212 -0
- package/dist/shared/{5vdm4sgp.js → q3j1tq7a.js} +36 -23
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{dxjp14rk.js → r11n8grd.js} +2 -2
- package/dist/shared/r1fdd0f6.js +19 -0
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{jsd07prz.js → rpycarcr.js} +6 -6
- package/dist/shared/{xsq7v6wp.js → sbdme3vy.js} +14 -2
- package/dist/shared/{xdpj5kkm.js → t3g0k88x.js} +775 -264
- package/dist/shared/{ayz64vzj.js → ttmg09vd.js} +708 -19
- package/dist/shared/{r6pj4fq2.js → venqrjna.js} +8 -4
- package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
- package/dist/shared/{9tgmr1gh.js → vmfkhszw.js} +44 -9
- package/dist/shared/{wqem4jed.js → wkme6tep.js} +11 -9
- package/dist/shared/{qy9rdq0g.js → wt5rzv1h.js} +15 -11
- package/dist/shared/wxr8cwns.js +6 -0
- package/dist/shared/{bzsjtd7c.js → wynzeggs.js} +19 -14
- package/dist/shared/x3jc53kg.js +220 -0
- package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
- package/dist/shared/{fyqkk1m0.js → xq0mvhts.js} +10 -9
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{47xzb9fc.js → y2t3jktd.js} +2 -2
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/{h8ne16fq.js → ys0xzyaj.js} +1 -1
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/{fb00y8fp.js → zm0mafk4.js} +12 -6
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +97 -24
- package/dist/tooling/migrate/apply.d.ts +14 -0
- package/dist/tooling/migrate/check.d.ts +3 -4
- package/dist/tooling/migrate/classify.d.ts +4 -0
- package/dist/tooling/migrate/commands.d.ts +1 -2
- package/dist/tooling/migrate/config.d.ts +3 -2
- package/dist/tooling/migrate/drift.d.ts +1 -1
- package/dist/tooling/migrate/estimate.d.ts +14 -1
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +17 -16
- package/dist/tooling/migrate/lint.d.ts +4 -4
- package/dist/tooling/migrate/lost.d.ts +28 -0
- package/dist/tooling/migrate/paths.d.ts +14 -0
- package/dist/tooling/migrate/plan.d.ts +10 -3
- package/dist/tooling/migrate/policy.d.ts +11 -0
- package/dist/tooling/migrate/runner.d.ts +25 -0
- package/dist/tooling/migrate/sandbox.d.ts +57 -0
- package/dist/tooling/migrate/sql-lex.d.ts +39 -0
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -0
- package/dist/tooling/testing/factories.d.ts +10 -0
- package/dist/tooling/testing/facts.d.ts +33 -5
- package/dist/tooling/testing/index.d.ts +1 -1
- package/dist/tooling/testing/index.js +3 -3
- package/dist/tooling/testing/isolation.d.ts +15 -8
- package/package.json +10 -6
- package/dist/shared/0v1g424p.js +0 -26
- package/dist/shared/r73pt594.js +0 -426
- package/dist/shared/rasvvzgz.js +0 -21
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
serializeCatalog2
|
|
3
|
-
|
|
4
|
-
startupCatalog2,
|
|
5
|
-
parseCatalog2
|
|
6
|
-
} from "./8bwbwy8h.js";
|
|
2
|
+
serializeCatalog2
|
|
3
|
+
} from "./qq3899ht.js";
|
|
7
4
|
import {
|
|
8
5
|
roleExists
|
|
9
|
-
} from "./
|
|
10
|
-
import {
|
|
11
|
-
assertTargetPolicy
|
|
12
|
-
} from "./xdpj5kkm.js";
|
|
6
|
+
} from "./knmes2kh.js";
|
|
13
7
|
import {
|
|
14
8
|
canonicalTypeName,
|
|
15
9
|
createdRoleName,
|
|
@@ -20,29 +14,30 @@ import {
|
|
|
20
14
|
checkedCast,
|
|
21
15
|
omitManagedObjects,
|
|
22
16
|
planMigration,
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
sessionFailure,
|
|
18
|
+
assertTargetPolicy
|
|
19
|
+
} from "./ttmg09vd.js";
|
|
25
20
|
import {
|
|
26
21
|
quoteIdent,
|
|
27
22
|
qualify
|
|
28
|
-
} from "./
|
|
23
|
+
} from "./9s0ypp87.js";
|
|
29
24
|
import {
|
|
30
25
|
alignExtensionVersions
|
|
31
|
-
} from "./
|
|
26
|
+
} from "./r3j8s5y0.js";
|
|
32
27
|
import {
|
|
33
28
|
catalog,
|
|
34
29
|
isDomain
|
|
35
|
-
} from "./
|
|
30
|
+
} from "./ywspezzx.js";
|
|
36
31
|
import {
|
|
37
32
|
snakeCase
|
|
38
|
-
} from "./
|
|
33
|
+
} from "./rpycarcr.js";
|
|
39
34
|
import {
|
|
40
35
|
quoteLiteral
|
|
41
36
|
} from "./94ez8kzh.js";
|
|
42
37
|
import {
|
|
43
38
|
identityKey2,
|
|
44
39
|
identityLabel2
|
|
45
|
-
} from "./
|
|
40
|
+
} from "./358zsv4r.js";
|
|
46
41
|
import {
|
|
47
42
|
OkmError2
|
|
48
43
|
} from "./52szzakm.js";
|
|
@@ -78,6 +73,16 @@ async function assumeRole(connection, role, session) {
|
|
|
78
73
|
await connection.execute(`set role ${quoteIdent(role)}`);
|
|
79
74
|
session.setRole = role;
|
|
80
75
|
}
|
|
76
|
+
async function grantAppMeta(connection, role, session) {
|
|
77
|
+
if (role === undefined)
|
|
78
|
+
return;
|
|
79
|
+
const previous = session.setRole;
|
|
80
|
+
if (previous !== undefined)
|
|
81
|
+
await connection.execute("reset role");
|
|
82
|
+
await connection.execute(`grant select on okm_meta to ${quoteIdent(role)}`);
|
|
83
|
+
if (previous !== undefined)
|
|
84
|
+
await connection.execute(`set role ${quoteIdent(previous)}`);
|
|
85
|
+
}
|
|
81
86
|
async function grantSchema(connection, schema, role) {
|
|
82
87
|
await connection.execute(`grant usage, create on schema ${quoteIdent(schema)} to ${quoteIdent(role)}`);
|
|
83
88
|
}
|
|
@@ -100,9 +105,10 @@ async function runUnit(connection, unit, run, session) {
|
|
|
100
105
|
await rebuildInvalidIndex(connection, item.step.sql);
|
|
101
106
|
const created = createdRoleName(item.step.sql);
|
|
102
107
|
const existed = created !== undefined && await roleExists(connection, created);
|
|
103
|
-
if (created === undefined)
|
|
108
|
+
if (created === undefined) {
|
|
104
109
|
await connection.execute(item.step.sql);
|
|
105
|
-
|
|
110
|
+
await assertSchemaUsageLanded(connection, item.step.sql);
|
|
111
|
+
} else if (!existed)
|
|
106
112
|
await connection.execute(createRoleOnce(item.step.sql));
|
|
107
113
|
if (created !== undefined && created === run.migrationRole) {
|
|
108
114
|
if (!existed) {
|
|
@@ -305,11 +311,39 @@ function concurrentIndexName(sql) {
|
|
|
305
311
|
const match = /^create\s+(?:unique\s+)?index\s+concurrently\s+(?:if\s+not\s+exists\s+)?(?:"([^"]+)"|([A-Za-z_][\w$]*))/i.exec(sql.trim());
|
|
306
312
|
return match?.[1] ?? match?.[2];
|
|
307
313
|
}
|
|
314
|
+
var SCHEMA_USAGE = /^\s*grant\s+usage\s+on\s+schema\s+(?:"((?:[^"]|"")*)"|([A-Za-z_][\w$]*))\s+to\s+(?:"((?:[^"]|"")*)"|([A-Za-z_][\w$]*))\s*;?\s*$/i;
|
|
315
|
+
async function assertSchemaUsageLanded(connection, sql) {
|
|
316
|
+
const match = SCHEMA_USAGE.exec(sql.trim());
|
|
317
|
+
if (match === null)
|
|
318
|
+
return;
|
|
319
|
+
const schema = (match[1] ?? match[2] ?? "").replaceAll('""', '"');
|
|
320
|
+
const role = (match[3] ?? match[4] ?? "").replaceAll('""', '"');
|
|
321
|
+
const found = await connection.execute(`select exists (
|
|
322
|
+
select 1
|
|
323
|
+
from pg_namespace n
|
|
324
|
+
cross join lateral aclexplode(n.nspacl) a
|
|
325
|
+
join pg_roles r on r.oid = a.grantee
|
|
326
|
+
where n.nspname = $1 and r.rolname = $2 and a.privilege_type = 'USAGE'
|
|
327
|
+
)`, [schema, role]);
|
|
328
|
+
const landed = found.rows[0]?.[0];
|
|
329
|
+
if (landed === "t" || landed === "true")
|
|
330
|
+
return;
|
|
331
|
+
throw new OkmError2("OKM1825", `Grant usage on schema ${schema} to ${role} did not take effect.`, {
|
|
332
|
+
kind: "forbidden",
|
|
333
|
+
fix: {
|
|
334
|
+
summary: `Make the migration role the owner of schema ${schema}. ALTER SCHEMA ${quoteIdent(schema)} OWNER TO <migration role>.`
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
308
338
|
function failStep(unit, index, error) {
|
|
339
|
+
const lost = sessionFailure(error);
|
|
340
|
+
if (lost !== undefined) {
|
|
341
|
+
return new OkmError2(lost.code, `Migration ${unit.migrationId} failed at step ${String(index + 1)}: ${lost.message}`, { kind: lost.kind, cause: error, fix: lost.fix });
|
|
342
|
+
}
|
|
309
343
|
if (error instanceof OkmError2)
|
|
310
344
|
return error;
|
|
311
345
|
const message = error instanceof Error ? error.message : "The step failed.";
|
|
312
|
-
return new OkmError2("invalid", `Migration ${unit.migrationId} failed at step ${String(index)}: ${message}`, {
|
|
346
|
+
return new OkmError2("invalid", `Migration ${unit.migrationId} failed at step ${String(index + 1)}: ${message}`, {
|
|
313
347
|
cause: error,
|
|
314
348
|
fix: { summary: "Fix the step and run apply again. Finished steps are not repeated." }
|
|
315
349
|
});
|
|
@@ -362,44 +396,6 @@ function delay(ms) {
|
|
|
362
396
|
});
|
|
363
397
|
}
|
|
364
398
|
|
|
365
|
-
// src/tooling/migrate/files.ts
|
|
366
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
367
|
-
import { join } from "node:path";
|
|
368
|
-
function loadMigrations(directory) {
|
|
369
|
-
if (!existsSync(directory))
|
|
370
|
-
return [];
|
|
371
|
-
const names = readdirSync(directory).filter((file) => file.endsWith(".sql")).sort();
|
|
372
|
-
const migrations = [];
|
|
373
|
-
for (const file of names) {
|
|
374
|
-
const id = file.slice(0, -".sql".length);
|
|
375
|
-
const catalogPath = join(directory, `${id}.catalog.json`);
|
|
376
|
-
if (!existsSync(catalogPath)) {
|
|
377
|
-
throw new OkmError2("invalid", `Migration ${id} is missing its catalog snapshot.`, {
|
|
378
|
-
fix: {
|
|
379
|
-
summary: "Generate the migration again so the SQL and the catalog are written together."
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
const plan = parsePlan(readFileSync(join(directory, file), "utf8"));
|
|
384
|
-
const stored = parseCatalog2(readFileSync(catalogPath, "utf8"));
|
|
385
|
-
const startup = startupCatalog2(stored);
|
|
386
|
-
const hash = catalogHash2(startup);
|
|
387
|
-
migrations.push(startup === stored ? { id, catalogHash: hash, steps: plan.steps } : { id, catalogHash: hash, legacyHash: catalogHash2(stored), steps: plan.steps });
|
|
388
|
-
}
|
|
389
|
-
return migrations;
|
|
390
|
-
}
|
|
391
|
-
function loadHeadSnapshot(directory) {
|
|
392
|
-
const migrations = loadMigrations(directory);
|
|
393
|
-
const last = migrations.at(-1);
|
|
394
|
-
if (last === undefined)
|
|
395
|
-
return;
|
|
396
|
-
return {
|
|
397
|
-
id: last.id,
|
|
398
|
-
catalogHash: last.catalogHash,
|
|
399
|
-
catalog: parseCatalog2(readFileSync(join(directory, `${last.id}.catalog.json`), "utf8"))
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
|
|
403
399
|
// src/tooling/migrate/reference.ts
|
|
404
400
|
function readReference(tables, casing, head) {
|
|
405
401
|
const declared = [];
|
|
@@ -590,8 +586,10 @@ async function installSnapshot(connection, head, schema, reference, session, mig
|
|
|
590
586
|
return;
|
|
591
587
|
await connection.execute("begin");
|
|
592
588
|
began = true;
|
|
593
|
-
for (const sql of batch)
|
|
589
|
+
for (const sql of batch) {
|
|
594
590
|
await connection.execute(sql);
|
|
591
|
+
await assertSchemaUsageLanded(connection, sql);
|
|
592
|
+
}
|
|
595
593
|
await connection.execute("commit");
|
|
596
594
|
began = false;
|
|
597
595
|
batch.length = 0;
|
|
@@ -613,6 +611,7 @@ async function installSnapshot(connection, head, schema, reference, session, mig
|
|
|
613
611
|
} else {
|
|
614
612
|
await flush();
|
|
615
613
|
await connection.execute(sql);
|
|
614
|
+
await assertSchemaUsageLanded(connection, sql);
|
|
616
615
|
}
|
|
617
616
|
if (created !== undefined && created === migrationRole) {
|
|
618
617
|
await flush();
|
|
@@ -755,4 +754,4 @@ function normaliseFunction(object) {
|
|
|
755
754
|
};
|
|
756
755
|
}
|
|
757
756
|
|
|
758
|
-
export { runTarget, assumeRole,
|
|
757
|
+
export { runTarget, assumeRole, grantAppMeta, grantSchema, assertSchemaUsageLanded, statementOutsideTransaction, readReference, referenceInserts, catalogsEqual, provisionMark, expandProvisioned, provisionHistoryIsKnown, installSnapshot, snapshotDifference };
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
|
-
} from "./
|
|
4
|
-
import"./
|
|
3
|
+
} from "./wkme6tep.js";
|
|
4
|
+
import"./qq3899ht.js";
|
|
5
5
|
import"./n442h54c.js";
|
|
6
6
|
import {
|
|
7
|
-
assertTargetPolicy,
|
|
8
|
-
selectTarget,
|
|
9
7
|
openProject
|
|
10
|
-
} from "./
|
|
11
|
-
import
|
|
12
|
-
|
|
8
|
+
} from "./t3g0k88x.js";
|
|
9
|
+
import {
|
|
10
|
+
sessionFailure,
|
|
11
|
+
finishQuiet,
|
|
12
|
+
assertTargetPolicy,
|
|
13
|
+
selectTarget
|
|
14
|
+
} from "./ttmg09vd.js";
|
|
15
|
+
import"./9s0ypp87.js";
|
|
13
16
|
import {
|
|
14
17
|
isExactVersion,
|
|
15
18
|
compareExtensionVersions
|
|
16
|
-
} from "./
|
|
19
|
+
} from "./r3j8s5y0.js";
|
|
17
20
|
import {
|
|
18
21
|
OkmError2
|
|
19
22
|
} from "./52szzakm.js";
|
|
@@ -28,8 +31,10 @@ async function extProject(cwd, command, flags) {
|
|
|
28
31
|
if (command === "list")
|
|
29
32
|
return formatList(await readExtensions(pool));
|
|
30
33
|
return formatCheck(opened.built.catalog.objects, await readExtensions(pool));
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw sessionFailure(error) ?? error;
|
|
31
36
|
} finally {
|
|
32
|
-
await pool.close();
|
|
37
|
+
await finishQuiet(() => pool.close());
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
var LIST_SQL = `
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
readHandle,
|
|
4
4
|
readCall,
|
|
5
5
|
attachHttp
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./j60w0dvr.js";
|
|
7
7
|
import {
|
|
8
8
|
selectedColumns,
|
|
9
9
|
parseOrder,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isRecord,
|
|
16
16
|
registerFailFix,
|
|
17
17
|
fail
|
|
18
|
-
} from "./
|
|
18
|
+
} from "./2z7wv5tj.js";
|
|
19
19
|
import {
|
|
20
20
|
OkmError2,
|
|
21
21
|
throwNamed2
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
tag
|
|
3
|
+
} from "./cn0n68ft.js";
|
|
4
|
+
import {
|
|
5
|
+
OkmError2
|
|
6
|
+
} from "./52szzakm.js";
|
|
7
|
+
|
|
8
|
+
// src/dialects/pg/filter-parse.ts
|
|
9
|
+
var PARSED = [
|
|
10
|
+
"eq",
|
|
11
|
+
"in",
|
|
12
|
+
"inList",
|
|
13
|
+
"notIn",
|
|
14
|
+
"lt",
|
|
15
|
+
"lte",
|
|
16
|
+
"gt",
|
|
17
|
+
"gte",
|
|
18
|
+
"between",
|
|
19
|
+
"startsWith",
|
|
20
|
+
"endsWith",
|
|
21
|
+
"contains",
|
|
22
|
+
"like",
|
|
23
|
+
"ilike",
|
|
24
|
+
"not",
|
|
25
|
+
"containedBy",
|
|
26
|
+
"overlaps",
|
|
27
|
+
"hasKey",
|
|
28
|
+
"hasAnyKey"
|
|
29
|
+
];
|
|
30
|
+
var PARSED_OPS = `,${PARSED.join(",")},`;
|
|
31
|
+
var PARSED_FIX = "Use eq, in, notIn, lt, lte, gt, gte, between, startsWith, endsWith, contains, like, ilike, not, containedBy, overlaps, hasKey, or hasAnyKey.";
|
|
32
|
+
function parseQuery(allow, sort, query, relations) {
|
|
33
|
+
if (typeof query !== "object" || query === null || Array.isArray(query)) {
|
|
34
|
+
throw new OkmError2("OKM1121", "filters parse expects an object of fields.");
|
|
35
|
+
}
|
|
36
|
+
for (const field of Object.keys(allow)) {
|
|
37
|
+
for (const op of allow[field] ?? []) {
|
|
38
|
+
if (PARSED_OPS.includes(`,${op},`))
|
|
39
|
+
continue;
|
|
40
|
+
throw new OkmError2("OKM1120", `filters() cannot apply ${op} on ${field}.`, {
|
|
41
|
+
fix: { summary: PARSED_FIX }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const nested = relations ?? {};
|
|
46
|
+
const whereParts = [];
|
|
47
|
+
let orderBy;
|
|
48
|
+
for (const key of Object.keys(query)) {
|
|
49
|
+
const value = query[key];
|
|
50
|
+
if (key === "sort" && typeof value === "string" && sort.includes(value)) {
|
|
51
|
+
orderBy = { [value]: "asc" };
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (Object.hasOwn(allow, key)) {
|
|
55
|
+
whereParts.push(...clauses(key, allow[key] ?? [], value));
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (Object.hasOwn(nested, key)) {
|
|
59
|
+
whereParts.push(relationClause(key, nested[key] ?? [], value));
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
throw new OkmError2("OKM1123", `Field ${key} is not in the allow list.`, {
|
|
63
|
+
fix: { summary: "Remove the field, or add it to filters({ allow }) or relations." }
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const where = combine(whereParts);
|
|
67
|
+
return orderBy === undefined ? { where } : { where, orderBy };
|
|
68
|
+
}
|
|
69
|
+
function clauses(field, ops, value) {
|
|
70
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
71
|
+
if (!ops.includes("eq")) {
|
|
72
|
+
throw new OkmError2("OKM1120", `filters() cannot apply eq on ${field}.`, {
|
|
73
|
+
fix: { summary: "Add eq to that field, or send an object of allowed operators." }
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return [{ [field]: value }];
|
|
77
|
+
}
|
|
78
|
+
const applied = [];
|
|
79
|
+
for (const op of Object.keys(value)) {
|
|
80
|
+
if (!Object.hasOwn(value, op))
|
|
81
|
+
continue;
|
|
82
|
+
if (!ops.includes(op) && !(op === "inList" && ops.includes("in"))) {
|
|
83
|
+
throw new OkmError2("OKM1120", `filters() cannot apply ${op} on ${field}.`, {
|
|
84
|
+
fix: { summary: "Send an operator that field's allow list names." }
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
applied.push(one(field, op, value[op]));
|
|
88
|
+
}
|
|
89
|
+
if (applied.length === 0) {
|
|
90
|
+
throw new OkmError2("OKM1120", `filters() cannot apply a value on ${field}.`, {
|
|
91
|
+
fix: { summary: "Send eq as a scalar, or an object of allowed operators." }
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return applied;
|
|
95
|
+
}
|
|
96
|
+
function one(field, op, value) {
|
|
97
|
+
switch (op) {
|
|
98
|
+
case "eq":
|
|
99
|
+
return {
|
|
100
|
+
[field]: value !== null && typeof value === "object" ? tag("eq", value) : value
|
|
101
|
+
};
|
|
102
|
+
case "in":
|
|
103
|
+
case "inList":
|
|
104
|
+
return { [field]: tag("inList", list(value, op)) };
|
|
105
|
+
case "notIn":
|
|
106
|
+
return { [field]: tag("notIn", list(value, op)) };
|
|
107
|
+
case "lt":
|
|
108
|
+
return { [field]: tag("lt", value) };
|
|
109
|
+
case "lte":
|
|
110
|
+
return { [field]: tag("lte", value) };
|
|
111
|
+
case "gt":
|
|
112
|
+
return { [field]: tag("gt", value) };
|
|
113
|
+
case "gte":
|
|
114
|
+
return { [field]: tag("gte", value) };
|
|
115
|
+
case "between": {
|
|
116
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
117
|
+
throw new OkmError2("OKM1120", `between on ${field} needs two bounds.`, {
|
|
118
|
+
fix: { summary: "Send between as [from, to]." }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return { [field]: tag("between", [value[0], value[1]]) };
|
|
122
|
+
}
|
|
123
|
+
case "startsWith":
|
|
124
|
+
return { [field]: tag("startsWith", text(value, op)) };
|
|
125
|
+
case "endsWith":
|
|
126
|
+
return { [field]: tag("endsWith", text(value, op)) };
|
|
127
|
+
case "contains":
|
|
128
|
+
return { [field]: tag("contains", value) };
|
|
129
|
+
case "not":
|
|
130
|
+
if (value !== null && typeof value === "object") {
|
|
131
|
+
throw new OkmError2("OKM1120", `not on ${field} takes a scalar.`, {
|
|
132
|
+
fix: { summary: "Send not a scalar or null. Nested operators are not accepted." }
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return { [field]: tag("not", value) };
|
|
136
|
+
case "containedBy":
|
|
137
|
+
return { [field]: tag("containedBy", value) };
|
|
138
|
+
case "overlaps":
|
|
139
|
+
return { [field]: tag("overlaps", value) };
|
|
140
|
+
case "hasKey":
|
|
141
|
+
return { [field]: tag("hasKey", text(value, "hasKey")) };
|
|
142
|
+
case "hasAnyKey":
|
|
143
|
+
return { [field]: tag("hasAnyKey", strings(value, field)) };
|
|
144
|
+
case "like":
|
|
145
|
+
return { [field]: tag("like", text(value, op)) };
|
|
146
|
+
case "ilike":
|
|
147
|
+
return { [field]: tag("ilike", text(value, op)) };
|
|
148
|
+
default:
|
|
149
|
+
throw new OkmError2("OKM1120", `filters() cannot apply ${op} on ${field}.`, {
|
|
150
|
+
fix: { summary: "Use an operator parse applies." }
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function relationClause(name, fields, value) {
|
|
155
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
156
|
+
throw new OkmError2("OKM1120", `filters() cannot apply a value on ${name}.`, {
|
|
157
|
+
fix: { summary: "Send the relation an object of allowlisted fields." }
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const parts = [];
|
|
161
|
+
for (const field of Object.keys(value)) {
|
|
162
|
+
if (!Object.hasOwn(value, field))
|
|
163
|
+
continue;
|
|
164
|
+
if (!fields.includes(field)) {
|
|
165
|
+
throw new OkmError2("OKM1123", `Field ${field} is not in the allow list.`, {
|
|
166
|
+
fix: { summary: "Remove the field, or add it to filters({ relations })." }
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
parts.push(...clauses(field, PARSED, value[field]));
|
|
170
|
+
}
|
|
171
|
+
if (parts.length === 0) {
|
|
172
|
+
throw new OkmError2("OKM1120", `filters() cannot apply a value on ${name}.`, {
|
|
173
|
+
fix: { summary: "Send the relation an object of allowlisted fields." }
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return { [name]: tag("has", combine(parts)) };
|
|
177
|
+
}
|
|
178
|
+
function combine(parts) {
|
|
179
|
+
const first = parts[0];
|
|
180
|
+
if (first === undefined)
|
|
181
|
+
return {};
|
|
182
|
+
if (parts.length === 1)
|
|
183
|
+
return first;
|
|
184
|
+
return tag("and", parts);
|
|
185
|
+
}
|
|
186
|
+
function list(value, op) {
|
|
187
|
+
if (!Array.isArray(value)) {
|
|
188
|
+
throw new OkmError2("OKM1120", `${op} needs an array.`, {
|
|
189
|
+
fix: { summary: "Send that operator an array of values." }
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
194
|
+
function strings(value, field) {
|
|
195
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
196
|
+
throw new OkmError2("OKM1120", `hasAnyKey on ${field} needs an array of strings.`, {
|
|
197
|
+
fix: { summary: "Send hasAnyKey an array of strings." }
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
function text(value, op) {
|
|
203
|
+
if (typeof value !== "string") {
|
|
204
|
+
throw new OkmError2("OKM1120", `${op} needs a string.`, {
|
|
205
|
+
fix: { summary: "Send that operator a string." }
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
export {
|
|
211
|
+
parseQuery
|
|
212
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PgSession
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./wkme6tep.js";
|
|
4
4
|
import {
|
|
5
5
|
isConnectionLost
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./gwn6v667.js";
|
|
7
7
|
import {
|
|
8
8
|
driverErrors,
|
|
9
9
|
rejectClosed,
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
runCall,
|
|
12
12
|
rowsFrom,
|
|
13
13
|
resultFrom
|
|
14
|
-
} from "./
|
|
14
|
+
} from "./cgbamx3e.js";
|
|
15
15
|
|
|
16
16
|
// src/adapters/pg/postgres-extra.ts
|
|
17
17
|
var RESET_ALL = "RESET ALL";
|
|
18
18
|
var UNLOCK = "SELECT pg_advisory_unlock_all()";
|
|
19
|
-
async function
|
|
19
|
+
async function checkout2(pool) {
|
|
20
20
|
if (pool.isClosed())
|
|
21
21
|
return rejectClosed();
|
|
22
22
|
const reserved = await reserveConnection(pool.sql, pool.acquireMs, pool.counters);
|
|
@@ -24,16 +24,17 @@ async function checkout(pool) {
|
|
|
24
24
|
const local = new Set;
|
|
25
25
|
const session = new PgSession(reserved, pool.counters, "reserved", local, pool.isClosed, pool.poolInflight, pool.notices, pool.named);
|
|
26
26
|
let released = false;
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const lost = { on: false };
|
|
28
|
+
arm(reserved, lost);
|
|
29
|
+
const guard = (run) => lost.on ? rejectClosed("CONNECTION_CLOSED") : run().catch((error) => {
|
|
29
30
|
if (isConnectionLost(error))
|
|
30
|
-
lost = true;
|
|
31
|
+
lost.on = true;
|
|
31
32
|
throw error;
|
|
32
33
|
});
|
|
33
34
|
return {
|
|
34
35
|
execute: (text, params, options) => guard(() => runCall(pool.isClosed(), options, (watch) => session.query(text, params, watch))),
|
|
35
36
|
batch: (statements, options) => guard(() => runCall(pool.isClosed(), options, async (watch) => {
|
|
36
|
-
const { runAtomicBatch } = await import("./
|
|
37
|
+
const { runAtomicBatch } = await import("./ag4c7516.js");
|
|
37
38
|
return runAtomicBatch(session, statements, watch);
|
|
38
39
|
})),
|
|
39
40
|
cancel() {
|
|
@@ -44,17 +45,21 @@ async function checkout(pool) {
|
|
|
44
45
|
return;
|
|
45
46
|
released = true;
|
|
46
47
|
try {
|
|
47
|
-
if (!lost)
|
|
48
|
+
if (!lost.on)
|
|
48
49
|
await resetConnection(reserved, session.depth());
|
|
49
50
|
} finally {
|
|
50
51
|
pool.counters.reserved = Math.max(0, pool.counters.reserved - 1);
|
|
51
|
-
if (
|
|
52
|
+
if (lost.on)
|
|
53
|
+
await pool.sql.unsafe("select 1").catch(() => {
|
|
54
|
+
return;
|
|
55
|
+
});
|
|
56
|
+
else
|
|
52
57
|
reserved.release();
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
|
-
async function
|
|
62
|
+
async function describe2(sql, text, params) {
|
|
58
63
|
const pending = sql.unsafe(text, asParams(params), { prepare: true });
|
|
59
64
|
const described = await pending.describe();
|
|
60
65
|
return {
|
|
@@ -62,7 +67,7 @@ async function describe(sql, text, params) {
|
|
|
62
67
|
parameterCount: described.types.length
|
|
63
68
|
};
|
|
64
69
|
}
|
|
65
|
-
async function*
|
|
70
|
+
async function* stream2(sql, text, params) {
|
|
66
71
|
const pending = sql.unsafe(text, asParams(params));
|
|
67
72
|
for await (const chunk of pending.cursor(64)) {
|
|
68
73
|
yield rowsFrom(chunk);
|
|
@@ -124,7 +129,21 @@ function asParams(params) {
|
|
|
124
129
|
return [];
|
|
125
130
|
return params;
|
|
126
131
|
}
|
|
127
|
-
|
|
132
|
+
function watchReserved2(sql, lost) {
|
|
133
|
+
arm(sql, lost);
|
|
134
|
+
}
|
|
135
|
+
function arm(sql, lost) {
|
|
136
|
+
const unsafe = sql.unsafe.bind(sql);
|
|
137
|
+
sql.unsafe = (text, params, options) => unsafe(text, params, {
|
|
138
|
+
...options,
|
|
139
|
+
onexecute(connection) {
|
|
140
|
+
connection.onclose = () => {
|
|
141
|
+
lost.on = true;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async function holdCheckout2(gate, checkout) {
|
|
128
147
|
try {
|
|
129
148
|
const connection = await checkout();
|
|
130
149
|
let released = false;
|
|
@@ -143,7 +162,7 @@ async function holdCheckout(gate, checkout) {
|
|
|
143
162
|
throw error;
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
|
-
async function
|
|
165
|
+
async function holdListener2(gate, start) {
|
|
147
166
|
try {
|
|
148
167
|
const stop = await start();
|
|
149
168
|
let stopped = false;
|
|
@@ -162,7 +181,7 @@ async function holdListener(gate, start) {
|
|
|
162
181
|
throw error;
|
|
163
182
|
}
|
|
164
183
|
}
|
|
165
|
-
function
|
|
184
|
+
function watchQuery2(pending, watch, onAbort, ctx) {
|
|
166
185
|
return pending.then((result) => {
|
|
167
186
|
finishWatch(pending, watch, onAbort, ctx);
|
|
168
187
|
const why = watch.reason();
|
|
@@ -194,11 +213,5 @@ async function classify(error, watch) {
|
|
|
194
213
|
}
|
|
195
214
|
return Promise.reject(errors.mapDriverError(error));
|
|
196
215
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
describe,
|
|
200
|
-
holdCheckout,
|
|
201
|
-
holdListener,
|
|
202
|
-
stream,
|
|
203
|
-
watchQuery
|
|
204
|
-
};
|
|
216
|
+
|
|
217
|
+
export { checkout2, describe2, stream2, watchReserved2, holdCheckout2, holdListener2, watchQuery2 };
|