okmodel 0.5.1 → 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 +29 -14
- 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 +5 -4
- package/dist/dialects/pg/fn/index.js +2 -2
- package/dist/dialects/pg/index.d.ts +2 -1
- package/dist/dialects/pg/index.js +23 -17
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/model.d.ts +7 -2
- 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/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/conflict.d.ts +2 -2
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/pg/bun.js +4 -3
- package/dist/runtime/pg/pg.js +3 -3
- package/dist/runtime/pg/pglite.js +4 -3
- package/dist/runtime/pg/postgresjs.js +3 -3
- package/dist/runtime/plan.d.ts +18 -10
- 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/{6qd27mx0.js → 1f0xa3cb.js} +5 -5
- package/dist/shared/1nw1f3vs.js +23 -0
- package/dist/shared/{96qcj21c.js → 1z04fa85.js} +19 -9
- package/dist/shared/{qm7cdtvr.js → 2cg3wnxc.js} +296 -60
- package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
- package/dist/shared/{gbtcc2d7.js → 2z7wv5tj.js} +10 -35
- package/dist/shared/{k8v5v5wj.js → 32cnm7kn.js} +6 -1
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/{2pqx26h8.js → 3fqwmr09.js} +31 -22
- package/dist/shared/{zqrnhwsq.js → 3qnhc7w5.js} +16 -9
- package/dist/shared/{r2sp8hrc.js → 5d8t84hg.js} +12 -3
- package/dist/shared/{87jvvhnt.js → 5j36z8dn.js} +16 -5
- 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/{v36c5g6p.js → 8x72s86k.js} +400 -13
- package/dist/shared/{nxdp2ze3.js → 929h19xp.js} +107 -5
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/{efmy2gcg.js → ag4c7516.js} +1 -1
- package/dist/shared/b3awxn7h.js +45 -0
- package/dist/shared/b4v57v3x.js +9 -0
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{51mvgj8w.js → c58secgj.js} +100 -7
- 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/{sycnx8gt.js → f0f1n281.js} +18 -8
- package/dist/shared/{f5cw5q5r.js → g90m9b0g.js} +2 -1
- package/dist/shared/{pf0d8f77.js → gwn6v667.js} +1 -1
- package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
- package/dist/shared/{5enne4ma.js → hazqqecq.js} +17 -93
- package/dist/shared/{jwtxdj06.js → j3rkk835.js} +32 -9
- package/dist/shared/{hf22e0wt.js → j60w0dvr.js} +19 -18
- 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/{0t22wwh1.js → mb2ycs1p.js} +4 -2
- package/dist/shared/{cr74e96e.js → n076ydsc.js} +1 -1
- package/dist/shared/{cctw17hj.js → nx9hh281.js} +31 -28
- package/dist/shared/{gde73es6.js → p248q79y.js} +56 -55
- package/dist/shared/{janx09m5.js → p6bjzq9q.js} +11 -7
- package/dist/shared/{6rk2gen5.js → pjr6xrm5.js} +2 -2
- package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
- package/dist/shared/{caw8b9d8.js → q3j1tq7a.js} +35 -22
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{tm5ab8we.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/{ntneex2a.js → rpycarcr.js} +6 -6
- package/dist/shared/{aj2qxyhj.js → sbdme3vy.js} +14 -2
- package/dist/shared/{qv2ydck9.js → t3g0k88x.js} +638 -67
- package/dist/shared/{ga3sfy93.js → ttmg09vd.js} +535 -200
- package/dist/shared/{kfjp0gck.js → venqrjna.js} +8 -4
- package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
- package/dist/shared/{32zqc1dw.js → vmfkhszw.js} +31 -7
- package/dist/shared/{krxx77g0.js → wkme6tep.js} +10 -8
- package/dist/shared/{ps7a6h14.js → wt5rzv1h.js} +12 -8
- package/dist/shared/wxr8cwns.js +6 -0
- package/dist/shared/{6mnp99hx.js → wynzeggs.js} +16 -12
- package/dist/shared/x3jc53kg.js +220 -0
- package/dist/shared/{sdc7r2ww.js → xq0mvhts.js} +8 -8
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{47x8x9ze.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/{nkaxvt9q.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/{r8x5qhd7.js → zm0mafk4.js} +10 -4
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +41 -15
- 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/config.d.ts +3 -2
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +14 -14
- package/dist/tooling/migrate/lint.d.ts +1 -1
- 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 +6 -3
- 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 +20 -3
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -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 +11 -5
- package/package.json +5 -2
- package/dist/shared/7zwwyh0v.js +0 -448
- package/dist/shared/q58y17hy.js +0 -21
|
@@ -1,197 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
viewClient
|
|
3
|
+
} from "../../../shared/x3jc53kg.js";
|
|
1
4
|
import {
|
|
2
5
|
viewObject,
|
|
3
6
|
materializedViewObject,
|
|
4
7
|
materializedViewIndex
|
|
5
|
-
} from "../../../shared/
|
|
6
|
-
import {
|
|
7
|
-
encodeUuid,
|
|
8
|
-
decodeUuid
|
|
9
|
-
} from "../../../shared/dyj86cmj.js";
|
|
10
|
-
import {
|
|
11
|
-
snakeCase
|
|
12
|
-
} from "../../../shared/ntneex2a.js";
|
|
13
|
-
import {
|
|
14
|
-
encodeText,
|
|
15
|
-
decodeText
|
|
16
|
-
} from "../../../shared/4m9fn52z.js";
|
|
8
|
+
} from "../../../shared/zy8r7qvz.js";
|
|
17
9
|
import {
|
|
18
10
|
staticNamespace2
|
|
19
|
-
} from "../../../shared/
|
|
11
|
+
} from "../../../shared/358zsv4r.js";
|
|
20
12
|
import {
|
|
21
13
|
OkmError2
|
|
22
14
|
} from "../../../shared/52szzakm.js";
|
|
23
15
|
|
|
24
|
-
// src/dialects/pg/view/client.ts
|
|
25
|
-
function viewClient(name, columns, query, tenancy) {
|
|
26
|
-
const field = camelCase(name);
|
|
27
|
-
const marked = readGlobal(name, tenancy);
|
|
28
|
-
return {
|
|
29
|
-
field,
|
|
30
|
-
install(model, scope, tables, casing, scoped) {
|
|
31
|
-
if (Object.hasOwn(model, field)) {
|
|
32
|
-
throw new OkmError2("OKM1023", `View ${name} uses the client name ${field}.`, {
|
|
33
|
-
fix: { summary: "Give the view a name that no table uses." }
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
const exposes = exposesKey(columns, scope);
|
|
37
|
-
if (scope !== undefined && readsTenant(query, tables, casing, scoped)) {
|
|
38
|
-
if (!exposes && marked === undefined) {
|
|
39
|
-
throw new OkmError2("OKM1820", `View ${name} reads a tenant table and does not expose ${scope.key}.`, {
|
|
40
|
-
fix: {
|
|
41
|
-
summary: "Expose the tenant key so the predicate can be applied, or declare global(reason)."
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
if (exposes) {
|
|
46
|
-
scope.scopeView(field);
|
|
47
|
-
scoped.add(name);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
model[field] = {
|
|
51
|
-
name: field,
|
|
52
|
-
sql: name,
|
|
53
|
-
primary: [],
|
|
54
|
-
uniques: [],
|
|
55
|
-
columns: columnModels(columns, scope),
|
|
56
|
-
relations: []
|
|
57
|
-
};
|
|
58
|
-
},
|
|
59
|
-
hook(target, ctx) {
|
|
60
|
-
publish(field, target, ctx);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
function publish(field, target, ctx) {
|
|
65
|
-
if (ctx.tables === undefined || ctx.table !== undefined)
|
|
66
|
-
return;
|
|
67
|
-
const handle = ctx.tables[field];
|
|
68
|
-
if (typeof handle !== "object" || handle === null)
|
|
69
|
-
return;
|
|
70
|
-
const source = handle;
|
|
71
|
-
const views = target.views;
|
|
72
|
-
const map = typeof views === "object" && views !== null ? views : {};
|
|
73
|
-
map[field] = {
|
|
74
|
-
find: source.find,
|
|
75
|
-
one: source.one,
|
|
76
|
-
count: source.count,
|
|
77
|
-
exists: source.exists
|
|
78
|
-
};
|
|
79
|
-
target.views = map;
|
|
80
|
-
delete ctx.tables[field];
|
|
81
|
-
delete target[field];
|
|
82
|
-
}
|
|
83
|
-
function columnModels(columns, tenancy) {
|
|
84
|
-
const seen = new Set;
|
|
85
|
-
const models = [];
|
|
86
|
-
for (const column of columns) {
|
|
87
|
-
const field = fieldName(column.name, tenancy);
|
|
88
|
-
if (seen.has(field)) {
|
|
89
|
-
throw new OkmError2("OKM1020", `View column ${column.name} repeats ${field}.`, {
|
|
90
|
-
fix: { summary: "Declare each output column once." }
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
seen.add(field);
|
|
94
|
-
const uuid = column.type.toLowerCase() === "uuid";
|
|
95
|
-
const key = tenancy !== undefined && field === tenancy.key;
|
|
96
|
-
models.push({
|
|
97
|
-
field,
|
|
98
|
-
sql: column.name,
|
|
99
|
-
dataType: column.type,
|
|
100
|
-
encode: uuid ? (value) => encodeUuid(textValue(value)) : (value) => encodeText(textValue(value)),
|
|
101
|
-
decode: uuid ? decodeUuid : decodeText,
|
|
102
|
-
hidden: false,
|
|
103
|
-
sensitive: false,
|
|
104
|
-
guarded: key,
|
|
105
|
-
writable: false,
|
|
106
|
-
guardUpdate: false
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
return models;
|
|
110
|
-
}
|
|
111
|
-
function exposesKey(columns, tenancy) {
|
|
112
|
-
if (tenancy === undefined)
|
|
113
|
-
return false;
|
|
114
|
-
return columns.some((column) => fieldName(column.name, tenancy) === tenancy.key);
|
|
115
|
-
}
|
|
116
|
-
function readsTenant(query, tables, casing, scoped) {
|
|
117
|
-
for (const name of scoped) {
|
|
118
|
-
if (mentions(query, name))
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
for (const table of tables) {
|
|
122
|
-
const mark = table.options?.tenancy;
|
|
123
|
-
if (isGlobalMark(mark))
|
|
124
|
-
continue;
|
|
125
|
-
const sql = casing === "snake" ? snakeCase(table.name) : table.name;
|
|
126
|
-
if (mentions(query, sql) || mentions(query, table.name))
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
function readGlobal(name, tenancy) {
|
|
132
|
-
if (tenancy === undefined)
|
|
133
|
-
return;
|
|
134
|
-
if (!isGlobalMark(tenancy)) {
|
|
135
|
-
throw new OkmError2("OKM1020", `View ${name} tenancy must be global("reason").`, {
|
|
136
|
-
fix: { summary: 'Pass global("reason") from okmodel/tenancy, or omit tenancy.' }
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
return tenancy.reason;
|
|
140
|
-
}
|
|
141
|
-
function isGlobalMark(value) {
|
|
142
|
-
if (typeof value !== "object" || value === null)
|
|
143
|
-
return false;
|
|
144
|
-
const record = value;
|
|
145
|
-
return record.kind === "global" && typeof record.reason === "string" && record.reason.trim().length > 0;
|
|
146
|
-
}
|
|
147
|
-
function fieldName(column, tenancy) {
|
|
148
|
-
const field = camelCase(column);
|
|
149
|
-
if (tenancy !== undefined && (column === tenancy.key || field === tenancy.key))
|
|
150
|
-
return tenancy.key;
|
|
151
|
-
return field;
|
|
152
|
-
}
|
|
153
|
-
function camelCase(name) {
|
|
154
|
-
let out = "";
|
|
155
|
-
let upper = false;
|
|
156
|
-
for (const char of name) {
|
|
157
|
-
if (char === "_") {
|
|
158
|
-
upper = out.length > 0;
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
out += upper ? char.toUpperCase() : char;
|
|
162
|
-
upper = false;
|
|
163
|
-
}
|
|
164
|
-
return out;
|
|
165
|
-
}
|
|
166
|
-
function mentions(query, name) {
|
|
167
|
-
let pattern = '(^|[^A-Za-z0-9_])"?';
|
|
168
|
-
for (const char of name) {
|
|
169
|
-
if ("\\^$[]().*+?|{}".includes(char))
|
|
170
|
-
pattern += "\\";
|
|
171
|
-
pattern += char;
|
|
172
|
-
}
|
|
173
|
-
pattern += '"?(?![A-Za-z0-9_])';
|
|
174
|
-
return new RegExp(pattern).test(query);
|
|
175
|
-
}
|
|
176
|
-
function textValue(value) {
|
|
177
|
-
if (typeof value !== "string") {
|
|
178
|
-
throw new OkmError2("OKM1121", "A view column value must be text.", {
|
|
179
|
-
fix: { summary: "Pass a string." }
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
return value;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
16
|
// src/dialects/pg/view/index.ts
|
|
186
17
|
function view(name, options) {
|
|
187
18
|
const schema = options.schema ?? "public";
|
|
188
19
|
const columns = options.columns.map((column) => ({ name: column.name, dataType: column.type }));
|
|
189
20
|
const query = bodyText(options.query);
|
|
190
|
-
const bound = viewClient(name, options.columns, query, options.tenancy);
|
|
21
|
+
const bound = viewClient(name, options.columns, query, options.tenancy, "plain");
|
|
22
|
+
let securityInvoker = false;
|
|
191
23
|
return {
|
|
192
24
|
name,
|
|
193
25
|
schema,
|
|
194
|
-
|
|
26
|
+
"~kind": "view",
|
|
27
|
+
install(model, tenancy, tables, casing, scoped) {
|
|
28
|
+
bound.install(model, tenancy, tables, casing, scoped);
|
|
29
|
+
securityInvoker = tenancy?.strategy === "rls" && scoped.has(name);
|
|
30
|
+
},
|
|
195
31
|
hook: bound.hook,
|
|
196
32
|
contribute(peers, built) {
|
|
197
33
|
assertPeers(peers);
|
|
@@ -203,7 +39,8 @@ function view(name, options) {
|
|
|
203
39
|
name,
|
|
204
40
|
columns,
|
|
205
41
|
query,
|
|
206
|
-
provenance
|
|
42
|
+
provenance,
|
|
43
|
+
...securityInvoker ? { securityInvoker: true } : {}
|
|
207
44
|
})
|
|
208
45
|
];
|
|
209
46
|
}
|
|
@@ -213,7 +50,12 @@ function materializedView(name, options) {
|
|
|
213
50
|
const schema = options.schema ?? "public";
|
|
214
51
|
const columns = options.columns.map((column) => ({ name: column.name, dataType: column.type }));
|
|
215
52
|
const query = bodyText(options.query);
|
|
216
|
-
|
|
53
|
+
if (options.refresh !== undefined && options.refresh !== "concurrently") {
|
|
54
|
+
throw new OkmError2("OKM1120", `Materialized view ${name} refresh must be "concurrently".`, {
|
|
55
|
+
fix: { summary: 'Omit refresh, or pass refresh: "concurrently" with a unique index.' }
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const bound = viewClient(name, options.columns, query, options.tenancy, options.refresh === "concurrently" ? "concurrently" : "blocking");
|
|
217
59
|
const indexes = options.indexes ?? [];
|
|
218
60
|
if (options.refresh === "concurrently" && !indexes.some((index) => index.unique === true)) {
|
|
219
61
|
throw new OkmError2("OKM1822", `Materialized view ${name} refreshes concurrently and has no unique index.`, { fix: { summary: "Add a unique index, or refresh without CONCURRENTLY." } });
|
|
@@ -229,6 +71,7 @@ function materializedView(name, options) {
|
|
|
229
71
|
return {
|
|
230
72
|
name,
|
|
231
73
|
schema,
|
|
74
|
+
"~kind": "materialized",
|
|
232
75
|
install: bound.install,
|
|
233
76
|
hook: bound.hook,
|
|
234
77
|
contribute(peers, built) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `REFRESH MATERIALIZED VIEW` for one view handle.
|
|
3
|
+
*
|
|
4
|
+
* Loaded the first time `refresh()` runs. A featureless app, and an app that
|
|
5
|
+
* never calls it, do not import this module. The name is unqualified so the
|
|
6
|
+
* session `search_path` selects the schema, matching a view `find`.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Refreshes one materialized view on the primary.
|
|
10
|
+
*
|
|
11
|
+
* `CONCURRENTLY` when the declaration asked for it. The statement timeout is
|
|
12
|
+
* the client's, the same ceiling a write uses. A database failure is mapped
|
|
13
|
+
* and logged like any other statement.
|
|
14
|
+
*
|
|
15
|
+
* The refresh runs on a reserved primary connection with `app.unscoped` set
|
|
16
|
+
* in that same transaction. Under `FORCE ROW LEVEL SECURITY` the owner would
|
|
17
|
+
* otherwise refresh zero rows. `CONCURRENTLY` cannot run inside a transaction,
|
|
18
|
+
* so that form sets the session value and clears it before release.
|
|
19
|
+
*
|
|
20
|
+
* @param session - Pool, timeout, and logger from the client
|
|
21
|
+
* @param name - SQL name of the materialized view
|
|
22
|
+
* @param concurrently - True when the view declares `refresh: "concurrently"`
|
|
23
|
+
*/
|
|
24
|
+
export declare function refreshView(session: object, name: string, concurrently: boolean): Promise<void>;
|
package/dist/runtime/batch.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { type Session } from "./client.js";
|
|
|
12
12
|
* Runs write handles as one atomic unit.
|
|
13
13
|
*
|
|
14
14
|
* @param session - Client session
|
|
15
|
-
* @param ops - Write handles: `insert`, `update`, `delete`, `archive`. A `restore`,
|
|
15
|
+
* @param ops - Write handles: `insert`, `update`, `delete`, `archive`. A `restore`, a write with `expect`, or `refresh()` is OKM1121 (D183, D239)
|
|
16
16
|
* @param options - `signal` and `timeout` for the whole batch
|
|
17
17
|
* @param replica - Set by `.replica()`. A batch needs the primary (OKM1840)
|
|
18
18
|
* @returns One result per operation, in order
|
|
@@ -18,10 +18,10 @@ export type ConflictPlan = {
|
|
|
18
18
|
* @param table - Target table
|
|
19
19
|
* @param value - The option the caller passed
|
|
20
20
|
* @param allow - Guarded fields this write may set
|
|
21
|
-
* @param tenantKey - The tenant key
|
|
21
|
+
* @param tenantKey - The tenant key, or every tenant key when the schema has several. A unique that includes them matches when `on` names the other columns. The target keeps the keys, in the unique's order. Naming a key is OKM1104.
|
|
22
22
|
* @returns The plan, or `undefined` for the default `"error"`
|
|
23
23
|
*/
|
|
24
|
-
export declare function readConflict(table: Indexed, value: unknown, allow?: ReadonlySet<string>, tenantKey?: string): ConflictPlan | undefined;
|
|
24
|
+
export declare function readConflict(table: Indexed, value: unknown, allow?: ReadonlySet<string>, tenantKey?: string | readonly string[]): ConflictPlan | undefined;
|
|
25
25
|
/**
|
|
26
26
|
* Appends the conflict clause, or wraps a first-or-create insert.
|
|
27
27
|
*
|
package/dist/runtime/drift.d.ts
CHANGED
|
@@ -29,3 +29,12 @@ export declare function assertCompatible(pool: DriverPool, schema: QuerySchema,
|
|
|
29
29
|
readonly catalog?: CatalogArtifact;
|
|
30
30
|
readonly catalogDir?: string;
|
|
31
31
|
}, options: ExecuteOptions | undefined): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Directory of `catalog.hash` and `catalog.json`.
|
|
34
|
+
*
|
|
35
|
+
* A trailing `/` or `\` is removed so the joined file name is one path.
|
|
36
|
+
*
|
|
37
|
+
* @param catalogDir - Directory the caller passed, or the default `.okm`
|
|
38
|
+
* @returns The directory, without a trailing slash
|
|
39
|
+
*/
|
|
40
|
+
export declare function artifactDir(catalogDir: string | undefined): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refuses a positive timeout on a driver that cannot cancel.
|
|
3
|
+
*
|
|
4
|
+
* `tx({ timeout })` and `batch({ timeout })` load this with the call. The
|
|
5
|
+
* connect graph does not. The message stays the one {@link noTimeout} throws.
|
|
6
|
+
*/
|
|
7
|
+
import type { DriverPool } from "../contracts/driver.js";
|
|
8
|
+
/**
|
|
9
|
+
* Throws OKM1120 when `timeout` is positive and the driver cannot cancel.
|
|
10
|
+
*
|
|
11
|
+
* @param pool - Driver the call will use
|
|
12
|
+
* @param timeout - Milliseconds, when the caller passed one
|
|
13
|
+
*/
|
|
14
|
+
export declare function refuseUncancellableTimeout(pool: DriverPool, timeout: number | undefined): Promise<void>;
|
package/dist/runtime/pg/bun.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import"../../shared/8dqhth8c.js";
|
|
1
2
|
import {
|
|
2
3
|
DriverError2
|
|
3
4
|
} from "../../shared/31vm914h.js";
|
|
4
5
|
import {
|
|
5
6
|
open5
|
|
6
|
-
} from "../../shared/
|
|
7
|
+
} from "../../shared/32cnm7kn.js";
|
|
7
8
|
import {
|
|
8
9
|
BUNSQL_CAPABILITIES,
|
|
9
10
|
readCapability2,
|
|
@@ -11,12 +12,12 @@ import {
|
|
|
11
12
|
} from "../../shared/cgbamx3e.js";
|
|
12
13
|
import {
|
|
13
14
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
15
|
+
} from "../../shared/j60w0dvr.js";
|
|
15
16
|
|
|
16
17
|
// src/runtime/pg/bun.ts
|
|
17
18
|
function connect(target, options) {
|
|
18
19
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
20
|
+
return import("../../shared/929h19xp.js").then((mod) => mod.default(target, options, open5));
|
|
20
21
|
}
|
|
21
22
|
const owned = !isPool(target);
|
|
22
23
|
const pool = isPool(target) ? target : open5({
|
package/dist/runtime/pg/pg.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open4
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/1z04fa85.js";
|
|
7
7
|
import {
|
|
8
8
|
NODE_POSTGRES_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/j60w0dvr.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/pg.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
18
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
19
|
+
return import("../../shared/929h19xp.js").then((mod) => mod.default(target, options, open4));
|
|
20
20
|
}
|
|
21
21
|
const owned = !isPool(target);
|
|
22
22
|
const pool = isPool(target) ? target : open4({
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import"../../shared/8dqhth8c.js";
|
|
1
2
|
import {
|
|
2
3
|
DriverError2
|
|
3
4
|
} from "../../shared/31vm914h.js";
|
|
4
5
|
import {
|
|
5
6
|
open3
|
|
6
|
-
} from "../../shared/
|
|
7
|
+
} from "../../shared/5j36z8dn.js";
|
|
7
8
|
import {
|
|
8
9
|
PGLITE_CAPABILITIES,
|
|
9
10
|
readCapability2,
|
|
@@ -11,12 +12,12 @@ import {
|
|
|
11
12
|
} from "../../shared/cgbamx3e.js";
|
|
12
13
|
import {
|
|
13
14
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
15
|
+
} from "../../shared/j60w0dvr.js";
|
|
15
16
|
|
|
16
17
|
// src/runtime/pg/pglite.ts
|
|
17
18
|
async function connect(target, options) {
|
|
18
19
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
20
|
+
return import("../../shared/929h19xp.js").then((mod) => mod.default(target, options, open3));
|
|
20
21
|
}
|
|
21
22
|
const pool = isPool(target) ? target : await open3({
|
|
22
23
|
...target !== undefined ? { dataDir: target } : {},
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open2
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/wkme6tep.js";
|
|
7
7
|
import {
|
|
8
8
|
POSTGRESJS_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/j60w0dvr.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/postgresjs.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
18
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
19
|
+
return import("../../shared/929h19xp.js").then((mod) => mod.default(target, options, open2));
|
|
20
20
|
}
|
|
21
21
|
const owned = !isPool(target);
|
|
22
22
|
const pool = isPool(target) ? target : open2({
|
package/dist/runtime/plan.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type RouteConstraint = "auto" | "primary" | "replica";
|
|
|
18
18
|
*/
|
|
19
19
|
export type CallScope = {
|
|
20
20
|
readonly value: string;
|
|
21
|
+
readonly values?: Readonly<Record<string, string>>;
|
|
21
22
|
} | {
|
|
22
23
|
readonly unscoped: string;
|
|
23
24
|
};
|
|
@@ -249,6 +250,15 @@ export declare function emitJoin(sink: Sink, parent: string, child: string, rela
|
|
|
249
250
|
export declare function emitWhere(schema: QuerySchema, table: Indexed, where: unknown, sink: Sink, alias: string, depth: number, appended?: boolean, extra?: Keyset): void;
|
|
250
251
|
export declare function emitOrder(table: Indexed, orderBy: unknown, sink: Sink, alias: string): void;
|
|
251
252
|
export declare function emitPrimaryOrder(table: Indexed, sink: Sink, alias: string): void;
|
|
253
|
+
/**
|
|
254
|
+
* Refuses a hidden field in `where` or `orderBy`.
|
|
255
|
+
*
|
|
256
|
+
* `"filter"` is `hidden({ filterable: true })` and is allowed here.
|
|
257
|
+
* Aggregate loads this on its first call and applies it before the groupBy rule.
|
|
258
|
+
*
|
|
259
|
+
* @param column - The field the caller named
|
|
260
|
+
*/
|
|
261
|
+
export declare function refuseHidden(column: ColumnModel): void;
|
|
252
262
|
export type ParsedInclude = {
|
|
253
263
|
readonly name: string;
|
|
254
264
|
readonly relation: RelationModel;
|
|
@@ -289,18 +299,15 @@ export declare function quote(name: string): string;
|
|
|
289
299
|
export declare function list(names: readonly string[]): string;
|
|
290
300
|
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
291
301
|
/**
|
|
292
|
-
*
|
|
302
|
+
* Throws OKM1121 for an `or()` that is not an array, or for an empty branch.
|
|
293
303
|
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* It enters the where object's own keys, `and`, `or`, and `not` when `not` is
|
|
297
|
-
* the where itself. An `or()` branch with no predicate is OKM1121. `or([])`
|
|
298
|
-
* matches nothing.
|
|
304
|
+
* The write and archive predicate walk uses the same throw. It lives here
|
|
305
|
+
* because the read planner throws it too, and that planner stays in this module.
|
|
299
306
|
*
|
|
300
|
-
* @param
|
|
301
|
-
* @returns
|
|
307
|
+
* @param empty - `true` when a branch has no predicate
|
|
308
|
+
* @returns Never
|
|
302
309
|
*/
|
|
303
|
-
export declare function
|
|
310
|
+
export declare function orFail(empty: boolean): never;
|
|
304
311
|
/**
|
|
305
312
|
* Records the fix text for a code thrown from a chunk that loads on first use.
|
|
306
313
|
*
|
|
@@ -316,6 +323,7 @@ export declare function registerFailFix(code: QueryCode, summary: string): void;
|
|
|
316
323
|
*
|
|
317
324
|
* @param code - Spec code
|
|
318
325
|
* @param message - What failed
|
|
326
|
+
* @param fix - Fix sentence for this call. Omitted, the sentence registered for `code` is used
|
|
319
327
|
*/
|
|
320
|
-
export declare function fail(code: QueryCode, message: string): never;
|
|
328
|
+
export declare function fail(code: QueryCode, message: string, fix?: string): never;
|
|
321
329
|
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a `where` constrains a row.
|
|
3
|
+
*
|
|
4
|
+
* Write and archive load this module. A read does not. The walk is the same
|
|
5
|
+
* one those paths used when it lived in the planner.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Whether `where` constrains a row.
|
|
9
|
+
*
|
|
10
|
+
* A field value is a leaf. Anything other than `undefined` counts, including
|
|
11
|
+
* `null`, objects, arrays, and operators. The walk does not enter a field value.
|
|
12
|
+
* It enters the where object's own keys, `and`, `or`, and `not` when `not` is
|
|
13
|
+
* the where itself. An `or()` branch with no predicate is OKM1121. `or([])`
|
|
14
|
+
* matches nothing.
|
|
15
|
+
*
|
|
16
|
+
* @param where - Caller filter, or one `and` / `or` / `not` operand
|
|
17
|
+
* @returns `false` when the filter matches every row
|
|
18
|
+
*/
|
|
19
|
+
export declare function effectivePredicate(where: unknown): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composite tenancy (`compositeTenancy()`).
|
|
3
|
+
*
|
|
4
|
+
* Every tenant table carries the key list, in that order. A column-only app
|
|
5
|
+
* does not import this file. `via()` is a separate import: this file calls a
|
|
6
|
+
* table's own `rewrite` and does not load the path compiler.
|
|
7
|
+
*/
|
|
8
|
+
import type { ColumnTenancy } from "../../dialects/pg/tenancy.js";
|
|
9
|
+
/**
|
|
10
|
+
* Composite tenancy for `schema({ tenancy })`.
|
|
11
|
+
*
|
|
12
|
+
* Every table gains each key unless it passes `global("reason")` or `via()`.
|
|
13
|
+
* The keys are guarded uuids, in this order. Insert fills them from `for()`.
|
|
14
|
+
* Reads and writes filter on every key.
|
|
15
|
+
*
|
|
16
|
+
* @typeParam Keys - Field names, at least one
|
|
17
|
+
* @param input - The key list and `uuid`
|
|
18
|
+
* @returns The object `schema()` applies
|
|
19
|
+
*/
|
|
20
|
+
export declare function compositeTenancy<const Keys extends readonly [string, ...string[]]>(input: {
|
|
21
|
+
readonly key: Keys;
|
|
22
|
+
readonly type: "uuid";
|
|
23
|
+
}): ColumnTenancy & {
|
|
24
|
+
readonly key: Keys[number];
|
|
25
|
+
readonly keys: Keys;
|
|
26
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a table tenancy `rewrite` receives.
|
|
3
|
+
*
|
|
4
|
+
* `columnTenancy()` and `compositeTenancy()` pass it. `via()` reads it.
|
|
5
|
+
* This file is types only, so it is not in a bundle.
|
|
6
|
+
*/
|
|
7
|
+
import type { AnyTable } from "../../dialects/pg/table.js";
|
|
8
|
+
import type { ColumnTenancy } from "../../dialects/pg/tenancy.js";
|
|
9
|
+
/** Context for one table whose tenancy mark carries `rewrite`. */
|
|
10
|
+
export type TableRewriteContext = {
|
|
11
|
+
readonly tables: readonly AnyTable[];
|
|
12
|
+
readonly keys: readonly string[];
|
|
13
|
+
readonly encodes: readonly ((value: string) => string)[];
|
|
14
|
+
readonly api: ColumnTenancy;
|
|
15
|
+
readonly extras: Map<string, readonly string[]>;
|
|
16
|
+
};
|
|
@@ -22,16 +22,20 @@ export declare function global(reason: string): {
|
|
|
22
22
|
/**
|
|
23
23
|
* Column tenancy for `schema({ tenancy })`.
|
|
24
24
|
*
|
|
25
|
-
* Every table gains `key` unless it passes `global("reason")
|
|
26
|
-
* guarded uuid. Insert fills it from `for()`. Reads and writes
|
|
25
|
+
* Every table gains `key` unless it passes `global("reason")` or `via()`.
|
|
26
|
+
* The key is a guarded uuid. Insert fills it from `for()`. Reads and writes
|
|
27
|
+
* filter on it. A list of keys is `compositeTenancy()`.
|
|
27
28
|
*
|
|
28
29
|
* @typeParam Key - Field name of the tenant key
|
|
29
30
|
* @param input - Field name and `uuid`
|
|
30
31
|
* @returns The object `schema()` applies
|
|
31
32
|
*/
|
|
32
|
-
export declare function columnTenancy<const Key
|
|
33
|
-
readonly key: Key;
|
|
33
|
+
export declare function columnTenancy<const Key>(input: {
|
|
34
|
+
readonly key: Key extends readonly unknown[] ? "columnTenancy() takes one key. Use compositeTenancy()." : Key extends string ? Key : "columnTenancy() key must be a field name.";
|
|
34
35
|
readonly type: "uuid";
|
|
35
36
|
}): ColumnTenancy & {
|
|
36
|
-
readonly key: Key;
|
|
37
|
+
readonly key: Key extends string ? Key : string;
|
|
37
38
|
};
|
|
39
|
+
export { compositeTenancy } from "./composite.js";
|
|
40
|
+
export { via } from "./via.js";
|
|
41
|
+
export { RlsRoleError, rlsTenancy, type RlsRoleReason } from "./rls.js";
|