okmodel 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/dialects/pg/filter-parse.d.ts +8 -2
- package/dist/dialects/pg/fn/index.js +8 -0
- package/dist/dialects/pg/index.js +8 -2
- package/dist/dialects/pg/ops/or.d.ts +1 -1
- package/dist/dialects/pg/temporal.d.ts +5 -76
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/runtime/client.d.ts +6 -1
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/pg/bun.js +5 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.js +5 -5
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +13 -0
- package/dist/runtime/tenancy/index.js +1 -1
- package/dist/runtime/traits/index.js +4 -4
- package/dist/runtime/validate/index.js +3 -3
- package/dist/shared/{ckjbyrt9.js → 0t22wwh1.js} +5 -9
- package/dist/shared/{jdgqqx31.js → 2pqx26h8.js} +23 -8
- package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
- package/dist/shared/{9tgmr1gh.js → 32zqc1dw.js} +18 -7
- package/dist/shared/{47xzb9fc.js → 47x8x9ze.js} +1 -1
- package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
- package/dist/shared/{s6gqfn5j.js → 51mvgj8w.js} +27 -3
- package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
- package/dist/shared/{3p4b1fg0.js → 5enne4ma.js} +1 -1
- package/dist/shared/{bzsjtd7c.js → 6mnp99hx.js} +7 -6
- package/dist/shared/{ykv7wh5b.js → 6qd27mx0.js} +2 -2
- package/dist/shared/{h4nqvjkp.js → 6rk2gen5.js} +2 -2
- package/dist/shared/{r73pt594.js → 7zwwyh0v.js} +32 -10
- package/dist/shared/{fa9vt245.js → 87jvvhnt.js} +2 -2
- package/dist/shared/{c8aghh05.js → 8rsy3hxz.js} +7 -1
- package/dist/shared/{6p5k20sm.js → 96qcj21c.js} +3 -3
- package/dist/shared/{xsq7v6wp.js → aj2qxyhj.js} +2 -2
- package/dist/shared/{5vdm4sgp.js → caw8b9d8.js} +4 -4
- package/dist/shared/{xhh1srw3.js → cctw17hj.js} +23 -8
- package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
- package/dist/shared/{tq9afp8d.js → cr74e96e.js} +1 -1
- package/dist/shared/{b066g80h.js → efmy2gcg.js} +2 -2
- package/dist/shared/{gdh9mrtp.js → f5cw5q5r.js} +2 -2
- package/dist/shared/{ayz64vzj.js → ga3sfy93.js} +357 -3
- package/dist/shared/{qgvt8nx1.js → gbtcc2d7.js} +44 -3
- package/dist/shared/{kdkxh3kb.js → gde73es6.js} +5 -7
- package/dist/shared/{bt9sfq0z.js → hf22e0wt.js} +51 -17
- package/dist/shared/{990a291j.js → janx09m5.js} +6 -5
- package/dist/shared/{4ef7mmqf.js → jwtxdj06.js} +5 -5
- package/dist/shared/{sf8m6tfy.js → k8v5v5wj.js} +3 -3
- package/dist/shared/{r6pj4fq2.js → kfjp0gck.js} +2 -2
- package/dist/shared/{wqem4jed.js → krxx77g0.js} +7 -7
- package/dist/shared/{h8ne16fq.js → nkaxvt9q.js} +1 -1
- package/dist/shared/{jsd07prz.js → ntneex2a.js} +1 -1
- package/dist/shared/{nkc9sfqb.js → nxdp2ze3.js} +40 -4
- package/dist/shared/{tbszx8mz.js → pf0d8f77.js} +1 -1
- package/dist/shared/{qy9rdq0g.js → ps7a6h14.js} +6 -6
- package/dist/shared/{rasvvzgz.js → q58y17hy.js} +5 -5
- package/dist/shared/{p7pfx624.js → qm7cdtvr.js} +22 -9
- package/dist/shared/{xdpj5kkm.js → qv2ydck9.js} +149 -209
- package/dist/shared/{k7cc9nzk.js → r2sp8hrc.js} +6 -3
- package/dist/shared/{fb00y8fp.js → r8x5qhd7.js} +5 -5
- package/dist/shared/{fyqkk1m0.js → sdc7r2ww.js} +6 -5
- package/dist/shared/{wxn4b7pp.js → sycnx8gt.js} +42 -5
- package/dist/shared/{dxjp14rk.js → tm5ab8we.js} +2 -2
- package/dist/shared/{g516zdsb.js → v36c5g6p.js} +78 -19
- package/dist/shared/wq9n6pwr.js +139 -0
- package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
- package/dist/shared/{922qbgnw.js → zqrnhwsq.js} +3 -3
- package/dist/tooling/cli.js +68 -21
- package/dist/tooling/migrate/commands.d.ts +1 -2
- package/dist/tooling/migrate/drift.d.ts +1 -1
- package/dist/tooling/migrate/estimate.d.ts +14 -1
- package/dist/tooling/migrate/index.js +8 -7
- package/dist/tooling/migrate/lint.d.ts +3 -3
- package/dist/tooling/migrate/plan.d.ts +7 -3
- package/dist/tooling/migrate/policy.d.ts +11 -0
- package/dist/tooling/migrate/sql-lex.d.ts +22 -0
- package/dist/tooling/testing/factories.d.ts +10 -0
- package/dist/tooling/testing/index.js +1 -1
- package/dist/tooling/testing/isolation.d.ts +4 -3
- package/package.json +6 -5
- package/dist/shared/0v1g424p.js +0 -26
package/README.md
CHANGED
|
@@ -80,9 +80,11 @@ bun add okmodel @electric-sql/pglite
|
|
|
80
80
|
|
|
81
81
|
Bun.sql needs no extra package: `import { connect } from "okmodel/pg/bun"`. okmodel has no runtime dependencies. Each installed driver is an optional peer.
|
|
82
82
|
|
|
83
|
+
The `okm` bin's shebang is node, so `bunx okm` runs it with Node even inside a Bun project. Run `bun --bun okm` when the command must use the Bun runtime (Bun.sql runs only there). A `.ts` config file under plain Node needs Node 22.18 or newer for type stripping.
|
|
84
|
+
|
|
83
85
|
## Quickstart
|
|
84
86
|
|
|
85
|
-
This builds two tables, applies them, and runs one script. The script writes an author and a note, then reads the note with its author. `DATABASE_URL` is a direct Postgres URL, not a pooler.
|
|
87
|
+
This builds two tables, applies them, and runs one script. The script writes an author and a note, then reads the note with its author. `DATABASE_URL` is a direct Postgres URL, not a pooler. Port `6432` and port `6543` count as a pooler. Apply, seed, and check also refuse when the backend pid changes between two statements (OKM1854), unless `--allow-pooler` is set.
|
|
86
88
|
|
|
87
89
|
### Configure
|
|
88
90
|
|
|
@@ -373,7 +375,7 @@ if (!(await db.notes.exists({ where: { id: note.id } }))) {
|
|
|
373
375
|
|
|
374
376
|
### Update
|
|
375
377
|
|
|
376
|
-
`update` changes the columns in `set` on the rows that match `where`. A
|
|
378
|
+
`update` changes the columns in `set` on the rows that match `where`. A write with no effective predicate, including undefined values, is OKM1102. An empty `or()` branch is OKM1121. `.all(reason)` is the form that means every row.
|
|
377
379
|
|
|
378
380
|
```ts
|
|
379
381
|
// where picks the row. set names the new title.
|
|
@@ -382,7 +384,7 @@ await db.notes.update({ where: { id: note.id }, set: { title: "next" } });
|
|
|
382
384
|
|
|
383
385
|
### Delete
|
|
384
386
|
|
|
385
|
-
`delete` removes the rows that match `where`. A
|
|
387
|
+
`delete` removes the rows that match `where`. A write with no effective predicate, including undefined values, is OKM1102. An empty `or()` branch is OKM1121. `.all(reason)` is the form that means every row.
|
|
386
388
|
|
|
387
389
|
```ts
|
|
388
390
|
// where picks the row. Without it the call is refused.
|
|
@@ -828,7 +830,7 @@ export const app = schema({
|
|
|
828
830
|
|
|
829
831
|
### Views
|
|
830
832
|
|
|
831
|
-
A view is a saved query. You give it the SQL and the columns that query returns. `db.views.active.find({ limit: 20 })` reads `active`. That handle has no insert or update. There is no query-builder form yet. `okm check` reprints the query on the connected server before it compares, so a difference that is only how that server prints the query is not drift. A materialized view that refreshes while people are reading it needs a unique index, or the declaration is OKM1822. See [known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md).
|
|
833
|
+
A view is a saved query. You give it the SQL and the columns that query returns. `db.views.active.find({ limit: 20 })` reads `active`. That handle has no insert or update. View handles are camelCased: a view named `active_projects` reads as `db.views.activeProjects`. There is no query-builder form yet. `okm check` reprints the query on the connected server before it compares, so a difference that is only how that server prints the query is not drift. A materialized view refreshes with `REFRESH MATERIALIZED VIEW`: the plan populates it with a plain refresh first (Postgres rejects `CONCURRENTLY` on an empty view), then refreshes concurrently when the declaration sets `refresh: "concurrently"`. A materialized view that refreshes while people are reading it needs a unique index, or the declaration is OKM1822. See [known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md).
|
|
832
834
|
|
|
833
835
|
`views.ts`:
|
|
834
836
|
|
|
@@ -945,7 +947,7 @@ update "public"."notes" set "title" = 'noted' where "title" = 'hello' and ("id"
|
|
|
945
947
|
|
|
946
948
|
### Testing
|
|
947
949
|
|
|
948
|
-
`okmodel/testing` opens a real pool. `factories` insert rows, `expectQueries` counts statements, and `isolation()` checks that tenant A cannot see tenant B. `okm seed <file>` calls the file's default export with that harness. The target must already be migrated. A protected target is refused unless `--allow-protected`.
|
|
950
|
+
`okmodel/testing` opens a real pool. `factories` insert rows, `expectQueries` counts statements, and `isolation()` checks that tenant A cannot see the row it inserted for tenant B. Each call uses a new pair of tenant ids, deletes what it inserted, and names a factory that is missing. `okm seed <file>` calls the file's default export with that harness. The target must already be migrated. A protected target is refused unless `--allow-protected`.
|
|
949
951
|
|
|
950
952
|
`factory.ts`:
|
|
951
953
|
|
|
@@ -1071,7 +1073,7 @@ The worked example is a project tracker: workspaces as tenants, archive, a funct
|
|
|
1071
1073
|
|
|
1072
1074
|
### Startup
|
|
1073
1075
|
|
|
1074
|
-
`connect()` compares the app with `okm_history`. A database that is ahead by expand migrations still opens. Ahead by a contract migration, or behind the app, is OKM1520 and names the migration. `okm migrate status` prints the same states, plus `failed at step N (resume with okm migrate apply)
|
|
1076
|
+
`connect()` compares the app with `okm_history`. A database that is ahead by expand migrations still opens. Ahead by a contract migration, or behind the app, is OKM1520 and names the migration. `okm migrate status` prints the same states, plus `failed at step N (resume with okm migrate apply)`, where N is the stored step index. Apply's own `failed at step N` counts from 1, the same number the linter prints.
|
|
1075
1077
|
|
|
1076
1078
|
### Protected targets
|
|
1077
1079
|
|
|
@@ -1144,6 +1146,7 @@ Status is on the [board](https://github.com/users/omqkhafi/projects/1). Each rel
|
|
|
1144
1146
|
- [x] [0.3](https://github.com/omqkhafi/okmodel/milestone/3) — Extensions, domains, functions, triggers, views, roles, and grants.
|
|
1145
1147
|
- [x] [0.4](https://github.com/omqkhafi/okmodel/milestone/4) — Safer migration plans, backfill, drift checks, provisioning, reference data, and a testing package.
|
|
1146
1148
|
- [x] [0.5](https://github.com/omqkhafi/okmodel/milestone/5) — A primary with replicas, read routing, and a reference app.
|
|
1149
|
+
- [ ] [0.5.1](https://github.com/omqkhafi/okmodel/milestone/7) — QA fixes for 0.5.0.
|
|
1147
1150
|
|
|
1148
1151
|
`okmodel/internal` has no stability promise. Names on that subpath can change or disappear in any release.
|
|
1149
1152
|
|
|
@@ -3,13 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Loaded the first time `parse()` is called. `filters()` validates the spec
|
|
5
5
|
* before this module exists.
|
|
6
|
+
*
|
|
7
|
+
* A request key is equality when the value is a scalar and `eq` is allowed.
|
|
8
|
+
* An object value names operators: `eq`, `in` (`inList`), `notIn`, `lt`,
|
|
9
|
+
* `lte`, `gt`, `gte`, `between`, `startsWith`, `endsWith`, `contains`,
|
|
10
|
+
* `like`, and `ilike`. `sort` is a field name from the sort list.
|
|
6
11
|
*/
|
|
7
12
|
import type { ParsedFilters } from "./table.js";
|
|
8
13
|
/**
|
|
9
14
|
* Reads one request object.
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
16
|
+
* Lookups use own properties, so `constructor`, `__proto__`, `toString`, and
|
|
17
|
+
* `hasOwnProperty` are ordinary keys. A key that is not in `allow` is OKM1123.
|
|
18
|
+
* `sort` is the exception.
|
|
13
19
|
*
|
|
14
20
|
* @param allow - Fields and the operators each one accepts
|
|
15
21
|
* @param sort - Fields a caller may sort by
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
staticNamespace2
|
|
7
7
|
} from "../../../shared/t4tbsy9h.js";
|
|
8
|
+
import {
|
|
9
|
+
assertIdentifier2
|
|
10
|
+
} from "../../../shared/nfzc5z0w.js";
|
|
8
11
|
import {
|
|
9
12
|
OkmError2
|
|
10
13
|
} from "../../../shared/52szzakm.js";
|
|
@@ -26,6 +29,11 @@ function fn(name, options) {
|
|
|
26
29
|
fix: { summary: "Set search_path on the function to the schemas it is allowed to see." }
|
|
27
30
|
});
|
|
28
31
|
}
|
|
32
|
+
if (options.searchPath !== undefined && options.searchPath.trim().length > 0) {
|
|
33
|
+
for (const part of options.searchPath.split(",")) {
|
|
34
|
+
assertIdentifier2(part.trim(), `function ${name} search_path`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
29
37
|
const argTypes = (options.arguments ?? []).map((argument) => argument.type);
|
|
30
38
|
const schema = options.schema ?? "public";
|
|
31
39
|
return {
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
many2,
|
|
21
21
|
manyThrough2,
|
|
22
22
|
schema2
|
|
23
|
-
} from "../../shared/
|
|
23
|
+
} from "../../shared/5enne4ma.js";
|
|
24
24
|
import {
|
|
25
25
|
domainType
|
|
26
26
|
} from "../../shared/g7ez901n.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
table2,
|
|
33
33
|
index2,
|
|
34
34
|
sql2
|
|
35
|
-
} from "../../shared/
|
|
35
|
+
} from "../../shared/ntneex2a.js";
|
|
36
36
|
import {
|
|
37
37
|
text2,
|
|
38
38
|
varchar2,
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
tag
|
|
60
60
|
} from "../../shared/cn0n68ft.js";
|
|
61
61
|
import {
|
|
62
|
+
OkmError2,
|
|
62
63
|
catalogError2
|
|
63
64
|
} from "../../shared/52szzakm.js";
|
|
64
65
|
var __defProp = Object.defineProperty;
|
|
@@ -909,6 +910,11 @@ function notIn(values) {
|
|
|
909
910
|
}
|
|
910
911
|
// src/dialects/pg/ops/or.ts
|
|
911
912
|
function or(branches) {
|
|
913
|
+
if (arguments.length !== 1 || !Array.isArray(branches)) {
|
|
914
|
+
throw new OkmError2("OKM1121", "Pass an array: or([a, b]).", {
|
|
915
|
+
fix: { summary: "Pass an array: or([a, b])." }
|
|
916
|
+
});
|
|
917
|
+
}
|
|
912
918
|
return tag("or", branches);
|
|
913
919
|
}
|
|
914
920
|
// src/dialects/pg/ops/overlaps.ts
|
|
@@ -3,7 +3,7 @@ import { type Or } from "../operators.js";
|
|
|
3
3
|
* Disjunction of where objects.
|
|
4
4
|
*
|
|
5
5
|
* @typeParam V - One branch
|
|
6
|
-
* @param branches - Where objects, or-ed
|
|
6
|
+
* @param branches - Where objects, or-ed. One array: `or([a, b])`
|
|
7
7
|
* @returns A tagged operator
|
|
8
8
|
*/
|
|
9
9
|
export declare function or<const V>(branches: readonly V[]): Or<V>;
|
|
@@ -114,100 +114,29 @@ export declare function decodeDuration(wire: string): Temporal.Duration;
|
|
|
114
114
|
*/
|
|
115
115
|
export declare function intervalFields(fields: string): string;
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
118
|
-
* TypeScript
|
|
117
|
+
* Empty names so `Temporal.Instant` and the other codec types merge with
|
|
118
|
+
* TypeScript's Temporal lib and with `temporal-polyfill`. Method signatures
|
|
119
|
+
* live in `temporal.local.d.ts` for this repository's typecheck only. They
|
|
120
|
+
* are not shipped: a second `toString` or `var Temporal` conflicts with those
|
|
121
|
+
* libraries (QA-L2).
|
|
119
122
|
*/
|
|
120
123
|
declare global {
|
|
121
124
|
/** Instant, plain date-time, date, time, and duration. */
|
|
122
125
|
namespace Temporal {
|
|
123
126
|
/** UTC instant. */
|
|
124
127
|
interface Instant {
|
|
125
|
-
/**
|
|
126
|
-
* @param options - Fractional digits to keep
|
|
127
|
-
* @returns ISO-8601 text
|
|
128
|
-
*/
|
|
129
|
-
toString(options?: {
|
|
130
|
-
readonly fractionalSecondDigits?: number;
|
|
131
|
-
}): string;
|
|
132
128
|
}
|
|
133
129
|
/** Date and time without a zone. */
|
|
134
130
|
interface PlainDateTime {
|
|
135
|
-
/**
|
|
136
|
-
* @param options - Fractional digits to keep
|
|
137
|
-
* @returns ISO-8601 text
|
|
138
|
-
*/
|
|
139
|
-
toString(options?: {
|
|
140
|
-
readonly fractionalSecondDigits?: number;
|
|
141
|
-
}): string;
|
|
142
131
|
}
|
|
143
132
|
/** Calendar date. */
|
|
144
133
|
interface PlainDate {
|
|
145
|
-
/**
|
|
146
|
-
* @returns `YYYY-MM-DD`
|
|
147
|
-
*/
|
|
148
|
-
toString(): string;
|
|
149
|
-
/**
|
|
150
|
-
* @param duration - Days to add
|
|
151
|
-
* @returns A later or earlier date
|
|
152
|
-
*/
|
|
153
|
-
add(duration: {
|
|
154
|
-
readonly days: number;
|
|
155
|
-
}): Temporal.PlainDate;
|
|
156
134
|
}
|
|
157
135
|
/** Time of day. */
|
|
158
136
|
interface PlainTime {
|
|
159
|
-
/**
|
|
160
|
-
* @param options - Fractional digits to keep
|
|
161
|
-
* @returns Time text
|
|
162
|
-
*/
|
|
163
|
-
toString(options?: {
|
|
164
|
-
readonly fractionalSecondDigits?: number;
|
|
165
|
-
}): string;
|
|
166
137
|
}
|
|
167
138
|
/** ISO-8601 duration. */
|
|
168
139
|
interface Duration {
|
|
169
|
-
/**
|
|
170
|
-
* @returns ISO-8601 duration text
|
|
171
|
-
*/
|
|
172
|
-
toString(): string;
|
|
173
140
|
}
|
|
174
141
|
}
|
|
175
|
-
/** Temporal constructors used by the codecs. */
|
|
176
|
-
var Temporal: {
|
|
177
|
-
readonly Instant: {
|
|
178
|
-
/**
|
|
179
|
-
* @param item - ISO-8601 instant
|
|
180
|
-
* @returns An instant
|
|
181
|
-
*/
|
|
182
|
-
from(item: string): Temporal.Instant;
|
|
183
|
-
};
|
|
184
|
-
readonly PlainDateTime: {
|
|
185
|
-
/**
|
|
186
|
-
* @param item - ISO-8601 date-time
|
|
187
|
-
* @returns A plain date-time
|
|
188
|
-
*/
|
|
189
|
-
from(item: string): Temporal.PlainDateTime;
|
|
190
|
-
};
|
|
191
|
-
readonly PlainDate: {
|
|
192
|
-
/**
|
|
193
|
-
* @param item - `YYYY-MM-DD`
|
|
194
|
-
* @returns A date
|
|
195
|
-
*/
|
|
196
|
-
from(item: string): Temporal.PlainDate;
|
|
197
|
-
};
|
|
198
|
-
readonly PlainTime: {
|
|
199
|
-
/**
|
|
200
|
-
* @param item - Time text
|
|
201
|
-
* @returns A time
|
|
202
|
-
*/
|
|
203
|
-
from(item: string): Temporal.PlainTime;
|
|
204
|
-
};
|
|
205
|
-
readonly Duration: {
|
|
206
|
-
/**
|
|
207
|
-
* @param item - ISO-8601 duration, or numeric fields
|
|
208
|
-
* @returns A duration
|
|
209
|
-
*/
|
|
210
|
-
from(item: string | Readonly<Record<string, number>>): Temporal.Duration;
|
|
211
|
-
};
|
|
212
|
-
};
|
|
213
142
|
}
|
package/dist/runtime/client.d.ts
CHANGED
|
@@ -37,9 +37,14 @@ export type Session = {
|
|
|
37
37
|
};
|
|
38
38
|
/** Tenant value or an unscoped reason. Absent on the root client. */
|
|
39
39
|
readonly scope?: CallScope;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Shared close. `for()` and `unscoped()` reuse the same promise.
|
|
42
|
+
*
|
|
43
|
+
* `early` is set when `close()` runs before `connected` settles (QA-M5).
|
|
44
|
+
*/
|
|
41
45
|
readonly closing: {
|
|
42
46
|
current: Promise<void> | undefined;
|
|
47
|
+
early: boolean;
|
|
43
48
|
};
|
|
44
49
|
};
|
|
45
50
|
/** Per-call modifiers of a read. */
|
|
@@ -18,9 +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 on a tenant schema, which every unique includes
|
|
21
22
|
* @returns The plan, or `undefined` for the default `"error"`
|
|
22
23
|
*/
|
|
23
|
-
export declare function readConflict(table: Indexed, value: unknown, allow?: ReadonlySet<string
|
|
24
|
+
export declare function readConflict(table: Indexed, value: unknown, allow?: ReadonlySet<string>, tenantKey?: string): ConflictPlan | undefined;
|
|
24
25
|
/**
|
|
25
26
|
* Appends the conflict clause, or wraps a first-or-create insert.
|
|
26
27
|
*
|
package/dist/runtime/pg/bun.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DriverError2
|
|
3
|
-
} from "../../shared/
|
|
3
|
+
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open5
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/k8v5v5wj.js";
|
|
7
7
|
import {
|
|
8
8
|
BUNSQL_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
10
10
|
hasCapability2
|
|
11
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/hf22e0wt.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/bun.ts
|
|
17
17
|
function connect(target, options) {
|
|
18
18
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
19
|
+
return import("../../shared/nxdp2ze3.js").then((mod) => mod.default(target, options, open5));
|
|
20
20
|
}
|
|
21
21
|
const owned = !isPool(target);
|
|
22
22
|
const pool = isPool(target) ? target : open5({
|
package/dist/runtime/pg/pg.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DriverError2
|
|
3
|
-
} from "../../shared/
|
|
3
|
+
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open4
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/96qcj21c.js";
|
|
7
7
|
import {
|
|
8
8
|
NODE_POSTGRES_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
10
10
|
hasCapability2
|
|
11
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/hf22e0wt.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/nxdp2ze3.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,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DriverError2
|
|
3
|
-
} from "../../shared/
|
|
3
|
+
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open3
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/87jvvhnt.js";
|
|
7
7
|
import {
|
|
8
8
|
PGLITE_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
10
10
|
hasCapability2
|
|
11
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/hf22e0wt.js";
|
|
15
15
|
|
|
16
16
|
// src/runtime/pg/pglite.ts
|
|
17
17
|
async function connect(target, options) {
|
|
18
18
|
if (typeof target === "object" && !isPool(target)) {
|
|
19
|
-
return import("../../shared/
|
|
19
|
+
return import("../../shared/nxdp2ze3.js").then((mod) => mod.default(target, options, open3));
|
|
20
20
|
}
|
|
21
21
|
const pool = isPool(target) ? target : await open3({
|
|
22
22
|
...target !== undefined ? { dataDir: target } : {},
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DriverError2
|
|
3
|
-
} from "../../shared/
|
|
3
|
+
} from "../../shared/31vm914h.js";
|
|
4
4
|
import {
|
|
5
5
|
open2
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/krxx77g0.js";
|
|
7
7
|
import {
|
|
8
8
|
POSTGRESJS_CAPABILITIES,
|
|
9
9
|
readCapability2,
|
|
10
10
|
hasCapability2
|
|
11
|
-
} from "../../shared/
|
|
11
|
+
} from "../../shared/cgbamx3e.js";
|
|
12
12
|
import {
|
|
13
13
|
createClient
|
|
14
|
-
} from "../../shared/
|
|
14
|
+
} from "../../shared/hf22e0wt.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/nxdp2ze3.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
|
@@ -288,6 +288,19 @@ export declare function indexes(schema: QuerySchema): ReadonlyMap<string, Indexe
|
|
|
288
288
|
export declare function quote(name: string): string;
|
|
289
289
|
export declare function list(names: readonly string[]): string;
|
|
290
290
|
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
291
|
+
/**
|
|
292
|
+
* Whether `where` constrains a row.
|
|
293
|
+
*
|
|
294
|
+
* A field value is a leaf. Anything other than `undefined` counts, including
|
|
295
|
+
* `null`, objects, arrays, and operators. The walk does not enter a field value.
|
|
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.
|
|
299
|
+
*
|
|
300
|
+
* @param where - Caller filter, or one `and` / `or` / `not` operand
|
|
301
|
+
* @returns `false` when the filter matches every row
|
|
302
|
+
*/
|
|
303
|
+
export declare function effectivePredicate(where: unknown): boolean;
|
|
291
304
|
/**
|
|
292
305
|
* Records the fix text for a code thrown from a chunk that loads on first use.
|
|
293
306
|
*
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from "../../shared/dyj86cmj.js";
|
|
22
22
|
import {
|
|
23
23
|
snakeCase
|
|
24
|
-
} from "../../shared/
|
|
24
|
+
} from "../../shared/ntneex2a.js";
|
|
25
25
|
import {
|
|
26
26
|
ColumnBuilder2,
|
|
27
27
|
retarget
|
|
@@ -38,10 +38,10 @@ import {
|
|
|
38
38
|
queryHandle,
|
|
39
39
|
attachHttp,
|
|
40
40
|
settleCall
|
|
41
|
-
} from "../../shared/
|
|
41
|
+
} from "../../shared/hf22e0wt.js";
|
|
42
42
|
import {
|
|
43
43
|
installArchiveInspect
|
|
44
|
-
} from "../../shared/
|
|
44
|
+
} from "../../shared/gbtcc2d7.js";
|
|
45
45
|
import {
|
|
46
46
|
fitIdentifier2
|
|
47
47
|
} from "../../shared/nfzc5z0w.js";
|
|
@@ -459,7 +459,7 @@ function refuse(host, table) {
|
|
|
459
459
|
}
|
|
460
460
|
var archiveMod;
|
|
461
461
|
function loadArchive() {
|
|
462
|
-
archiveMod ??= import("../../shared/
|
|
462
|
+
archiveMod ??= import("../../shared/0t22wwh1.js");
|
|
463
463
|
return archiveMod;
|
|
464
464
|
}
|
|
465
465
|
async function settle(host, table, mods) {
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
} from "../../shared/9m80mkac.js";
|
|
4
4
|
import {
|
|
5
5
|
addSchemaHook
|
|
6
|
-
} from "../../shared/
|
|
6
|
+
} from "../../shared/5enne4ma.js";
|
|
7
7
|
import {
|
|
8
8
|
queryHandle
|
|
9
|
-
} from "../../shared/
|
|
9
|
+
} from "../../shared/hf22e0wt.js";
|
|
10
10
|
import {
|
|
11
11
|
OkmError2
|
|
12
12
|
} from "../../shared/52szzakm.js";
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
// src/runtime/validate/load.ts
|
|
15
15
|
var engine;
|
|
16
16
|
function loadEngine() {
|
|
17
|
-
engine ??= import("../../shared/
|
|
17
|
+
engine ??= import("../../shared/8rsy3hxz.js");
|
|
18
18
|
return engine;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -12,16 +12,14 @@ import {
|
|
|
12
12
|
indexes,
|
|
13
13
|
quote,
|
|
14
14
|
isRecord,
|
|
15
|
+
effectivePredicate,
|
|
15
16
|
registerFailFix,
|
|
16
17
|
fail
|
|
17
|
-
} from "./
|
|
18
|
+
} from "./gbtcc2d7.js";
|
|
18
19
|
import {
|
|
19
20
|
safetyInstalled,
|
|
20
21
|
runSafety
|
|
21
22
|
} from "./a5sxz52y.js";
|
|
22
|
-
import {
|
|
23
|
-
isOperator
|
|
24
|
-
} from "./cn0n68ft.js";
|
|
25
23
|
import {
|
|
26
24
|
OkmError2
|
|
27
25
|
} from "./52szzakm.js";
|
|
@@ -362,11 +360,9 @@ function requireFilter(table, where, mods, op) {
|
|
|
362
360
|
}
|
|
363
361
|
return;
|
|
364
362
|
}
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return;
|
|
369
|
-
fail("OKM1102", `${op} on ${table.model.name} needs a where. Pass a filter, or .all(reason).`);
|
|
363
|
+
if (!effectivePredicate(where)) {
|
|
364
|
+
fail("OKM1102", `${op} on ${table.model.name} needs a where. Pass a filter, or .all(reason).`);
|
|
365
|
+
}
|
|
370
366
|
}
|
|
371
367
|
function callOptions(input) {
|
|
372
368
|
const signal = input.signal;
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./krxx77g0.js";
|
|
4
4
|
import"./8bwbwy8h.js";
|
|
5
5
|
import {
|
|
6
6
|
createdOf,
|
|
7
7
|
testing2
|
|
8
|
-
} from "./
|
|
8
|
+
} from "./v36c5g6p.js";
|
|
9
9
|
import"./n442h54c.js";
|
|
10
10
|
import {
|
|
11
|
-
assertTargetPolicy,
|
|
12
|
-
assertDirectConnection,
|
|
13
|
-
selectTarget,
|
|
14
11
|
loadConfig,
|
|
15
12
|
loadSchema
|
|
16
|
-
} from "./
|
|
17
|
-
import
|
|
13
|
+
} from "./qv2ydck9.js";
|
|
14
|
+
import {
|
|
15
|
+
assertTargetPolicy,
|
|
16
|
+
assertDirectConnection,
|
|
17
|
+
assertStableBackend,
|
|
18
|
+
selectTarget
|
|
19
|
+
} from "./ga3sfy93.js";
|
|
18
20
|
import"./8xsbagad.js";
|
|
19
21
|
import {
|
|
20
22
|
OkmError2
|
|
@@ -34,9 +36,22 @@ async function seedProject(cwd, file, flags) {
|
|
|
34
36
|
fix: { summary: "Pass okm seed <file> a module in this project." }
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
|
-
|
|
39
|
+
const allowPooler = flags.allowPooler || config.allowPooler === true;
|
|
40
|
+
assertDirectConnection(target.url, allowPooler);
|
|
38
41
|
const schema = await loadSchema(cwd, config.schema);
|
|
39
42
|
const pool = open2({ url: target.url, max: 1 });
|
|
43
|
+
const held = await pool.reserve?.();
|
|
44
|
+
if (held !== undefined) {
|
|
45
|
+
try {
|
|
46
|
+
await assertStableBackend(async () => {
|
|
47
|
+
const result = await held.execute("select pg_backend_pid()::text");
|
|
48
|
+
const cell = result.rows[0]?.[0];
|
|
49
|
+
return cell === null || cell === undefined ? "" : String(cell);
|
|
50
|
+
}, allowPooler);
|
|
51
|
+
} finally {
|
|
52
|
+
await held.release();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
40
55
|
const harness = await testing2(schema, { driver: pool, migrate: false });
|
|
41
56
|
try {
|
|
42
57
|
const imported = await import(`${pathToFileURL(path).href}?okm=${Date.now()}`);
|
|
@@ -75,7 +75,7 @@ function mapDriverError2(error, batchIndex) {
|
|
|
75
75
|
if (error instanceof DriverError2) {
|
|
76
76
|
return batchIndex === undefined ? error : error.at(batchIndex);
|
|
77
77
|
}
|
|
78
|
-
const message = error
|
|
78
|
+
const message = messageOf(error);
|
|
79
79
|
return new DriverError2(message, driverFields({
|
|
80
80
|
sqlstate: sqlstateOf(error),
|
|
81
81
|
constraint: errorField2(error, "constraint_name") ?? errorField2(error, "constraint"),
|
|
@@ -86,6 +86,14 @@ function mapDriverError2(error, batchIndex) {
|
|
|
86
86
|
batchIndex
|
|
87
87
|
}));
|
|
88
88
|
}
|
|
89
|
+
function messageOf(error) {
|
|
90
|
+
if (!(error instanceof Error))
|
|
91
|
+
return "driver error";
|
|
92
|
+
if (error.message.length > 0)
|
|
93
|
+
return error.message;
|
|
94
|
+
const first = error.errors?.[0];
|
|
95
|
+
return first instanceof Error && first.message.length > 0 ? first.message : "driver error";
|
|
96
|
+
}
|
|
89
97
|
function driverFields(input) {
|
|
90
98
|
const fields = {};
|
|
91
99
|
if (input.sqlstate !== undefined)
|