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,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isConnectionSqlstate,
|
|
3
3
|
isConnectionFailure
|
|
4
|
-
} from "./
|
|
4
|
+
} from "./gwn6v667.js";
|
|
5
5
|
import {
|
|
6
6
|
OkmError2,
|
|
7
7
|
stripRowValues,
|
|
@@ -9,19 +9,21 @@ import {
|
|
|
9
9
|
} from "./52szzakm.js";
|
|
10
10
|
|
|
11
11
|
// src/dialects/pg/errors.ts
|
|
12
|
-
function
|
|
12
|
+
function mapPostgresError2(error, options) {
|
|
13
13
|
if (error instanceof OkmError2)
|
|
14
14
|
return error;
|
|
15
15
|
if (!isDriverError(error))
|
|
16
16
|
return OkmError2.from(error);
|
|
17
17
|
const kind = kindOf(error);
|
|
18
18
|
const columns = columnsOf(error);
|
|
19
|
-
const
|
|
19
|
+
const hint = hintOf(error, kind);
|
|
20
|
+
const fieldReason = hint?.reason ?? (kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint, columns, options?.schema));
|
|
20
21
|
const values = options?.includeValues === true ? valuesOf(error.detail, columns) : undefined;
|
|
21
22
|
const code = kind === "outcome_unknown" ? "OKM1401" : kind;
|
|
22
23
|
return new OkmError2(code, summaryOf(kind, error, columns, fieldReason), {
|
|
23
24
|
kind,
|
|
24
25
|
fieldReason,
|
|
26
|
+
...hint !== undefined ? { fix: hint.fix } : {},
|
|
25
27
|
...error.table !== undefined ? { table: error.table } : {},
|
|
26
28
|
...columns.length > 0 ? { columns } : {},
|
|
27
29
|
...error.constraint !== undefined ? { constraint: error.constraint } : {},
|
|
@@ -32,6 +34,12 @@ function mapPostgresError(error, options) {
|
|
|
32
34
|
...options?.http !== undefined ? { http: options.http } : {}
|
|
33
35
|
});
|
|
34
36
|
}
|
|
37
|
+
var TLS_CODE = /^(ERR_TLS_|ERR_POSTGRES_TLS_|SELF_SIGNED_CERT_|DEPTH_ZERO_SELF_SIGNED_CERT$|UNABLE_TO_VERIFY_LEAF_SIGNATURE$)/;
|
|
38
|
+
function isTlsFailure(error) {
|
|
39
|
+
const cause = error.cause;
|
|
40
|
+
const code = typeof cause === "object" && cause !== null ? Reflect.get(cause, "code") : undefined;
|
|
41
|
+
return typeof code === "string" && TLS_CODE.test(code);
|
|
42
|
+
}
|
|
35
43
|
function isDriverError(error) {
|
|
36
44
|
if (!(error instanceof Error) || error.name !== "DriverError")
|
|
37
45
|
return false;
|
|
@@ -47,10 +55,54 @@ function kindOf(error) {
|
|
|
47
55
|
if (mapped !== undefined)
|
|
48
56
|
return mapped;
|
|
49
57
|
}
|
|
50
|
-
if (isConnectionFailure(error))
|
|
58
|
+
if (isTlsFailure(error) || isConnectionFailure(error))
|
|
51
59
|
return "unavailable";
|
|
52
60
|
return "driver";
|
|
53
61
|
}
|
|
62
|
+
var MIGRATE_FIX = {
|
|
63
|
+
summary: "Run okm migrate apply so the object exists, then check okm migrate status. The reason names the missing object."
|
|
64
|
+
};
|
|
65
|
+
var TLS_FIX = {
|
|
66
|
+
summary: "Check sslmode in the connection URL against the server certificate: use require, verify-ca, or verify-full with the CA the certificate chains to. For node-postgres, add uselibpqcompat=true so sslmode follows libpq."
|
|
67
|
+
};
|
|
68
|
+
function hintOf(error, kind) {
|
|
69
|
+
if (error.sqlstate === "42P01")
|
|
70
|
+
return { reason: "undefined_table", fix: MIGRATE_FIX };
|
|
71
|
+
if (error.sqlstate === "42703")
|
|
72
|
+
return { reason: "undefined_column", fix: MIGRATE_FIX };
|
|
73
|
+
const refresh = refreshHint(error);
|
|
74
|
+
if (refresh !== undefined)
|
|
75
|
+
return refresh;
|
|
76
|
+
if (kind === "unavailable" && error.sqlstate === undefined && isTlsFailure(error)) {
|
|
77
|
+
return { reason: "tls", fix: TLS_FIX };
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
function refreshHint(error) {
|
|
82
|
+
if (error.sqlstate === "0A000" && error.message.includes("materialized view is not populated")) {
|
|
83
|
+
return {
|
|
84
|
+
reason: "not_populated",
|
|
85
|
+
fix: { summary: "Refresh once without CONCURRENTLY so the view is populated." }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (error.sqlstate === "55000" && error.message.includes("cannot refresh materialized view") && error.message.includes("concurrently")) {
|
|
89
|
+
return {
|
|
90
|
+
reason: "no_unique_index",
|
|
91
|
+
fix: {
|
|
92
|
+
summary: "Add a unique index with no WHERE clause, or refresh without CONCURRENTLY."
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (error.sqlstate === "42501" && error.message.includes("materialized view")) {
|
|
97
|
+
return {
|
|
98
|
+
reason: "not_owner",
|
|
99
|
+
fix: {
|
|
100
|
+
summary: "Refresh runs as the owner, the migration role. Connect as that role and call refresh(), or run REFRESH MATERIALIZED VIEW as that role. The application role is not the owner."
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
54
106
|
function kindFromSqlstate(sqlstate) {
|
|
55
107
|
switch (sqlstate) {
|
|
56
108
|
case "23505":
|
|
@@ -88,7 +140,15 @@ function kindFromSqlstate(sqlstate) {
|
|
|
88
140
|
return;
|
|
89
141
|
}
|
|
90
142
|
}
|
|
91
|
-
function reasonOf(kind, table, constraint) {
|
|
143
|
+
function reasonOf(kind, table, constraint, columns, schema) {
|
|
144
|
+
if (schema !== undefined && schema.catalog !== undefined && table !== undefined) {
|
|
145
|
+
const matched = matchObject(schema.catalog, table, constraint, columns);
|
|
146
|
+
if (matched !== undefined)
|
|
147
|
+
return reasonFromObject(schema, table, matched, columns);
|
|
148
|
+
}
|
|
149
|
+
return reasonFromName(kind, table, constraint);
|
|
150
|
+
}
|
|
151
|
+
function reasonFromName(kind, table, constraint) {
|
|
92
152
|
if (constraint === undefined || constraint.length === 0)
|
|
93
153
|
return kind;
|
|
94
154
|
if (table !== undefined) {
|
|
@@ -104,6 +164,61 @@ function reasonOf(kind, table, constraint) {
|
|
|
104
164
|
}
|
|
105
165
|
return constraint;
|
|
106
166
|
}
|
|
167
|
+
function matchObject(catalog, table, constraint, columns) {
|
|
168
|
+
const rows = [];
|
|
169
|
+
for (const object of catalog.objects) {
|
|
170
|
+
if (object.kind !== "constraint" && object.kind !== "index")
|
|
171
|
+
continue;
|
|
172
|
+
if (object.identity.parent.name !== table)
|
|
173
|
+
continue;
|
|
174
|
+
rows.push(object);
|
|
175
|
+
}
|
|
176
|
+
if (columns.length > 0) {
|
|
177
|
+
const key = columns.join(",");
|
|
178
|
+
const hits = rows.filter((object) => object.definition.columns.join(",") === key);
|
|
179
|
+
if (constraint !== undefined) {
|
|
180
|
+
const named = hits.find((object) => object.identity.name === constraint);
|
|
181
|
+
if (named !== undefined)
|
|
182
|
+
return named;
|
|
183
|
+
}
|
|
184
|
+
const only = hits.length === 1 ? hits[0] : undefined;
|
|
185
|
+
if (only !== undefined)
|
|
186
|
+
return only;
|
|
187
|
+
}
|
|
188
|
+
if (constraint === undefined)
|
|
189
|
+
return;
|
|
190
|
+
return rows.find((object) => object.identity.name === constraint);
|
|
191
|
+
}
|
|
192
|
+
function reasonFromObject(schema, table, object, columns) {
|
|
193
|
+
if (object.kind === "index")
|
|
194
|
+
return object.identity.name;
|
|
195
|
+
const nameKey = object.definition.nameKey;
|
|
196
|
+
if (columns.length === 0)
|
|
197
|
+
return nameKey;
|
|
198
|
+
const sqlKey = object.definition.columns.join("_");
|
|
199
|
+
if (nameKey !== sqlKey || object.definition.columns.length < 2)
|
|
200
|
+
return nameKey;
|
|
201
|
+
return fieldKey(schema, table, object.definition.columns) ?? nameKey;
|
|
202
|
+
}
|
|
203
|
+
function fieldKey(schema, table, columns) {
|
|
204
|
+
let model;
|
|
205
|
+
for (const item of Object.values(schema.model)) {
|
|
206
|
+
if (item.sql === table) {
|
|
207
|
+
model = item;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (model === undefined)
|
|
212
|
+
return;
|
|
213
|
+
const fields = [];
|
|
214
|
+
for (const column of columns) {
|
|
215
|
+
const found = model.columns.find((item) => item.sql === column);
|
|
216
|
+
if (found === undefined)
|
|
217
|
+
return;
|
|
218
|
+
fields.push(found.field);
|
|
219
|
+
}
|
|
220
|
+
return fields.join("_");
|
|
221
|
+
}
|
|
107
222
|
function nameKeyOf(rest) {
|
|
108
223
|
const tags = ["_fkey", "_check", "_key"];
|
|
109
224
|
for (const tag of tags) {
|
|
@@ -188,6 +303,9 @@ function unquote(name) {
|
|
|
188
303
|
}
|
|
189
304
|
function summaryOf(kind, error, columns, fieldReason) {
|
|
190
305
|
const label = labelOf(kind);
|
|
306
|
+
if (kind === "driver" && fieldReason === "not_owner") {
|
|
307
|
+
return "The application role cannot refresh a materialized view. Refresh runs as the owner, the migration role.";
|
|
308
|
+
}
|
|
191
309
|
if (kind === "driver")
|
|
192
310
|
return stripRowValues(error.message);
|
|
193
311
|
const where = place(error.table, columns);
|
|
@@ -252,6 +370,5 @@ function labelOf(kind) {
|
|
|
252
370
|
return "Driver error";
|
|
253
371
|
}
|
|
254
372
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
};
|
|
373
|
+
|
|
374
|
+
export { mapPostgresError2 };
|
|
@@ -41,7 +41,7 @@ function hasCapability2(flags, name) {
|
|
|
41
41
|
// src/adapters/failure.ts
|
|
42
42
|
var loading;
|
|
43
43
|
function driverErrors() {
|
|
44
|
-
loading ??= import("./
|
|
44
|
+
loading ??= import("./x72jb7ad.js");
|
|
45
45
|
return loading;
|
|
46
46
|
}
|
|
47
47
|
function rejectClosed(message = "The pool is closed.") {
|
|
@@ -83,7 +83,7 @@ function runCall(closed, options, fn) {
|
|
|
83
83
|
if (options === undefined || !needsWatch(options))
|
|
84
84
|
return fn(undefined);
|
|
85
85
|
const watched = options;
|
|
86
|
-
return import("./
|
|
86
|
+
return import("./54tqkxja.js").then(({ openWatch }) => {
|
|
87
87
|
const watch = openWatch(watched);
|
|
88
88
|
return fn(watch).finally(() => {
|
|
89
89
|
watch.finish();
|
|
@@ -7,9 +7,11 @@ import {
|
|
|
7
7
|
startupCatalog2,
|
|
8
8
|
startupHash2,
|
|
9
9
|
loadTrustedCatalog2,
|
|
10
|
+
catalogFileText2,
|
|
10
11
|
parseCatalog2
|
|
11
|
-
} from "./
|
|
12
|
+
} from "./qq3899ht.js";
|
|
12
13
|
export {
|
|
14
|
+
catalogFileText2 as catalogFileText,
|
|
13
15
|
catalogHash2 as catalogHash,
|
|
14
16
|
creationOrder2 as creationOrder,
|
|
15
17
|
loadTrustedCatalog2 as loadTrustedCatalog,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
catalogFileText2
|
|
3
|
+
} from "./qq3899ht.js";
|
|
1
4
|
import {
|
|
2
5
|
OkmError2
|
|
3
6
|
} from "./52szzakm.js";
|
|
@@ -11,7 +14,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
|
|
|
11
14
|
if (code.artifact !== undefined) {
|
|
12
15
|
const artifact = code.artifact;
|
|
13
16
|
await loadOnce(`text\x00${artifact.hash}`, async () => {
|
|
14
|
-
const { loadTrustedCatalog } = await import("./
|
|
17
|
+
const { loadTrustedCatalog } = await import("./dk8v79p3.js");
|
|
15
18
|
loadTrustedCatalog(artifact.text, artifact.hash);
|
|
16
19
|
});
|
|
17
20
|
} else if (code.fromFile) {
|
|
@@ -25,7 +28,7 @@ async function assertCompatible(pool, schema, recordedHash, source, options) {
|
|
|
25
28
|
}
|
|
26
29
|
});
|
|
27
30
|
}
|
|
28
|
-
const { loadTrustedCatalog } = await import("./
|
|
31
|
+
const { loadTrustedCatalog } = await import("./dk8v79p3.js");
|
|
29
32
|
loadTrustedCatalog(text, code.hash);
|
|
30
33
|
});
|
|
31
34
|
}
|
|
@@ -39,7 +42,7 @@ async function codeHash(schema, source) {
|
|
|
39
42
|
const listed = await readHashFile(source.catalogDir);
|
|
40
43
|
if (listed !== undefined)
|
|
41
44
|
return { hash: listed, fromFile: true };
|
|
42
|
-
const { catalogHash } = await import("./
|
|
45
|
+
const { catalogHash } = await import("./dk8v79p3.js");
|
|
43
46
|
return { hash: catalogHash(schemaCatalog(schema)), fromFile: false };
|
|
44
47
|
}
|
|
45
48
|
function schemaCatalog(schema) {
|
|
@@ -57,12 +60,12 @@ async function readHashFile(catalogDir) {
|
|
|
57
60
|
const text = await readText(`${artifactDir(catalogDir)}/catalog.hash`);
|
|
58
61
|
if (text === undefined)
|
|
59
62
|
return;
|
|
60
|
-
const hash = text.trim();
|
|
63
|
+
const hash = catalogFileText2(text, "catalog.hash").trim();
|
|
61
64
|
return hash.length === 0 ? undefined : hash;
|
|
62
65
|
}
|
|
63
66
|
function artifactDir(catalogDir) {
|
|
64
67
|
if (catalogDir !== undefined)
|
|
65
|
-
return catalogDir.replace(
|
|
68
|
+
return catalogDir.replace(/[/\\]+$/, "");
|
|
66
69
|
const cwd = globalThis.process?.cwd?.() ?? ".";
|
|
67
70
|
return `${cwd}/.okm`;
|
|
68
71
|
}
|
|
@@ -4,22 +4,26 @@ import {
|
|
|
4
4
|
viewDependencyEdges,
|
|
5
5
|
PUBLIC,
|
|
6
6
|
introspectSchema
|
|
7
|
-
} from "./
|
|
7
|
+
} from "./vjpnzwjz.js";
|
|
8
8
|
import {
|
|
9
|
-
planMigration
|
|
10
|
-
|
|
9
|
+
planMigration,
|
|
10
|
+
sessionFailure,
|
|
11
|
+
finishQuiet,
|
|
12
|
+
assertDirectConnection,
|
|
13
|
+
assertStableBackend
|
|
14
|
+
} from "./ttmg09vd.js";
|
|
11
15
|
import {
|
|
12
16
|
quoteIdent,
|
|
13
17
|
createObjectSql
|
|
14
|
-
} from "./
|
|
18
|
+
} from "./9s0ypp87.js";
|
|
15
19
|
import {
|
|
16
20
|
normaliseViewQuery,
|
|
17
21
|
viewObject,
|
|
18
22
|
materializedViewObject
|
|
19
|
-
} from "./
|
|
23
|
+
} from "./zy8r7qvz.js";
|
|
20
24
|
import {
|
|
21
25
|
catalog
|
|
22
|
-
} from "./
|
|
26
|
+
} from "./ywspezzx.js";
|
|
23
27
|
import {
|
|
24
28
|
OkmError2
|
|
25
29
|
} from "./52szzakm.js";
|
|
@@ -49,8 +53,11 @@ async function sealViews(runner, source) {
|
|
|
49
53
|
return source;
|
|
50
54
|
await dropScratch(runner);
|
|
51
55
|
await runner.query(`create schema ${quoteIdent(SCRATCH)}`);
|
|
56
|
+
const previous = await runner.query(`select current_setting('search_path') as path`);
|
|
57
|
+
const saved = cellText(previous[0]?.path);
|
|
58
|
+
const path = await scratchSearchPath(runner, source);
|
|
52
59
|
try {
|
|
53
|
-
await runner.query(`
|
|
60
|
+
await runner.query(`select set_config('search_path', $1, false)`, [path]);
|
|
54
61
|
await createObjects(runner, source, "type");
|
|
55
62
|
for (const object of source.objects) {
|
|
56
63
|
if (object.kind !== "table")
|
|
@@ -83,7 +90,8 @@ async function sealViews(runner, source) {
|
|
|
83
90
|
query,
|
|
84
91
|
owner: object.owner,
|
|
85
92
|
provenance: object.provenance,
|
|
86
|
-
dependencies
|
|
93
|
+
dependencies,
|
|
94
|
+
...object.definition.securityInvoker === true ? { securityInvoker: true } : {}
|
|
87
95
|
});
|
|
88
96
|
}
|
|
89
97
|
return materializedViewObject({
|
|
@@ -99,10 +107,37 @@ async function sealViews(runner, source) {
|
|
|
99
107
|
});
|
|
100
108
|
return catalog(next);
|
|
101
109
|
} finally {
|
|
102
|
-
await runner.query(
|
|
110
|
+
await runner.query(`select set_config('search_path', $1, false)`, [saved]).catch(() => {
|
|
111
|
+
return;
|
|
112
|
+
});
|
|
103
113
|
await dropScratch(runner);
|
|
104
114
|
}
|
|
105
115
|
}
|
|
116
|
+
async function scratchSearchPath(runner, source) {
|
|
117
|
+
const names = new Set;
|
|
118
|
+
for (const object of source.objects) {
|
|
119
|
+
if (object.kind !== "column")
|
|
120
|
+
continue;
|
|
121
|
+
const bare = object.definition.dataType.split(".").pop()?.replace(/\(.*$/, "").replace(/\[\]$/, "").trim().toLowerCase();
|
|
122
|
+
if (bare !== undefined && bare.length > 0)
|
|
123
|
+
names.add(bare);
|
|
124
|
+
}
|
|
125
|
+
const extra = [];
|
|
126
|
+
if (names.size > 0) {
|
|
127
|
+
const rows = await runner.query(`select distinct n.nspname as schema
|
|
128
|
+
from pg_type t
|
|
129
|
+
join pg_namespace n on n.oid = t.typnamespace
|
|
130
|
+
where t.typname = any(string_to_array($1, E'\\x1f'))
|
|
131
|
+
and n.nspname not in ('pg_catalog', 'information_schema', 'pg_toast')`, [[...names].join("\x1F")]);
|
|
132
|
+
for (const row of rows) {
|
|
133
|
+
const schema = cellText(row.schema);
|
|
134
|
+
if (schema.length > 0 && schema !== "public" && schema !== SCRATCH)
|
|
135
|
+
extra.push(schema);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
extra.sort();
|
|
139
|
+
return [SCRATCH, ...extra, "public"].map((name) => quoteIdent(name)).join(", ");
|
|
140
|
+
}
|
|
106
141
|
async function createObjects(runner, source, kind) {
|
|
107
142
|
for (const object of source.objects) {
|
|
108
143
|
if (object.kind !== kind)
|
|
@@ -193,7 +228,8 @@ async function dropScratch(runner) {
|
|
|
193
228
|
}
|
|
194
229
|
|
|
195
230
|
// src/tooling/migrate/drift.ts
|
|
196
|
-
async function assertAuthorDrift2(url, author, roles) {
|
|
231
|
+
async function assertAuthorDrift2(url, author, roles, allowPooler = false) {
|
|
232
|
+
assertDirectConnection(url, allowPooler);
|
|
197
233
|
const sql = postgres(url, {
|
|
198
234
|
max: 1,
|
|
199
235
|
connect_timeout: 5,
|
|
@@ -201,6 +237,10 @@ async function assertAuthorDrift2(url, author, roles) {
|
|
|
201
237
|
onnotice: () => {}
|
|
202
238
|
});
|
|
203
239
|
try {
|
|
240
|
+
await assertStableBackend(async () => {
|
|
241
|
+
const rows = await sql`select pg_backend_pid()::text as pid`;
|
|
242
|
+
return rows[0]?.pid ?? "";
|
|
243
|
+
}, allowPooler);
|
|
204
244
|
const present = await sql`
|
|
205
245
|
select to_regclass('public.okm_meta')::text as reg
|
|
206
246
|
`;
|
|
@@ -219,8 +259,10 @@ ${plan.steps.map((step) => step.sql).join(`
|
|
|
219
259
|
summary: "Change the schema or the database so okm check reports no difference."
|
|
220
260
|
}
|
|
221
261
|
});
|
|
262
|
+
} catch (error) {
|
|
263
|
+
throw sessionFailure(error) ?? error;
|
|
222
264
|
} finally {
|
|
223
|
-
await sql.end({ timeout: 5 });
|
|
265
|
+
await finishQuiet(() => sql.end({ timeout: 5 }));
|
|
224
266
|
}
|
|
225
267
|
}
|
|
226
268
|
function catalogQuery2(sql) {
|
|
@@ -238,12 +280,17 @@ function catalogQuery2(sql) {
|
|
|
238
280
|
}
|
|
239
281
|
function managedRoleOptions2(roles) {
|
|
240
282
|
const names = managedRoleNames(roles);
|
|
241
|
-
return names === undefined ? undefined : {
|
|
283
|
+
return names === undefined ? undefined : {
|
|
284
|
+
managedRoles: names,
|
|
285
|
+
...roles?.reporting !== undefined ? { reportingRole: roles.reporting } : {}
|
|
286
|
+
};
|
|
242
287
|
}
|
|
243
288
|
function managedRoleNames(roles) {
|
|
244
289
|
if (roles === undefined)
|
|
245
290
|
return;
|
|
246
291
|
const names = new Set([roles.migration, roles.app]);
|
|
292
|
+
if (roles.reporting !== undefined)
|
|
293
|
+
names.add(roles.reporting);
|
|
247
294
|
for (const role of roles.managed ?? [])
|
|
248
295
|
names.add(role.name);
|
|
249
296
|
return [...names];
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open3
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./5j36z8dn.js";
|
|
4
|
+
import"./8dqhth8c.js";
|
|
4
5
|
import {
|
|
5
6
|
PGLITE_CAPABILITIES,
|
|
6
7
|
readCapability2,
|
|
7
8
|
hasCapability2
|
|
8
|
-
} from "./
|
|
9
|
+
} from "./cgbamx3e.js";
|
|
9
10
|
export {
|
|
10
11
|
PGLITE_CAPABILITIES as capabilities,
|
|
11
12
|
hasCapability2 as hasCapability,
|
|
@@ -28,7 +28,7 @@ function isConnectionFailure(error) {
|
|
|
28
28
|
if (!(error instanceof Error))
|
|
29
29
|
return false;
|
|
30
30
|
const message = error.message;
|
|
31
|
-
return message.includes("ECONNREFUSED") || message.includes("ECONNRESET") || message.includes("
|
|
31
|
+
return message.includes("ECONNREFUSED") || message.includes("ECONNRESET") || message.includes("CONNECT") || message.includes("terminating connection") || message.includes("The pool is closed");
|
|
32
32
|
}
|
|
33
33
|
function isConnectionLost(error) {
|
|
34
34
|
if (isConnectionFailure(error))
|
|
@@ -51,4 +51,4 @@ function readCode(error, key) {
|
|
|
51
51
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export { isConnectionSqlstate, isConnectionFailure, isConnectionLost };
|
|
54
|
+
export { isConnectionSqlstate, isConnectionErrno, isConnectionFailure, isConnectionLost };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validationGate
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./ze4hxsmy.js";
|
|
4
4
|
import {
|
|
5
5
|
isOperator
|
|
6
6
|
} from "./cn0n68ft.js";
|
|
@@ -422,6 +422,12 @@ function isRecord(value) {
|
|
|
422
422
|
function failShape(message) {
|
|
423
423
|
throw new OkmError2("OKM1121", message, { kind: "invalid" });
|
|
424
424
|
}
|
|
425
|
+
function failedMessage(first) {
|
|
426
|
+
if (first === undefined)
|
|
427
|
+
return "Validation failed.";
|
|
428
|
+
const field = first.path.length === 0 ? "$row" : first.path.join(".");
|
|
429
|
+
return `Validation failed: ${field} ${first.message}`;
|
|
430
|
+
}
|
|
425
431
|
function throwIssues(issues) {
|
|
426
432
|
const columns = [];
|
|
427
433
|
for (const issue of issues) {
|
|
@@ -429,7 +435,7 @@ function throwIssues(issues) {
|
|
|
429
435
|
if (typeof field === "string" && !columns.includes(field))
|
|
430
436
|
columns.push(field);
|
|
431
437
|
}
|
|
432
|
-
throw new OkmError2("OKM1200",
|
|
438
|
+
throw new OkmError2("OKM1200", failedMessage(issues[0]), {
|
|
433
439
|
kind: "invalid",
|
|
434
440
|
...columns.length > 0 ? { columns } : {},
|
|
435
441
|
issues,
|
|
@@ -2,23 +2,23 @@ import {
|
|
|
2
2
|
catalog,
|
|
3
3
|
enumType,
|
|
4
4
|
sameEnumLabels
|
|
5
|
-
} from "./
|
|
5
|
+
} from "./ywspezzx.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
rejectLater
|
|
10
|
-
} from "./jsd07prz.js";
|
|
11
|
-
import {
|
|
12
|
-
withLocation
|
|
13
|
-
} from "./k7dwkhvq.js";
|
|
7
|
+
isRelationCall
|
|
8
|
+
} from "./k68eedmy.js";
|
|
14
9
|
import {
|
|
15
10
|
encodeText,
|
|
16
11
|
decodeText
|
|
17
|
-
} from "./
|
|
12
|
+
} from "./ed0b8k4s.js";
|
|
13
|
+
import {
|
|
14
|
+
snakeCase,
|
|
15
|
+
emittedTypeName,
|
|
16
|
+
rejectLater
|
|
17
|
+
} from "./rpycarcr.js";
|
|
18
18
|
import {
|
|
19
19
|
ColumnBuilder2,
|
|
20
20
|
formatType
|
|
21
|
-
} from "./
|
|
21
|
+
} from "./ywr8hmey.js";
|
|
22
22
|
import {
|
|
23
23
|
definition,
|
|
24
24
|
unavailable
|
|
@@ -26,6 +26,9 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
quoteLiteral
|
|
28
28
|
} from "./94ez8kzh.js";
|
|
29
|
+
import {
|
|
30
|
+
withLocation
|
|
31
|
+
} from "./y6jdds7g.js";
|
|
29
32
|
import {
|
|
30
33
|
staticNamespace2,
|
|
31
34
|
table3,
|
|
@@ -34,7 +37,7 @@ import {
|
|
|
34
37
|
constraint2,
|
|
35
38
|
sequence2,
|
|
36
39
|
compareText
|
|
37
|
-
} from "./
|
|
40
|
+
} from "./358zsv4r.js";
|
|
38
41
|
import {
|
|
39
42
|
assertIdentifier2,
|
|
40
43
|
fitIdentifier2,
|
|
@@ -49,85 +52,6 @@ import {
|
|
|
49
52
|
readClientGenerator
|
|
50
53
|
} from "./rwmrejjz.js";
|
|
51
54
|
|
|
52
|
-
// src/dialects/pg/through.ts
|
|
53
|
-
var emit = (planner, schema, relation, child, sink, parent, alias, depth) => {
|
|
54
|
-
const through = relation.through;
|
|
55
|
-
const join = through === undefined ? undefined : planner.indexes(schema).get(through.table);
|
|
56
|
-
if (through === undefined || join === undefined) {
|
|
57
|
-
return catalogError2("OKM1020", `Relation ${relation.name} names a join table that is not in the schema.`);
|
|
58
|
-
}
|
|
59
|
-
const { quote } = planner;
|
|
60
|
-
const joinAlias = `j${alias}`;
|
|
61
|
-
sink.mark(`via:${through.table}`);
|
|
62
|
-
sink.text(`${quote(join.model.sql)} ${joinAlias} join ${quote(child.model.sql)} ${alias} on `);
|
|
63
|
-
for (let index = 0;index < through.local.length; index += 1) {
|
|
64
|
-
const local = through.local[index];
|
|
65
|
-
const remote = through.remote[index];
|
|
66
|
-
if (local === undefined || remote === undefined)
|
|
67
|
-
continue;
|
|
68
|
-
if (index > 0)
|
|
69
|
-
sink.text(" and ");
|
|
70
|
-
sink.text(`${alias}.${quote(remote)} = ${joinAlias}.${quote(local)}`);
|
|
71
|
-
}
|
|
72
|
-
sink.text(" where ");
|
|
73
|
-
planner.join(sink, parent, joinAlias, relation);
|
|
74
|
-
planner.where(schema, join, undefined, sink, joinAlias, depth + 1, true);
|
|
75
|
-
};
|
|
76
|
-
function resolveThrough(scope, table, through, from, to) {
|
|
77
|
-
for (const name of [table, through]) {
|
|
78
|
-
if (!scope.tables.includes(name)) {
|
|
79
|
-
throwNamed2("OKM1020", name, scope.tables, `Relation ${scope.owner}.${scope.name} names ${name}, which is not in the schema. Accepted names: ${scope.tables.join(", ")}.`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const toOwner = pick(scope, through, scope.owner, from, `${scope.owner}.${scope.name}`, "from");
|
|
83
|
-
const toTable = pick(scope, through, table, to, `${scope.owner}.${scope.name}`, "to");
|
|
84
|
-
if (toOwner === toTable) {
|
|
85
|
-
catalogError2("OKM1021", `Relation ${scope.owner}.${scope.name} uses ${toOwner.fromField} on ${through} for both ends. Pass from and to.`);
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
name: scope.name,
|
|
89
|
-
kind: "many",
|
|
90
|
-
table,
|
|
91
|
-
local: toOwner.remote,
|
|
92
|
-
remote: toOwner.local,
|
|
93
|
-
through: { table: through, local: toTable.local, remote: toTable.remote, emit }
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function pick(scope, through, target, field, label, end) {
|
|
97
|
-
const matches = scope.edges.filter((edge) => edge.fromTable === through && edge.toTable === target && (field === undefined || edge.fromField === field));
|
|
98
|
-
const [only] = matches;
|
|
99
|
-
if (matches.length === 1 && only !== undefined)
|
|
100
|
-
return only;
|
|
101
|
-
const fields = matches.map((edge) => edge.fromField).sort();
|
|
102
|
-
catalogError2("OKM1021", `Relation ${label} through ${through} is ambiguous at ${end}. Accepted columns: ${fields.length === 0 ? "(none)" : fields.join(", ")}.`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// src/dialects/pg/relations.ts
|
|
106
|
-
function one2(table, field) {
|
|
107
|
-
return { kind: "one", table, field };
|
|
108
|
-
}
|
|
109
|
-
function many2(table, field) {
|
|
110
|
-
return { kind: "many", table, field };
|
|
111
|
-
}
|
|
112
|
-
function isRelationCall(value) {
|
|
113
|
-
if (typeof value !== "object" || value === null)
|
|
114
|
-
return false;
|
|
115
|
-
if (!("kind" in value) || !("table" in value))
|
|
116
|
-
return false;
|
|
117
|
-
const kind = value.kind;
|
|
118
|
-
return (kind === "one" || kind === "many") && typeof value.table === "string";
|
|
119
|
-
}
|
|
120
|
-
function manyThrough2(table, options) {
|
|
121
|
-
const { through, from, to } = options;
|
|
122
|
-
return {
|
|
123
|
-
kind: "many",
|
|
124
|
-
table,
|
|
125
|
-
field: undefined,
|
|
126
|
-
through,
|
|
127
|
-
resolve: (scope) => resolveThrough(scope, table, through, from, to)
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
55
|
// src/dialects/pg/compile.ts
|
|
132
56
|
function compileColumn(builder, input) {
|
|
133
57
|
const state = builder.state;
|
|
@@ -212,7 +136,7 @@ function readTenancy(value) {
|
|
|
212
136
|
definition("schema() tenancy must be columnTenancy() from okmodel/tenancy.");
|
|
213
137
|
}
|
|
214
138
|
const record = value;
|
|
215
|
-
if (
|
|
139
|
+
if (typeof record.rewrite !== "function") {
|
|
216
140
|
definition("schema() tenancy must be columnTenancy() from okmodel/tenancy.");
|
|
217
141
|
}
|
|
218
142
|
return value;
|
|
@@ -557,7 +481,7 @@ function compileTable(item, namespace, casing, codecs, requires, idDefault, jobs
|
|
|
557
481
|
references: column.state.references,
|
|
558
482
|
encode: column.state.encode,
|
|
559
483
|
decode: decode === decodeText ? undefined : decode,
|
|
560
|
-
hidden: column.state.hidden,
|
|
484
|
+
hidden: column.state.filterable === true ? "filter" : column.state.hidden,
|
|
561
485
|
sensitive: column.state.sensitive,
|
|
562
486
|
guarded: column.state.guarded,
|
|
563
487
|
writable: column.state.guarded !== true && column.state.omitWrite !== true && column.state.generated === undefined,
|
|
@@ -1127,4 +1051,4 @@ function list(names) {
|
|
|
1127
1051
|
return names.length === 0 ? "(none)" : names.join(", ");
|
|
1128
1052
|
}
|
|
1129
1053
|
|
|
1130
|
-
export {
|
|
1054
|
+
export { schema2, addSchemaHook };
|