okmodel 0.1.1 → 0.2.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 +32 -16
- package/dist/adapters/capabilities.d.ts +34 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
- package/dist/adapters/pg/bunsql.d.ts +60 -0
- package/dist/adapters/pg/call.d.ts +2 -12
- package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
- package/dist/adapters/pg/nodepostgres.d.ts +57 -0
- package/dist/adapters/pg/postgres-extra.d.ts +50 -1
- package/dist/adapters/pg/postgresjs.d.ts +0 -4
- package/dist/adapters/pg/session.d.ts +94 -0
- package/dist/adapters/pg/watch.d.ts +18 -0
- package/dist/contracts/catalog/object.d.ts +1 -0
- package/dist/contracts/catalog/types.d.ts +15 -8
- package/dist/contracts/connection.d.ts +13 -0
- package/dist/contracts/driver.d.ts +18 -5
- package/dist/contracts/error.d.ts +17 -1
- package/dist/contracts/generator.d.ts +63 -0
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/internal.js +11 -9
- package/dist/contracts/location.d.ts +24 -0
- package/dist/contracts/rows.d.ts +15 -0
- package/dist/dialects/pg/archive-bind.d.ts +22 -0
- package/dist/dialects/pg/column.d.ts +126 -9
- package/dist/dialects/pg/compile.d.ts +1 -0
- package/dist/dialects/pg/custom.d.ts +6 -0
- package/dist/dialects/pg/filter-parse.d.ts +19 -0
- package/dist/dialects/pg/filters.d.ts +19 -0
- package/dist/dialects/pg/index.d.ts +11 -2
- package/dist/dialects/pg/index.js +159 -1063
- package/dist/dialects/pg/keys.d.ts +19 -3
- package/dist/dialects/pg/model.d.ts +223 -2
- package/dist/dialects/pg/operator-fit.d.ts +86 -0
- package/dist/dialects/pg/operators.d.ts +39 -1
- package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
- package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
- package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
- package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
- package/dist/dialects/pg/ops/contains.d.ts +8 -4
- package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
- package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
- package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
- package/dist/dialects/pg/ops/json-set.d.ts +12 -0
- package/dist/dialects/pg/ops/matches.d.ts +16 -0
- package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
- package/dist/dialects/pg/ops/path.d.ts +13 -0
- package/dist/dialects/pg/preset.d.ts +76 -0
- package/dist/dialects/pg/relations.d.ts +59 -2
- package/dist/dialects/pg/schema.d.ts +109 -5
- package/dist/dialects/pg/table.d.ts +130 -11
- package/dist/dialects/pg/temporal.d.ts +9 -7
- package/dist/dialects/pg/tenancy.d.ts +94 -0
- package/dist/dialects/pg/through.d.ts +21 -0
- package/dist/dialects/pg/trait.d.ts +141 -0
- package/dist/dialects/pg/where.d.ts +37 -0
- package/dist/runtime/aggregate.d.ts +25 -0
- package/dist/runtime/archive-handle.d.ts +18 -0
- package/dist/runtime/archive-rules.d.ts +12 -0
- package/dist/runtime/archive.d.ts +73 -0
- package/dist/runtime/batch.d.ts +20 -0
- package/dist/runtime/client.d.ts +114 -5
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/exposure.d.ts +27 -0
- package/dist/runtime/hookm.d.ts +39 -0
- package/dist/runtime/ids/index.d.ts +11 -0
- package/dist/runtime/ids/index.js +193 -0
- package/dist/runtime/ids/okid-extended.d.ts +19 -0
- package/dist/runtime/ids/okid-generator.d.ts +21 -0
- package/dist/runtime/ids/okid-shared.d.ts +89 -0
- package/dist/runtime/ids/okid.d.ts +24 -0
- package/dist/runtime/ids/uuid.d.ts +21 -0
- package/dist/runtime/lock.d.ts +22 -0
- package/dist/runtime/operator-sql.d.ts +8 -0
- package/dist/runtime/page.d.ts +25 -0
- package/dist/runtime/pg/bun.d.ts +30 -0
- package/dist/runtime/pg/bun.js +52 -0
- package/dist/runtime/pg/pg.d.ts +29 -0
- package/dist/runtime/pg/pg.js +52 -0
- package/dist/runtime/pg/pglite.js +16 -17
- package/dist/runtime/pg/postgresjs.js +14 -24
- package/dist/runtime/plan.d.ts +146 -7
- package/dist/runtime/preset-stack.d.ts +17 -0
- package/dist/runtime/presets.d.ts +48 -0
- package/dist/runtime/read-stream.d.ts +26 -0
- package/dist/runtime/safety/index.d.ts +159 -0
- package/dist/runtime/safety/index.js +294 -0
- package/dist/runtime/safety-hook.d.ts +42 -0
- package/dist/runtime/server-check.d.ts +34 -0
- package/dist/runtime/tenancy/index.d.ts +37 -0
- package/dist/runtime/tenancy/index.js +365 -0
- package/dist/runtime/trait-read.d.ts +30 -0
- package/dist/runtime/traits/index.d.ts +128 -0
- package/dist/runtime/traits/index.js +509 -0
- package/dist/runtime/transaction.d.ts +19 -0
- package/dist/runtime/tx.d.ts +22 -7
- package/dist/runtime/types.d.ts +376 -27
- package/dist/runtime/validate/bind.d.ts +11 -0
- package/dist/runtime/validate/closed.d.ts +16 -0
- package/dist/runtime/validate/engine.d.ts +41 -0
- package/dist/runtime/validate/hook.d.ts +17 -0
- package/dist/runtime/validate/index.d.ts +21 -0
- package/dist/runtime/validate/index.js +175 -0
- package/dist/runtime/validate/load.d.ts +13 -0
- package/dist/runtime/validate/places.d.ts +41 -0
- package/dist/runtime/validate/rules.d.ts +108 -0
- package/dist/runtime/validate/surface.d.ts +102 -0
- package/dist/runtime/write.d.ts +30 -5
- package/dist/shared/{fgqgsb5z.js → 0qkxbm1f.js} +2 -2
- package/dist/shared/0v1g424p.js +26 -0
- package/dist/shared/10tjenmd.js +210 -0
- package/dist/shared/{xqbhg6cn.js → 1dp5knt7.js} +95 -10
- package/dist/shared/38crxbgn.js +229 -0
- package/dist/shared/3a5ne750.js +158 -0
- package/dist/shared/4b9da9d7.js +138 -0
- package/dist/shared/4e4c6vq2.js +62 -0
- package/dist/shared/{x5x59srr.js → 4jzzghr6.js} +416 -83
- package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
- package/dist/shared/{05w44d8g.js → 5z4q2zda.js} +567 -18
- package/dist/shared/672t5vym.js +12 -0
- package/dist/shared/7m88x3e9.js +45 -0
- package/dist/shared/7mht49yd.js +1091 -0
- package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
- package/dist/shared/83eaefwr.js +10 -0
- package/dist/shared/96ps4g1z.js +32 -0
- package/dist/shared/97g2jnrw.js +76 -0
- package/dist/shared/{xy79j5hq.js → 9k6vetvf.js} +25 -36
- package/dist/shared/{w8samvk1.js → a1gdp7j9.js} +1 -1
- package/dist/shared/a5sxz52y.js +13 -0
- package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
- package/dist/shared/cstgkzdx.js +154 -0
- package/dist/shared/{523ft3e8.js → d04j53v8.js} +6 -5
- package/dist/shared/{y9m15dfv.js → d2whjz4k.js} +15 -9
- package/dist/shared/dd4f8mnx.js +307 -0
- package/dist/shared/e6wg00wd.js +164 -0
- package/dist/shared/e7a268fy.js +195 -0
- package/dist/shared/{kprcwaha.js → eaxwrgby.js} +4 -3
- package/dist/shared/{dkn3y60a.js → ecdzej21.js} +76 -112
- package/dist/shared/{hadrfb9h.js → edwqqryd.js} +17 -14
- package/dist/shared/{m3ypagh5.js → eqmtn1bj.js} +57 -5
- package/dist/shared/g1b5zzj9.js +75 -0
- package/dist/shared/g9f0zqce.js +376 -0
- package/dist/shared/ge03bfca.js +64 -0
- package/dist/shared/{yd1kzwn2.js → jns2wx4t.js} +55 -12
- package/dist/shared/k3ted12y.js +33 -0
- package/dist/shared/k7dwkhvq.js +31 -0
- package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
- package/dist/shared/m9tv7xn7.js +404 -0
- package/dist/shared/mrq77sgw.js +55 -0
- package/dist/shared/mxmcdsh5.js +450 -0
- package/dist/shared/n442h54c.js +14 -0
- package/dist/shared/n47rd821.js +442 -0
- package/dist/shared/n4jqhpqz.js +27 -0
- package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
- package/dist/shared/nsva2a6b.js +42 -0
- package/dist/shared/ps43134h.js +69 -0
- package/dist/shared/{8b04d28c.js → py3nh7jy.js} +2 -2
- package/dist/shared/qa5dsc7z.js +86 -0
- package/dist/shared/{g5fhqmwe.js → qxa0yb9j.js} +6 -4
- package/dist/shared/r6nwkxnt.js +86 -0
- package/dist/shared/{jjb7yht9.js → rtnaqre0.js} +3 -3
- package/dist/shared/rwmrejjz.js +26 -0
- package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
- package/dist/shared/sacqha1y.js +70 -0
- package/dist/shared/{qk3hxfja.js → sfh4pk75.js} +5 -5
- package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
- package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
- package/dist/shared/v18jva5b.js +90 -0
- package/dist/shared/x9v1qgeb.js +201 -0
- package/dist/shared/xatfg0gn.js +193 -0
- package/dist/shared/xkz8g6by.js +225 -0
- package/dist/shared/{rgs0st28.js → xrfnq5k8.js} +237 -434
- package/dist/shared/ytg3xf9p.js +149 -0
- package/dist/shared/yw5c610b.js +48 -0
- package/dist/shared/zd93g3rq.js +31 -0
- package/dist/shared/zt8y0wzb.js +132 -0
- package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
- package/dist/tooling/cli.js +14 -10
- package/dist/tooling/migrate/commands.d.ts +10 -0
- package/dist/tooling/migrate/engine.d.ts +36 -0
- package/package.json +41 -4
- package/dist/shared/gk7cs7sp.js +0 -566
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callerLocation,
|
|
3
|
+
withLocation
|
|
4
|
+
} from "./k7dwkhvq.js";
|
|
5
|
+
import {
|
|
6
|
+
definition,
|
|
7
|
+
unavailable
|
|
8
|
+
} from "./xatfg0gn.js";
|
|
9
|
+
import {
|
|
10
|
+
OkmError2,
|
|
11
|
+
throwNamed2
|
|
12
|
+
} from "./52szzakm.js";
|
|
13
|
+
|
|
14
|
+
// src/dialects/pg/filters.ts
|
|
15
|
+
function openFilters(table, relations, spec, hiddenFields) {
|
|
16
|
+
const allow = spec.allow ?? {};
|
|
17
|
+
const sort = spec.sort ?? [];
|
|
18
|
+
for (const field of Object.keys(allow))
|
|
19
|
+
deny(hiddenFields, table, field);
|
|
20
|
+
for (const field of sort)
|
|
21
|
+
deny(hiddenFields, table, field);
|
|
22
|
+
const nested = spec.relations;
|
|
23
|
+
if (nested !== undefined) {
|
|
24
|
+
for (const name of Object.keys(nested)) {
|
|
25
|
+
const target = relationTable(relations, name);
|
|
26
|
+
for (const field of nested[name] ?? [])
|
|
27
|
+
deny(hiddenFields, target, field);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
parse(query) {
|
|
32
|
+
return import("./0v1g424p.js").then((mod) => mod.parseQuery(allow, sort, query));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function deny(hiddenFields, table, field) {
|
|
37
|
+
if (!hiddenFields.has(`${table}.${field}`))
|
|
38
|
+
return;
|
|
39
|
+
throw new OkmError2("OKM1123", `Field ${table}.${field} is hidden.`, {
|
|
40
|
+
fix: {
|
|
41
|
+
summary: "Remove the hidden field from the allowlist. Hidden fields stay out of caller filters and sorts."
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function relationTable(relations, name) {
|
|
46
|
+
if (typeof relations !== "object" || relations === null)
|
|
47
|
+
return name;
|
|
48
|
+
const call = relations[name];
|
|
49
|
+
if (typeof call !== "object" || call === null || !("table" in call))
|
|
50
|
+
return name;
|
|
51
|
+
const table = call.table;
|
|
52
|
+
return typeof table === "string" ? table : name;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/dialects/pg/table.ts
|
|
56
|
+
var TABLE_KNOWN = new Set([
|
|
57
|
+
"checks",
|
|
58
|
+
"comment",
|
|
59
|
+
"indexes",
|
|
60
|
+
"omitDefaults",
|
|
61
|
+
"presets",
|
|
62
|
+
"primaryKey",
|
|
63
|
+
"relations",
|
|
64
|
+
"renamedFrom",
|
|
65
|
+
"sqlName",
|
|
66
|
+
"tenancy",
|
|
67
|
+
"traits",
|
|
68
|
+
"unique",
|
|
69
|
+
"validate",
|
|
70
|
+
"validation"
|
|
71
|
+
]);
|
|
72
|
+
var TABLE_LATER = {
|
|
73
|
+
computed: "later",
|
|
74
|
+
policies: "later",
|
|
75
|
+
reference: "0.4"
|
|
76
|
+
};
|
|
77
|
+
function table2(name, columns, options) {
|
|
78
|
+
const source = callerLocation(1);
|
|
79
|
+
if (name.length === 0) {
|
|
80
|
+
definition(withLocation("table() needs a name.", source));
|
|
81
|
+
}
|
|
82
|
+
if (options !== undefined) {
|
|
83
|
+
rejectLater(options, TABLE_KNOWN, TABLE_LATER, `Table ${name}`);
|
|
84
|
+
}
|
|
85
|
+
remember(name, columns);
|
|
86
|
+
return {
|
|
87
|
+
name,
|
|
88
|
+
columns,
|
|
89
|
+
filters(spec) {
|
|
90
|
+
return openFilters(name, options?.relations, spec, hiddenFields);
|
|
91
|
+
},
|
|
92
|
+
...options !== undefined ? { options } : {},
|
|
93
|
+
...source !== undefined ? { source } : {}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function index2(...columns) {
|
|
97
|
+
return indexCall(columns.map((column) => column.name), false);
|
|
98
|
+
}
|
|
99
|
+
function sql2(strings, ...values) {
|
|
100
|
+
let text = strings[0] ?? "";
|
|
101
|
+
for (let index = 0;index < values.length; index += 1) {
|
|
102
|
+
text += sqlValue(values[index]);
|
|
103
|
+
text += strings[index + 1] ?? "";
|
|
104
|
+
}
|
|
105
|
+
return { text };
|
|
106
|
+
}
|
|
107
|
+
function snakeCase(name) {
|
|
108
|
+
let out = "";
|
|
109
|
+
for (let index = 0;index < name.length; index += 1) {
|
|
110
|
+
const char = name[index] ?? "";
|
|
111
|
+
const lower = char.toLowerCase();
|
|
112
|
+
if (lower !== char && char.toUpperCase() === char && out.length > 0 && !out.endsWith("_")) {
|
|
113
|
+
out += "_";
|
|
114
|
+
}
|
|
115
|
+
out += lower;
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
function emittedTypeName(name) {
|
|
120
|
+
let out = "";
|
|
121
|
+
let capitalize = true;
|
|
122
|
+
for (const char of name) {
|
|
123
|
+
const letter = char >= "a" && char <= "z" || char >= "A" && char <= "Z";
|
|
124
|
+
const digit = char >= "0" && char <= "9";
|
|
125
|
+
if (!letter && !digit) {
|
|
126
|
+
capitalize = true;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (capitalize && letter) {
|
|
130
|
+
out += char.toUpperCase();
|
|
131
|
+
capitalize = false;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
out += char;
|
|
135
|
+
capitalize = false;
|
|
136
|
+
}
|
|
137
|
+
if (out.length === 0) {
|
|
138
|
+
return "Table";
|
|
139
|
+
}
|
|
140
|
+
const first = out[0] ?? "";
|
|
141
|
+
if (first >= "0" && first <= "9") {
|
|
142
|
+
return `T${out}`;
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
function rejectLater(options, known, later, where) {
|
|
147
|
+
const record = options;
|
|
148
|
+
for (const key of Object.keys(record)) {
|
|
149
|
+
const prompt = later[key];
|
|
150
|
+
if (prompt !== undefined) {
|
|
151
|
+
if (record[key] !== undefined) {
|
|
152
|
+
const when = prompt === "later" ? "later" : `in ${prompt}`;
|
|
153
|
+
unavailable(`${where} option ${key} is not available yet. It arrives ${when}.`);
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (!known.has(key)) {
|
|
158
|
+
const accepted = [...known].sort().join(", ");
|
|
159
|
+
const candidates = [...known, ...Object.keys(later)];
|
|
160
|
+
throwNamed2("OKM1060", key, candidates, `${where} option ${key} is not supported. Accepted options: ${accepted}.`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function indexCall(columns, isUnique, predicate) {
|
|
165
|
+
return {
|
|
166
|
+
columns,
|
|
167
|
+
isUnique,
|
|
168
|
+
...predicate !== undefined ? { predicate } : {},
|
|
169
|
+
unique() {
|
|
170
|
+
return indexCall(columns, true, predicate);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function sqlValue(value) {
|
|
175
|
+
if (typeof value === "string") {
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
179
|
+
return String(value);
|
|
180
|
+
}
|
|
181
|
+
if (value === null || value === undefined) {
|
|
182
|
+
return "null";
|
|
183
|
+
}
|
|
184
|
+
if ("text" in value && typeof value.text === "string") {
|
|
185
|
+
return value.text;
|
|
186
|
+
}
|
|
187
|
+
if ("name" in value && typeof value.name === "string") {
|
|
188
|
+
return value.name;
|
|
189
|
+
}
|
|
190
|
+
definition("sql accepts a column, a string, a number, a boolean, or null.");
|
|
191
|
+
}
|
|
192
|
+
var hiddenFields = new Set;
|
|
193
|
+
function remember(name, columns) {
|
|
194
|
+
for (const field of Object.keys(columns)) {
|
|
195
|
+
const column = columns[field];
|
|
196
|
+
if (column?.state?.hidden === true)
|
|
197
|
+
hiddenFields.add(`${name}.${field}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export { table2, index2, sql2, snakeCase, emittedTypeName, rejectLater };
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OkmError2
|
|
3
|
+
} from "./52szzakm.js";
|
|
4
|
+
|
|
5
|
+
// src/dialects/pg/misuse.ts
|
|
6
|
+
var COLUMN_DEFINITION_CODE = "OKM1060";
|
|
7
|
+
var RESERVED_OPTION_CODE = "OKM1061";
|
|
8
|
+
var CODEC_VALUE_CODE = "OKM1210";
|
|
9
|
+
function definition(message) {
|
|
10
|
+
throw new OkmError2(COLUMN_DEFINITION_CODE, message);
|
|
11
|
+
}
|
|
12
|
+
function unavailable(message) {
|
|
13
|
+
throw new OkmError2(RESERVED_OPTION_CODE, message);
|
|
14
|
+
}
|
|
15
|
+
function rejected(message) {
|
|
16
|
+
throw new OkmError2(CODEC_VALUE_CODE, message);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/dialects/pg/quote.ts
|
|
20
|
+
function quoteLiteral(value) {
|
|
21
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
22
|
+
}
|
|
23
|
+
function arrayElement(encoded, raw) {
|
|
24
|
+
if (raw && (encoded === "true" || encoded === "false" || isBareNumber(encoded))) {
|
|
25
|
+
return encoded;
|
|
26
|
+
}
|
|
27
|
+
return `"${encoded.replaceAll("\\", "\\\\").replaceAll('"', "\\\"")}"`;
|
|
28
|
+
}
|
|
29
|
+
function isBareNumber(encoded) {
|
|
30
|
+
let pattern = bareNumber;
|
|
31
|
+
pattern ??= /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
32
|
+
bareNumber = pattern;
|
|
33
|
+
return pattern.test(encoded);
|
|
34
|
+
}
|
|
35
|
+
var bareNumber;
|
|
36
|
+
|
|
37
|
+
// src/dialects/pg/array-literal.ts
|
|
38
|
+
function writeArray(value, dims, encode, raw) {
|
|
39
|
+
return writeLevel(value, dims, encode, raw);
|
|
40
|
+
}
|
|
41
|
+
function readArray(wire, dims, decode) {
|
|
42
|
+
const cursor = { text: wire, index: 0 };
|
|
43
|
+
const parsed = parseValue(cursor);
|
|
44
|
+
skipSpace(cursor);
|
|
45
|
+
if (cursor.index !== cursor.text.length) {
|
|
46
|
+
rejected("Array literal has trailing text.");
|
|
47
|
+
}
|
|
48
|
+
if (!Array.isArray(parsed)) {
|
|
49
|
+
rejected("Array literal must start with `{`.");
|
|
50
|
+
}
|
|
51
|
+
return interpret(parsed, dims, decode);
|
|
52
|
+
}
|
|
53
|
+
function writeLevel(value, dims, encode, raw) {
|
|
54
|
+
if (!Array.isArray(value)) {
|
|
55
|
+
rejected("Array column expected an array.");
|
|
56
|
+
}
|
|
57
|
+
const parts = [];
|
|
58
|
+
if (dims === 1) {
|
|
59
|
+
for (const item of value) {
|
|
60
|
+
if (item === null || item === undefined) {
|
|
61
|
+
rejected("Array elements cannot be null.");
|
|
62
|
+
}
|
|
63
|
+
parts.push(arrayElement(encode(item), raw));
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
for (const item of value) {
|
|
67
|
+
parts.push(writeLevel(item, dims - 1, encode, raw));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return `{${parts.join(",")}}`;
|
|
71
|
+
}
|
|
72
|
+
function interpret(nodes, dims, decode) {
|
|
73
|
+
if (dims === 1) {
|
|
74
|
+
return nodes.map((cell) => {
|
|
75
|
+
if (typeof cell !== "string") {
|
|
76
|
+
rejected("Array rank does not match dims.");
|
|
77
|
+
}
|
|
78
|
+
return decode(cell);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return nodes.map((cell) => {
|
|
82
|
+
if (!Array.isArray(cell)) {
|
|
83
|
+
rejected("Array rank does not match dims.");
|
|
84
|
+
}
|
|
85
|
+
return interpret(cell, dims - 1, decode);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function parseValue(cursor) {
|
|
89
|
+
skipSpace(cursor);
|
|
90
|
+
if (peek(cursor) === "{") {
|
|
91
|
+
return parseArray(cursor);
|
|
92
|
+
}
|
|
93
|
+
return parseElement(cursor);
|
|
94
|
+
}
|
|
95
|
+
function parseArray(cursor) {
|
|
96
|
+
expectChar(cursor, "{");
|
|
97
|
+
skipSpace(cursor);
|
|
98
|
+
if (peek(cursor) === "}") {
|
|
99
|
+
cursor.index += 1;
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const items = [];
|
|
103
|
+
for (;; ) {
|
|
104
|
+
items.push(parseValue(cursor));
|
|
105
|
+
skipSpace(cursor);
|
|
106
|
+
if (peek(cursor) === ",") {
|
|
107
|
+
cursor.index += 1;
|
|
108
|
+
skipSpace(cursor);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
expectChar(cursor, "}");
|
|
112
|
+
return items;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function parseElement(cursor) {
|
|
116
|
+
if (peek(cursor) === '"') {
|
|
117
|
+
return parseQuoted(cursor);
|
|
118
|
+
}
|
|
119
|
+
const start = cursor.index;
|
|
120
|
+
while (cursor.index < cursor.text.length) {
|
|
121
|
+
const char = cursor.text[cursor.index];
|
|
122
|
+
if (char === "," || char === "}" || char === undefined || isSpace(char)) {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
cursor.index += 1;
|
|
126
|
+
}
|
|
127
|
+
const token = cursor.text.slice(start, cursor.index);
|
|
128
|
+
if (token.length === 0) {
|
|
129
|
+
rejected("Array literal is missing an element.");
|
|
130
|
+
}
|
|
131
|
+
if (token === "NULL") {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return token;
|
|
135
|
+
}
|
|
136
|
+
function parseQuoted(cursor) {
|
|
137
|
+
expectChar(cursor, '"');
|
|
138
|
+
let out = "";
|
|
139
|
+
for (;; ) {
|
|
140
|
+
const char = next(cursor);
|
|
141
|
+
if (char === undefined) {
|
|
142
|
+
rejected("Array literal ended inside a quote.");
|
|
143
|
+
}
|
|
144
|
+
if (char === '"') {
|
|
145
|
+
if (peek(cursor) === '"') {
|
|
146
|
+
cursor.index += 1;
|
|
147
|
+
out += '"';
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
if (char === "\\") {
|
|
153
|
+
const escaped = next(cursor);
|
|
154
|
+
if (escaped === undefined) {
|
|
155
|
+
rejected("Array literal ended inside an escape.");
|
|
156
|
+
}
|
|
157
|
+
out += escaped;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
out += char;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function expectChar(cursor, expected) {
|
|
164
|
+
if (peek(cursor) !== expected) {
|
|
165
|
+
rejected(`Array literal expected ${expected}.`);
|
|
166
|
+
}
|
|
167
|
+
cursor.index += 1;
|
|
168
|
+
}
|
|
169
|
+
function peek(cursor) {
|
|
170
|
+
return cursor.text[cursor.index];
|
|
171
|
+
}
|
|
172
|
+
function next(cursor) {
|
|
173
|
+
const char = cursor.text[cursor.index];
|
|
174
|
+
if (char !== undefined) {
|
|
175
|
+
cursor.index += 1;
|
|
176
|
+
}
|
|
177
|
+
return char;
|
|
178
|
+
}
|
|
179
|
+
function skipSpace(cursor) {
|
|
180
|
+
while (cursor.index < cursor.text.length) {
|
|
181
|
+
const char = cursor.text[cursor.index];
|
|
182
|
+
if (char === undefined || !isSpace(char)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
cursor.index += 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function isSpace(char) {
|
|
189
|
+
return char === " " || char === `
|
|
190
|
+
` || char === "\t";
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export { definition, unavailable, rejected, quoteLiteral, writeArray, readArray };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
required
|
|
3
|
+
} from "./dd4f8mnx.js";
|
|
4
|
+
import {
|
|
5
|
+
definition,
|
|
6
|
+
rejected
|
|
7
|
+
} from "./xatfg0gn.js";
|
|
8
|
+
|
|
9
|
+
// src/dialects/pg/temporal.ts
|
|
10
|
+
var TEMPORAL_MISSING = "Date and time codecs need the Temporal global. okmodel does not ship a polyfill. Use a runtime that provides Temporal, or assign a polyfill to globalThis.Temporal before using these columns.";
|
|
11
|
+
function requireTemporal() {
|
|
12
|
+
const temporal = globalThis.Temporal;
|
|
13
|
+
if (typeof temporal !== "object" || temporal === null || !("Instant" in temporal)) {
|
|
14
|
+
rejected(TEMPORAL_MISSING);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function timePrecision(precision, role) {
|
|
18
|
+
if (precision === undefined) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!Number.isInteger(precision) || precision < 0 || precision > 6) {
|
|
22
|
+
definition(`${role} precision ${String(precision)} must be an integer from 0 to 6.`);
|
|
23
|
+
}
|
|
24
|
+
return precision;
|
|
25
|
+
}
|
|
26
|
+
function encodeInstant(value, precision) {
|
|
27
|
+
requireTemporal();
|
|
28
|
+
if (precision === undefined) {
|
|
29
|
+
return value.toString();
|
|
30
|
+
}
|
|
31
|
+
return value.toString({ fractionalSecondDigits: precision });
|
|
32
|
+
}
|
|
33
|
+
function decodeInstant(wire) {
|
|
34
|
+
requireTemporal();
|
|
35
|
+
try {
|
|
36
|
+
return Temporal.Instant.from(wire);
|
|
37
|
+
} catch {
|
|
38
|
+
rejected(`timestamptz ${wire} must be an ISO-8601 instant, for example 2020-01-01T00:00:00Z.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function encodeDateTime(value, precision) {
|
|
42
|
+
requireTemporal();
|
|
43
|
+
if (precision === undefined) {
|
|
44
|
+
return value.toString();
|
|
45
|
+
}
|
|
46
|
+
return value.toString({ fractionalSecondDigits: precision });
|
|
47
|
+
}
|
|
48
|
+
function decodeDateTime(wire) {
|
|
49
|
+
requireTemporal();
|
|
50
|
+
try {
|
|
51
|
+
return Temporal.PlainDateTime.from(wire);
|
|
52
|
+
} catch {
|
|
53
|
+
rejected(`timestamp ${wire} must be an ISO-8601 date-time without a zone, for example 2020-01-01T00:00:00.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function encodeDate(value) {
|
|
57
|
+
requireTemporal();
|
|
58
|
+
return value.toString();
|
|
59
|
+
}
|
|
60
|
+
function decodeDate(wire) {
|
|
61
|
+
requireTemporal();
|
|
62
|
+
try {
|
|
63
|
+
return Temporal.PlainDate.from(wire);
|
|
64
|
+
} catch {
|
|
65
|
+
rejected(`date ${wire} must be YYYY-MM-DD.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function encodeTime(value, precision) {
|
|
69
|
+
requireTemporal();
|
|
70
|
+
if (precision === undefined) {
|
|
71
|
+
return value.toString();
|
|
72
|
+
}
|
|
73
|
+
return value.toString({ fractionalSecondDigits: precision });
|
|
74
|
+
}
|
|
75
|
+
function decodeTime(wire) {
|
|
76
|
+
requireTemporal();
|
|
77
|
+
try {
|
|
78
|
+
return Temporal.PlainTime.from(wire);
|
|
79
|
+
} catch {
|
|
80
|
+
rejected(`time ${wire} must be a time of day, for example 00:00:00.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function encodeTimeZone(value, precision) {
|
|
84
|
+
requireTemporal();
|
|
85
|
+
if (!offsetText().test(value.offset)) {
|
|
86
|
+
rejected(`timetz offset ${value.offset} must be ±HH:MM.`);
|
|
87
|
+
}
|
|
88
|
+
return `${encodeTime(value.time, precision)}${value.offset}`;
|
|
89
|
+
}
|
|
90
|
+
function decodeTimeZone(wire) {
|
|
91
|
+
const match = timeZoneText().exec(wire);
|
|
92
|
+
const time = match?.[1];
|
|
93
|
+
const hours = match?.[2];
|
|
94
|
+
if (time === undefined || hours === undefined) {
|
|
95
|
+
rejected(`timetz ${wire} must be a time of day plus ±HH or ±HH:MM, for example 00:00:00+00.`);
|
|
96
|
+
}
|
|
97
|
+
return { time: decodeTime(time), offset: `${hours}:${match?.[3] ?? "00"}` };
|
|
98
|
+
}
|
|
99
|
+
function encodeDuration(value) {
|
|
100
|
+
requireTemporal();
|
|
101
|
+
const text = value.toString();
|
|
102
|
+
return text.startsWith("-") ? text.slice(1).replace(/\d+(?:\.\d+)?(?=[A-Z])/g, "-$&") : text;
|
|
103
|
+
}
|
|
104
|
+
function decodeDuration(wire) {
|
|
105
|
+
requireTemporal();
|
|
106
|
+
const fields = {};
|
|
107
|
+
const rest = wire.replace(/([+-]?\d+) (year|mon|day)s?|([+-]?)(\d+):(\d{2}):(\d{2})(?:\.(\d{1,6}))?/g, (_part, count, unit, sign, h = "", m = "", s = "", f = "") => {
|
|
108
|
+
if (count !== undefined && unit !== undefined) {
|
|
109
|
+
fields[`${unit === "mon" ? "month" : unit}s`] = Number(count);
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
const micros = Number(f.padEnd(6, "0"));
|
|
113
|
+
const flip = sign === "-" ? -1 : 1;
|
|
114
|
+
fields.hours = flip * Number(h);
|
|
115
|
+
fields.minutes = flip * Number(m);
|
|
116
|
+
fields.seconds = flip * Number(s);
|
|
117
|
+
fields.milliseconds = flip * Math.trunc(micros / 1000);
|
|
118
|
+
fields.microseconds = flip * (micros % 1000);
|
|
119
|
+
return "";
|
|
120
|
+
});
|
|
121
|
+
try {
|
|
122
|
+
return Temporal.Duration.from(rest.trim() === "" && wire !== "" ? fields : wire);
|
|
123
|
+
} catch {
|
|
124
|
+
rejected(`interval ${wire} must be what Postgres sends (for example 01:30:00 or 1 day 02:03:04) or an ISO-8601 duration (PT1H). Parts of different signs are not one Temporal.Duration.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function intervalFields(fields) {
|
|
128
|
+
switch (fields) {
|
|
129
|
+
case "year":
|
|
130
|
+
case "month":
|
|
131
|
+
case "day":
|
|
132
|
+
case "hour":
|
|
133
|
+
case "minute":
|
|
134
|
+
case "second":
|
|
135
|
+
case "year to month":
|
|
136
|
+
case "day to hour":
|
|
137
|
+
case "day to minute":
|
|
138
|
+
case "day to second":
|
|
139
|
+
case "hour to minute":
|
|
140
|
+
case "hour to second":
|
|
141
|
+
case "minute to second":
|
|
142
|
+
return fields;
|
|
143
|
+
default:
|
|
144
|
+
definition(`interval fields ${fields} must be one of: year, month, day, hour, minute, second, year to month, day to hour, day to minute, day to second, hour to minute, hour to second, minute to second.`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function offsetText() {
|
|
148
|
+
offsetPattern ??= /^[+-]\d{2}:\d{2}$/;
|
|
149
|
+
return offsetPattern;
|
|
150
|
+
}
|
|
151
|
+
function timeZoneText() {
|
|
152
|
+
timeZonePattern ??= /^(.+?)([+-]\d{2})(?::(\d{2}))?$/;
|
|
153
|
+
return timeZonePattern;
|
|
154
|
+
}
|
|
155
|
+
var offsetPattern;
|
|
156
|
+
var timeZonePattern;
|
|
157
|
+
|
|
158
|
+
// src/dialects/pg/time.ts
|
|
159
|
+
function timestamptz2(precision) {
|
|
160
|
+
const digits = timePrecision(precision, "timestamptz");
|
|
161
|
+
return required({
|
|
162
|
+
baseType: timed("timestamptz", digits),
|
|
163
|
+
encode: (value) => encodeInstant(value, digits),
|
|
164
|
+
decode: decodeInstant,
|
|
165
|
+
accepts: ["Temporal.Instant"],
|
|
166
|
+
sqlForm: "quote"
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function timestamp2(precision) {
|
|
170
|
+
const digits = timePrecision(precision, "timestamp");
|
|
171
|
+
return required({
|
|
172
|
+
baseType: timed("timestamp", digits),
|
|
173
|
+
encode: (value) => encodeDateTime(value, digits),
|
|
174
|
+
decode: decodeDateTime,
|
|
175
|
+
accepts: ["Temporal.PlainDateTime"],
|
|
176
|
+
sqlForm: "quote"
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function date2() {
|
|
180
|
+
return required({
|
|
181
|
+
baseType: "date",
|
|
182
|
+
encode: encodeDate,
|
|
183
|
+
decode: decodeDate,
|
|
184
|
+
accepts: ["Temporal.PlainDate"],
|
|
185
|
+
sqlForm: "quote"
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function time2(precision) {
|
|
189
|
+
const digits = timePrecision(precision, "time");
|
|
190
|
+
return required({
|
|
191
|
+
baseType: timed("time", digits),
|
|
192
|
+
encode: (value) => encodeTime(value, digits),
|
|
193
|
+
decode: decodeTime,
|
|
194
|
+
accepts: ["Temporal.PlainTime"],
|
|
195
|
+
sqlForm: "quote"
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function timetz2(precision) {
|
|
199
|
+
const digits = timePrecision(precision, "timetz");
|
|
200
|
+
return required({
|
|
201
|
+
baseType: timed("timetz", digits),
|
|
202
|
+
encode: (value) => encodeTimeZone(value, digits),
|
|
203
|
+
decode: decodeTimeZone,
|
|
204
|
+
accepts: ["Object"],
|
|
205
|
+
sqlForm: "quote"
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function interval2(fields) {
|
|
209
|
+
const qualifier = fields === undefined ? undefined : intervalFields(fields);
|
|
210
|
+
return required({
|
|
211
|
+
baseType: qualifier === undefined ? "interval" : `interval ${qualifier}`,
|
|
212
|
+
encode: encodeDuration,
|
|
213
|
+
decode: decodeDuration,
|
|
214
|
+
accepts: ["Temporal.Duration"],
|
|
215
|
+
sqlForm: "quote"
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function timed(name, precision) {
|
|
219
|
+
if (precision === undefined) {
|
|
220
|
+
return name;
|
|
221
|
+
}
|
|
222
|
+
return `${name}(${String(precision)})`;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { encodeInstant, decodeInstant, encodeDate, decodeDate, timestamptz2, timestamp2, date2, time2, timetz2, interval2 };
|