@voltro/database 0.86.0 → 0.88.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/CHANGELOG.md +5484 -0
- package/THIRD-PARTY-NOTICES.md +2 -226
- package/dist/actorSnapshot.js +1 -2
- package/dist/arrayCodec.js +1 -2
- package/dist/branchExecute.js +1 -2
- package/dist/branching.js +1 -2
- package/dist/bulkInsertLimits.js +16 -12
- package/dist/cdcOffsetsTables.js +1 -2
- package/dist/changeEvent.js +1 -2
- package/dist/changeIdentity.js +1 -2
- package/dist/changeListenerCeiling.js +1 -2
- package/dist/columnReference.js +1 -2
- package/dist/columns.js +1 -2
- package/dist/committedChanges.js +1 -2
- package/dist/connectionIdentity.js +1 -2
- package/dist/coreTables.js +1 -2
- package/dist/coreTablesRegistry.js +1 -2
- package/dist/dataTransfers.js +3 -3
- package/dist/dbCause.js +1 -2
- package/dist/dbMetrics.js +1 -2
- package/dist/decimalComparison.js +1 -2
- package/dist/derivedRowId.js +1 -2
- package/dist/dialect.js +1 -2
- package/dist/enumRenames.js +1 -2
- package/dist/expiresMixin.js +1 -2
- package/dist/fieldEncryption.js +65 -43
- package/dist/frameworkTables.js +16 -4
- package/dist/ginIndex.js +1 -2
- package/dist/hybridSearch.js +1 -2
- package/dist/idGenerator.js +5 -6
- package/dist/identifierLimits.js +1 -2
- package/dist/index.d.ts +153 -22
- package/dist/index.js +78 -78
- package/dist/indexAudit.js +45 -44
- package/dist/indexStorage.js +1 -2
- package/dist/joinCompiler.js +1 -2
- package/dist/jsonEagerCompiler.js +1 -2
- package/dist/jsonPatch.js +1 -2
- package/dist/jsonPatchAssignments.js +1 -2
- package/dist/jsonPath.js +1 -2
- package/dist/localFirstMixin.js +1 -2
- package/dist/migrate.js +52 -33
- package/dist/migration.js +1 -2
- package/dist/migrations/appliedAtValue.js +1 -2
- package/dist/migrations/applier.js +400 -386
- package/dist/migrations/boot.js +2 -3
- package/dist/migrations/branchRehearsal.js +1 -2
- package/dist/migrations/columnEquivalence.js +1 -2
- package/dist/migrations/ddlError.js +1 -2
- package/dist/migrations/ddlStatements.js +8 -0
- package/dist/migrations/declaredSchema.js +2 -3
- package/dist/migrations/deployLedger.js +1 -2
- package/dist/migrations/fileBased.js +1 -2
- package/dist/migrations/fileContext.js +1 -2
- package/dist/migrations/fileDiscovery.js +146 -133
- package/dist/migrations/fileSkipProbes.js +1 -2
- package/dist/migrations/fingerprint.js +1 -2
- package/dist/migrations/fkCycles.js +1 -2
- package/dist/migrations/frameworkLiveTables.js +1 -2
- package/dist/migrations/idempotentDdl.js +1 -2
- package/dist/migrations/indexPredicate.js +1 -2
- package/dist/migrations/introspect.js +188 -187
- package/dist/migrations/ledgerRows.js +1 -2
- package/dist/migrations/lock.js +1 -2
- package/dist/migrations/migrationTableExists.js +1 -2
- package/dist/migrations/mssqlColumnDependencies.js +1 -2
- package/dist/migrations/mysqlEngine.js +1 -2
- package/dist/migrations/namespaceCharset.js +1 -2
- package/dist/migrations/planner.js +25 -16
- package/dist/migrations/postgresEnumCheck.js +5 -3
- package/dist/migrations/reactiveTriggerDrift.js +1 -2
- package/dist/migrations/reactiveTriggerName.js +1 -2
- package/dist/migrations/renameMssqlCheck.js +1 -2
- package/dist/migrations/restoreSnapshots.js +1 -2
- package/dist/migrations/resumeLedger.js +1 -2
- package/dist/migrations/rollingDeploy.js +1 -2
- package/dist/migrations/schemaOwner.js +1 -2
- package/dist/migrations/schemaOwnerTable.js +1 -2
- package/dist/migrations/softDropSnapshot.js +1 -2
- package/dist/migrations/sqlLimit.js +1 -2
- package/dist/migrations/sqliteCatalogName.js +12 -0
- package/dist/migrations/sqliteConstraintIdentity.js +1 -2
- package/dist/migrations/sqliteDecimalBoot.js +1 -2
- package/dist/migrations/sqliteDecimalPublication.js +1 -2
- package/dist/migrations/sqliteDecimalReview.js +1 -2
- package/dist/migrations/sqliteDecimalReviewStore.js +1 -2
- package/dist/migrations/sqliteDecimalReviewWitness.js +1 -2
- package/dist/migrations/sqliteDecimalSource.js +1 -2
- package/dist/migrations/sqliteDecimalStage.js +1 -2
- package/dist/migrations/sqliteForeignKeys.js +1 -2
- package/dist/migrations/sqliteMigrationBatch.js +1 -2
- package/dist/migrations/sqliteRetainedSource.js +1 -2
- package/dist/migrations/sqliteRowIdentity.js +1 -2
- package/dist/migrations/sqliteSchemaEpoch.js +1 -2
- package/dist/migrations/sqliteSnapshotGuard.js +1 -2
- package/dist/migrations/sqliteTableContents.js +1 -2
- package/dist/migrations/sqliteTableCopy.js +1 -2
- package/dist/migrations/sqliteTableSchema.js +1 -2
- package/dist/migrations/sqliteWitnessProtection.js +1 -2
- package/dist/migrations/squash.js +1 -2
- package/dist/migrations/storeCharset.js +1 -2
- package/dist/migrations/transactionCause.js +1 -2
- package/dist/migrations/undeclaredCharset.js +1 -2
- package/dist/migrations/uniqueActiveLowering.js +1 -2
- package/dist/mixins.js +1 -2
- package/dist/mssqlDecimalDistinct.js +1 -2
- package/dist/mssqlJsonValueCheck.js +1 -2
- package/dist/mssqlTextStorage.js +1 -2
- package/dist/namespace.js +1 -2
- package/dist/optimisticVersion.js +1 -2
- package/dist/pendingAttribution.js +1 -2
- package/dist/pluginRef.js +1 -2
- package/dist/predicate.js +28 -22
- package/dist/predicateCoercion.js +1 -2
- package/dist/projectedColumn.js +1 -2
- package/dist/queryBuilder.js +7 -2
- package/dist/rawSql.js +1 -2
- package/dist/relations.js +1 -2
- package/dist/relationsRegistry.js +1 -2
- package/dist/replaceInProgress.js +1 -2
- package/dist/requiredColumns.js +1 -2
- package/dist/residency.js +1 -2
- package/dist/retention.js +1 -2
- package/dist/rowDecoder.js +62 -13
- package/dist/rowKey.js +1 -2
- package/dist/rowSchema.js +1 -2
- package/dist/scopeKey.js +1 -2
- package/dist/seed.js +1 -2
- package/dist/snowflake.js +1 -2
- package/dist/sql.d.ts +2746 -3748
- package/dist/sql.js +15 -14
- package/dist/sqlCompiler.js +89 -73
- package/dist/sqlError.js +1 -2
- package/dist/sqlMutation.js +54 -0
- package/dist/sqlPoolCapacity.js +1 -2
- package/dist/sqliteDecimal.js +1 -2
- package/dist/sqliteDecimalAggregateSql.js +1 -2
- package/dist/sqliteDecimalColumnSql.js +1 -2
- package/dist/sqliteDecimalConversion.js +1 -2
- package/dist/sqliteDecimalCte.js +1 -2
- package/dist/sqliteDecimalEncodeSql.js +1 -2
- package/dist/sqliteDecimalOutputs.js +1 -2
- package/dist/sqliteDecimalPredicate.js +1 -2
- package/dist/sqliteDecimalQuery.js +1 -2
- package/dist/sqliteDecimalQueryPlan.js +1 -2
- package/dist/sqliteDecimalResultSql.js +1 -2
- package/dist/sqliteDecimalRowQuery.js +1 -2
- package/dist/sqliteDecimalSetQuery.js +1 -2
- package/dist/sqliteDecimalSource.js +1 -2
- package/dist/sqliteDecimalStorage.js +1 -2
- package/dist/sqliteDecimalSubquery.js +1 -2
- package/dist/sqliteDecimalWindowQuery.js +1 -2
- package/dist/sqliteValueCoercion.js +1 -2
- package/dist/stampId.js +1 -2
- package/dist/storeErrors.js +1 -2
- package/dist/storeRefusal.js +1 -2
- package/dist/stream.js +1 -2
- package/dist/subjectGraph.js +1 -2
- package/dist/table.js +1 -2
- package/dist/tableRegistry.js +1 -2
- package/dist/tenantSelection.js +1 -2
- package/dist/transactionOutcome.js +5 -3
- package/dist/transientContention.js +1 -2
- package/dist/typeId.js +50 -0
- package/dist/typedStore.js +2 -3
- package/dist/upsertUpdate.js +1 -2
- package/dist/vectorEmbedding.js +1 -2
- package/dist/view.js +1 -2
- package/dist/wire.js +1 -2
- package/dist/writeAttribution.js +1 -2
- package/dist/writeRecorder.js +22 -22
- package/package.json +3 -4
package/dist/fieldEncryption.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
var e =
|
|
1
|
+
// src/fieldEncryption.ts
|
|
2
|
+
var e = /^[a-z0-9][a-z0-9-]{0,15}$/, t = (t) => {
|
|
3
|
+
if (!c(t)) return;
|
|
4
|
+
let i = t.startsWith(r), a = t.slice(i ? r.length : n.length).split(":")[i ? 4 : 3];
|
|
5
|
+
return a !== void 0 && e.test(a) ? a : void 0;
|
|
6
|
+
}, n = "enc:v1:", r = "enc:v2:", i = (e, t, n) => {
|
|
3
7
|
let r = `${e}:${t}`, i = n == null || n === "" ? void 0 : String(n);
|
|
4
8
|
return i === void 0 ? { column: r } : {
|
|
5
9
|
column: r,
|
|
6
10
|
row: `${r}:${i}`
|
|
7
11
|
};
|
|
8
|
-
},
|
|
12
|
+
}, a = (e) => typeof e == "string" && e.startsWith("enc:v2:"), o = class extends Error {
|
|
9
13
|
_tag = "FieldDecryptionError";
|
|
10
14
|
table;
|
|
11
15
|
column;
|
|
12
16
|
reason;
|
|
13
17
|
constructor(e) {
|
|
14
|
-
super(`column "${e.table}.${e.column}" is .encrypted() but could not be decrypted (${e.reason}) — the stored value was
|
|
18
|
+
super(`column "${e.table}.${e.column}" is .encrypted() but could not be decrypted (${e.reason}) — the stored value was sealed under a key this process does not hold, or it is not where it was sealed: a value opens only at the table, column and row it was written for (a rename needs .renamedFrom(); an id changed outside the store leaves it bound to the old id)`), this.name = "FieldDecryptionError", this.table = e.table, this.column = e.column, this.reason = e.reason;
|
|
15
19
|
}
|
|
16
|
-
},
|
|
20
|
+
}, s = (e) => typeof e == "object" && !!e && e._tag === "FieldDecryptionError", c = (e) => typeof e == "string" && (e.startsWith("enc:v1:") || e.startsWith("enc:v2:")), l = (e, t, n) => e.encrypt(JSON.stringify(t), n), u = /* @__PURE__ */ new Set([
|
|
17
21
|
"text",
|
|
18
22
|
"id",
|
|
19
23
|
"reference",
|
|
@@ -21,78 +25,96 @@ var e = "enc:v1:", t = "enc:v2:", n = (e, t, n) => {
|
|
|
21
25
|
"uuid",
|
|
22
26
|
"email",
|
|
23
27
|
"url"
|
|
24
|
-
]),
|
|
28
|
+
]), d = (e, t, n, r) => {
|
|
25
29
|
let i = e.decrypt(t, r), a;
|
|
26
30
|
try {
|
|
27
31
|
a = JSON.parse(i);
|
|
28
32
|
} catch {
|
|
29
33
|
return i;
|
|
30
34
|
}
|
|
31
|
-
return typeof a == "string" ? a : n === void 0 ||
|
|
32
|
-
},
|
|
35
|
+
return typeof a == "string" ? a : n === void 0 || u.has(n) ? i : a;
|
|
36
|
+
}, f = (e, t, n, r) => {
|
|
33
37
|
let i = e.decrypt(t, r);
|
|
34
38
|
try {
|
|
35
|
-
return typeof JSON.parse(i) == "string" ? !1 : n === void 0 ||
|
|
39
|
+
return typeof JSON.parse(i) == "string" ? !1 : n === void 0 || u.has(n) ? !0 : void 0;
|
|
36
40
|
} catch {
|
|
37
41
|
return !0;
|
|
38
42
|
}
|
|
39
|
-
},
|
|
43
|
+
}, p = (e, t) => e.fields[t]?.type, m = (e) => {
|
|
40
44
|
let t = [];
|
|
41
45
|
for (let [n, r] of Object.entries(e.fields)) r.encrypted === !0 && t.push(n);
|
|
42
46
|
return t;
|
|
43
|
-
},
|
|
47
|
+
}, h = "id", g = (e, t, n) => {
|
|
48
|
+
let r = e.tableName ?? "?", a = e.previousTableName, o = e.fields[t]?.renamedFrom, s = a === void 0 ? [r] : [r, a], c = o === void 0 ? [t] : [t, o];
|
|
49
|
+
return s.flatMap((e) => c.map((t) => i(e, t, n)));
|
|
50
|
+
}, _ = (e, t, n, r) => {
|
|
51
|
+
let i;
|
|
52
|
+
for (let a of r) try {
|
|
53
|
+
return d(e, t, n, a);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
i ??= e;
|
|
56
|
+
}
|
|
57
|
+
throw i;
|
|
58
|
+
}, v = (e, t, n, r) => {
|
|
44
59
|
if (!t) return e;
|
|
45
|
-
let i =
|
|
46
|
-
return i.length === 0 ? e :
|
|
47
|
-
},
|
|
60
|
+
let i = m(t);
|
|
61
|
+
return i.length === 0 ? e : x(e, i, t.tableName ?? "?", n, r);
|
|
62
|
+
}, y = (e, t, n) => {
|
|
63
|
+
if (t === void 0 || n == null) return;
|
|
64
|
+
let r = e[h];
|
|
65
|
+
if (r === void 0 || String(r) === String(n)) return;
|
|
66
|
+
let i = m(t);
|
|
67
|
+
if (i.length === 0) return;
|
|
68
|
+
let a = t.tableName ?? "?";
|
|
69
|
+
throw Error(`${a}: an update may not change the id of a row with .encrypted() columns (${i.join(", ")}) — each sealed value is bound to the id it was written under, so ${String(n)} → ${String(r)} would leave every one of them unreadable. Write the row under the new id (insert it, then delete the old one); the store seals its values there.`);
|
|
70
|
+
}, b = (e, t, n) => {
|
|
48
71
|
if (t === void 0 || e.length === 0) return e;
|
|
49
|
-
let r =
|
|
72
|
+
let r = m(t);
|
|
50
73
|
if (r.length === 0) return e;
|
|
51
74
|
let i = t.tableName ?? "?";
|
|
52
|
-
return e.map((e) =>
|
|
53
|
-
},
|
|
54
|
-
let
|
|
75
|
+
return e.map((e) => x(e, r, i, n));
|
|
76
|
+
}, x = (e, t, n, r, a) => {
|
|
77
|
+
let o = a ?? e[h], s = { ...e };
|
|
55
78
|
for (let e of t) {
|
|
56
|
-
let t =
|
|
57
|
-
if (!(t == null ||
|
|
58
|
-
if (!
|
|
59
|
-
|
|
79
|
+
let t = s[e];
|
|
80
|
+
if (!(t == null || c(t))) {
|
|
81
|
+
if (!r) throw Error(`column "${n}.${e}" is .encrypted() but no field cipher is registered — set VOLTRO_FIELD_ENCRYPTION_KEY (\`voltro dev\` mints one; \`voltro serve\` refuses to boot without it); in a test, pass \`fieldEncryptionKey\` to makeTestContext`);
|
|
82
|
+
s[e] = l(r, t, i(n, e, o));
|
|
60
83
|
}
|
|
61
84
|
}
|
|
62
|
-
return
|
|
63
|
-
},
|
|
85
|
+
return s;
|
|
86
|
+
}, S = (e, t, n, r) => {
|
|
64
87
|
if (!t) return e;
|
|
65
|
-
let
|
|
66
|
-
if (
|
|
67
|
-
let
|
|
88
|
+
let i = m(t);
|
|
89
|
+
if (i.length === 0 || !n) return e;
|
|
90
|
+
let a = r?.onError ?? "throw", s = t.tableName ?? "?";
|
|
68
91
|
return e.map((e) => {
|
|
69
|
-
let
|
|
70
|
-
for (let
|
|
71
|
-
let
|
|
72
|
-
if (
|
|
73
|
-
|
|
92
|
+
let l;
|
|
93
|
+
for (let u of i) {
|
|
94
|
+
let i = e[u];
|
|
95
|
+
if (c(i)) {
|
|
96
|
+
l ??= { ...e };
|
|
74
97
|
try {
|
|
75
|
-
|
|
98
|
+
l[u] = _(n, i, p(t, u), g(t, u, r?.rowId ?? e[h]));
|
|
76
99
|
} catch (e) {
|
|
77
100
|
let t = String(e?.message ?? e);
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
table:
|
|
81
|
-
column:
|
|
101
|
+
if (a === "null") {
|
|
102
|
+
l[u] = null, r?.warn?.({
|
|
103
|
+
table: s,
|
|
104
|
+
column: u,
|
|
82
105
|
reason: t
|
|
83
106
|
});
|
|
84
107
|
continue;
|
|
85
108
|
}
|
|
86
|
-
throw new
|
|
87
|
-
table:
|
|
88
|
-
column:
|
|
109
|
+
throw new o({
|
|
110
|
+
table: s,
|
|
111
|
+
column: u,
|
|
89
112
|
reason: t
|
|
90
113
|
});
|
|
91
114
|
}
|
|
92
115
|
}
|
|
93
116
|
}
|
|
94
|
-
return
|
|
117
|
+
return l ?? e;
|
|
95
118
|
});
|
|
96
119
|
};
|
|
97
|
-
|
|
98
|
-
export { t as BOUND_ENCRYPTED_PREFIX, e as ENCRYPTED_PREFIX, i as FieldDecryptionError, l as decodeFieldValue, _ as decryptFieldsOnRead, s as encodeFieldValue, m as encryptFieldsForWrite, h as encryptFieldsForWriteBatch, f as encryptedColumnsOf, n as fieldBinding, r as isBoundCiphertext, o as isEncrypted, a as isFieldDecryptionError, u as isRawEncoding };
|
|
120
|
+
export { r as BOUND_ENCRYPTED_PREFIX, n as ENCRYPTED_PREFIX, e as FIELD_KEY_ID_PATTERN, o as FieldDecryptionError, t as ciphertextKeyId, d as decodeFieldValue, S as decryptFieldsOnRead, l as encodeFieldValue, v as encryptFieldsForWrite, b as encryptFieldsForWriteBatch, m as encryptedColumnsOf, i as fieldBinding, g as fieldBindingsOf, a as isBoundCiphertext, c as isEncrypted, s as isFieldDecryptionError, f as isRawEncoding, y as refuseIdChangeOfSealedRow };
|
package/dist/frameworkTables.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { id as e, integer as t, json as n, text as r, timestamp as i } from "./columns.js";
|
|
2
2
|
import { table as a } from "./table.js";
|
|
3
|
-
|
|
3
|
+
// src/frameworkTables.ts
|
|
4
4
|
var o = a("_voltro_migrations", {
|
|
5
5
|
id: e({ prefix: "mig" }),
|
|
6
6
|
name: r(),
|
|
@@ -61,6 +61,7 @@ var o = a("_voltro_migrations", {
|
|
|
61
61
|
id: e({ prefix: "idem" }),
|
|
62
62
|
scope: r(),
|
|
63
63
|
key: r(),
|
|
64
|
+
inputHash: r().nullable(),
|
|
64
65
|
status: r(),
|
|
65
66
|
response: n().nullable(),
|
|
66
67
|
createdAt: i().default("now")
|
|
@@ -121,10 +122,21 @@ var o = a("_voltro_migrations", {
|
|
|
121
122
|
payload: r().nullable(),
|
|
122
123
|
reachableAt: r().maxLength(255).nullable(),
|
|
123
124
|
writtenAt: i().default("now").onUpdate("now")
|
|
124
|
-
}).unique(["replicaId", "kind"]).index(["kind"]), _ =
|
|
125
|
+
}).unique(["replicaId", "kind"]).index(["kind"]), _ = a("_voltro_api_role_workload_buckets", {
|
|
126
|
+
id: e({ prefix: "arwb" }),
|
|
127
|
+
replicaId: r().maxLength(191),
|
|
128
|
+
startedAt: i(),
|
|
129
|
+
role: r().maxLength(2080),
|
|
130
|
+
bucketFrom: i(),
|
|
131
|
+
bucketUntil: i(),
|
|
132
|
+
payload: r()
|
|
133
|
+
}).unique("_voltro_arwb_replica_bucket_uq", [
|
|
134
|
+
"replicaId",
|
|
135
|
+
"startedAt",
|
|
136
|
+
"bucketFrom"
|
|
137
|
+
]).index(["bucketUntil"]), v = [
|
|
125
138
|
o,
|
|
126
139
|
s,
|
|
127
140
|
u
|
|
128
141
|
];
|
|
129
|
-
|
|
130
|
-
export { h as _voltroApiKeysTable, f as _voltroDevicesTable, d as _voltroIdempotencyTable, m as _voltroKvTable, u as _voltroMigrationPlansTable, o as _voltroMigrationsTable, l as _voltroPluginMigrationsTable, g as _voltroReplicaObservationsTable, c as _voltroSchemaOwnerTable, s as _voltroSeedsTable, p as _voltroTenantSelectionsTable, _ as frameworkTables };
|
|
142
|
+
export { h as _voltroApiKeysTable, _ as _voltroApiRoleWorkloadBucketsTable, f as _voltroDevicesTable, d as _voltroIdempotencyTable, m as _voltroKvTable, u as _voltroMigrationPlansTable, o as _voltroMigrationsTable, l as _voltroPluginMigrationsTable, g as _voltroReplicaObservationsTable, c as _voltroSchemaOwnerTable, s as _voltroSeedsTable, p as _voltroTenantSelectionsTable, v as frameworkTables };
|
package/dist/ginIndex.js
CHANGED
package/dist/hybridSearch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveFullTextIndex as e } from "./queryBuilder.js";
|
|
2
|
-
|
|
2
|
+
// src/hybridSearch.ts
|
|
3
3
|
var t = (t) => {
|
|
4
4
|
let n = t.alpha ?? .5;
|
|
5
5
|
if (n < 0 || n > 1) throw Error(`hybridSearch: alpha must be in [0, 1], got ${n}`);
|
|
@@ -28,5 +28,4 @@ var t = (t) => {
|
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
-
//#endregion
|
|
32
31
|
export { t as hybridSearch };
|
package/dist/idGenerator.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { validateTypeIdPrefix as e } from "./identifierLimits.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { typeId as t } from "./typeId.js";
|
|
3
|
+
import { generateSnowflake as n } from "./snowflake.js";
|
|
4
4
|
import { ulid as r } from "ulid";
|
|
5
|
-
|
|
5
|
+
// src/idGenerator.ts
|
|
6
6
|
var i = (t) => {
|
|
7
7
|
let n = t.toLowerCase();
|
|
8
8
|
if (n.startsWith("_")) throw Error(`cannot derive a typeid prefix for table '${t}' (table names starting with '_' are not valid typeid prefixes). Pick an explicit prefix via id({ prefix: '...' }) or use a different scheme like id({ scheme: 'numeric' }) for internal tables.`);
|
|
@@ -46,12 +46,11 @@ var i = (t) => {
|
|
|
46
46
|
}
|
|
47
47
|
}, o = (e, i) => {
|
|
48
48
|
switch (e.kind) {
|
|
49
|
-
case "typeid": return
|
|
49
|
+
case "typeid": return t(e.prefix);
|
|
50
50
|
case "ulid": return r();
|
|
51
51
|
case "numeric": return null;
|
|
52
|
-
case "snowflake": return
|
|
52
|
+
case "snowflake": return n();
|
|
53
53
|
case "custom": return e.generate(i);
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
//#endregion
|
|
57
56
|
export { i as deriveTypeIdPrefix, o as generateId, a as resolveIdScheme };
|
package/dist/identifierLimits.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/identifierLimits.ts
|
|
2
2
|
var e = 63, t = 60, n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
3
3
|
n.add(e);
|
|
4
4
|
}, i = () => {
|
|
@@ -28,5 +28,4 @@ var e = 63, t = 60, n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
|
28
28
|
}
|
|
29
29
|
e.length > 60 && r(`typeid prefix '${e}' on table '${t.tableName}' is ${e.length} chars — close to the 63-byte limit. Generated ids will be even longer (prefix + '_' + 26).`);
|
|
30
30
|
};
|
|
31
|
-
//#endregion
|
|
32
31
|
export { e as MAX_IDENTIFIER_LENGTH, t as WARN_IDENTIFIER_LENGTH, i as drainIdentifierWarnings, c as validateColumnName, l as validateIndexName, s as validateTableName, u as validateTypeIdPrefix };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Duration } from 'effect/Duration';
|
|
|
4
4
|
import { Effect } from 'effect';
|
|
5
5
|
import { Exit } from 'effect';
|
|
6
6
|
import { Layer } from 'effect';
|
|
7
|
+
import { NonEmptyReadonlyArray } from 'effect/Array';
|
|
7
8
|
import { Schedule } from 'effect';
|
|
8
9
|
import { Schema } from 'effect';
|
|
9
10
|
import { SqlClient } from 'effect/sql';
|
|
@@ -240,12 +241,9 @@ export declare interface AuditActor {
|
|
|
240
241
|
export declare const auditAllTableIndexes: (tables: ReadonlyArray<Table<string, Record<string, ColumnDefinition<unknown>>, boolean, string>>) => ReadonlyArray<IndexAuditIssue>;
|
|
241
242
|
|
|
242
243
|
/**
|
|
243
|
-
* Find
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* Pair deduplication: each (a, b) collision is reported ONCE, never
|
|
247
|
-
* (a, b) AND (b, a). For `duplicate-fields` we keep the lexicographic
|
|
248
|
-
* lower name as `redundant` so the message is stable across re-runs.
|
|
244
|
+
* Find index-overlap issues on a single table. Each pair is reported once.
|
|
245
|
+
* When coverage holds in both directions, the lower name is redundant for
|
|
246
|
+
* stable output. Otherwise only the proven direction may recommend a drop.
|
|
249
247
|
*/
|
|
250
248
|
export declare const auditTableIndexes: (table: Table<string, Record<string, ColumnDefinition<unknown>>, boolean, string>) => ReadonlyArray<IndexAuditIssue>;
|
|
251
249
|
|
|
@@ -293,7 +291,8 @@ export declare const AUTO_FILLED_COLUMNS: readonly ["id", "tenantId", "createdAt
|
|
|
293
291
|
|
|
294
292
|
declare type AutoFilledColumn = (typeof AUTO_FILLED_COLUMNS)[number];
|
|
295
293
|
|
|
296
|
-
|
|
294
|
+
/** `AVG(column)` — always a `number` (a mean is not exact), `null` over no rows. */
|
|
295
|
+
export declare const avg: (column: string, alias?: string) => AggregateColumn<number | null>;
|
|
297
296
|
|
|
298
297
|
export declare const avgOver: (column: string, alias?: string) => WindowBuilder;
|
|
299
298
|
|
|
@@ -903,7 +902,25 @@ export declare const changeUpdate: (table: string, before: Row, after: Row, meta
|
|
|
903
902
|
*
|
|
904
903
|
* `undefined` limits (an unknown dialect) → one group, unchanged behaviour.
|
|
905
904
|
*/
|
|
906
|
-
export declare const chunkRowsForInsert: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, limits: BulkInsertLimits | undefined) => ReadonlyArray<
|
|
905
|
+
export declare const chunkRowsForInsert: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, limits: BulkInsertLimits | undefined) => ReadonlyArray<NonEmptyReadonlyArray<T>>;
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* The id of the key a ciphertext names, read off the value without any key —
|
|
909
|
+
* what lets a status count values per key instead of decrypting each one.
|
|
910
|
+
*
|
|
911
|
+
* The id is the LAST `:`-separated part of the envelope
|
|
912
|
+
* (`enc:v2:<r|c>:<iv>:<tag>:<ct>:<kid>`, `enc:v1:<iv>:<tag>:<ct>:<kid>`), after
|
|
913
|
+
* everything a release without key ids reads. That placement is deliberate:
|
|
914
|
+
* such a release takes the first parts and ignores the rest, so during a
|
|
915
|
+
* rolling deploy, and after a rollback, it still reads what the keyring wrote.
|
|
916
|
+
* The id is a lookup hint, not an authenticated field: a value whose id was
|
|
917
|
+
* altered still has to pass GCM under some key of the keyring, and a reader
|
|
918
|
+
* that verifies (the retire gate) decrypts rather than trusts it.
|
|
919
|
+
*
|
|
920
|
+
* `undefined` for a value written before ids, and for anything that is not a
|
|
921
|
+
* ciphertext.
|
|
922
|
+
*/
|
|
923
|
+
export declare const ciphertextKeyId: (value: unknown) => string | undefined;
|
|
907
924
|
|
|
908
925
|
/**
|
|
909
926
|
* Claim the attribution for an echo, or `undefined` if this write did not
|
|
@@ -2562,6 +2579,14 @@ export declare interface DataStore {
|
|
|
2562
2579
|
* up, on `FluentStore.query`, which is what handlers actually call.
|
|
2563
2580
|
*/
|
|
2564
2581
|
query(descriptor: QueryDescriptor): Promise<ReadonlyArray<Row>>;
|
|
2582
|
+
/** Server-internal constraint/integrity read on this exact store view.
|
|
2583
|
+
* Bypasses request row visibility only; preserves tenant, deletion/expiry
|
|
2584
|
+
* scopes, codecs, physical namespace and in-flight transaction writes.
|
|
2585
|
+
* Never use its rows as an application response or mutation authorization.
|
|
2586
|
+
* Optional for custom stores: a consumer requiring complete coverage must
|
|
2587
|
+
* refuse when absent, never fall back to an ordinary filtered query.
|
|
2588
|
+
*/
|
|
2589
|
+
integrityQuery?(descriptor: QueryDescriptor): Promise<ReadonlyArray<Row>>;
|
|
2565
2590
|
/** Insert a row. Emits an insert ChangeEvent (deferred if inside `transactional()`). */
|
|
2566
2591
|
insert(table: string, row: Row): Promise<Row>;
|
|
2567
2592
|
/**
|
|
@@ -2581,8 +2606,14 @@ export declare interface DataStore {
|
|
|
2581
2606
|
* - memory store: loop + per-row emit
|
|
2582
2607
|
*
|
|
2583
2608
|
* An empty `rows` array is a no-op that returns `[]` (no statement, no events).
|
|
2609
|
+
*
|
|
2610
|
+
* `{ returning: 'none' }` is for a caller that does not read the result: it
|
|
2611
|
+
* resolves to `[]`. The rows are written, and their change events emitted,
|
|
2612
|
+
* exactly as without it; the store reads the inserted rows back only when
|
|
2613
|
+
* change events or an in-transaction recorder need them
|
|
2614
|
+
* (`writeImagesObserved`). A wrapper store forwards `options` unchanged.
|
|
2584
2615
|
*/
|
|
2585
|
-
insertMany(table: string, rows: ReadonlyArray<Row
|
|
2616
|
+
insertMany(table: string, rows: ReadonlyArray<Row>, options?: InsertManyOptions): Promise<ReadonlyArray<Row>>;
|
|
2586
2617
|
/**
|
|
2587
2618
|
* In-place JSON merge: set `value` at `path` inside the JSON column
|
|
2588
2619
|
* (`path` is the column name, optionally with a nested dot-path, e.g.
|
|
@@ -2978,12 +3009,13 @@ export declare interface DataStore {
|
|
|
2978
3009
|
* not. Without a savepoint the two are incompatible, so `--atomic` simply
|
|
2979
3010
|
* could not import such a bundle on those engines.
|
|
2980
3011
|
*
|
|
2981
|
-
*
|
|
2982
|
-
*
|
|
2983
|
-
*
|
|
2984
|
-
*
|
|
2985
|
-
*
|
|
2986
|
-
*
|
|
3012
|
+
* Every shipped memory and SQL TRANSACTIONAL view implements it. Besides
|
|
3013
|
+
* statement-abort recovery, it isolates a compound operation whose typed
|
|
3014
|
+
* application error may be handled inside the outer transaction. Rollback
|
|
3015
|
+
* discards that operation's buffered committed-change events as well as rows;
|
|
3016
|
+
* earlier events and successful nesting remain intact. Root stores have no
|
|
3017
|
+
* savepoint. Custom stores may omit it; operations requiring local atomicity
|
|
3018
|
+
* must refuse rather than run without protection.
|
|
2987
3019
|
*
|
|
2988
3020
|
* Failures propagate: the savepoint is rolled back and the error rethrown, so
|
|
2989
3021
|
* the caller's own error handling is unchanged.
|
|
@@ -3192,6 +3224,9 @@ export declare interface DbOpSample {
|
|
|
3192
3224
|
*/
|
|
3193
3225
|
export declare const decimal: (precision: number, scale?: number) => ColumnBuilder<string, "decimal">;
|
|
3194
3226
|
|
|
3227
|
+
/** Equality key for exact fixed-point decimal strings; null for invalid input. */
|
|
3228
|
+
export declare const decimalEqualityKey: (value: unknown) => string | null;
|
|
3229
|
+
|
|
3195
3230
|
/**
|
|
3196
3231
|
* Declare that an enum value was renamed. Place this NEXT TO the
|
|
3197
3232
|
* `dbEnum(...)` declaration whose value array now carries the new label:
|
|
@@ -3276,6 +3311,12 @@ export declare const decodeRowsForTable: <T extends Record<string, unknown>>(row
|
|
|
3276
3311
|
*/
|
|
3277
3312
|
export declare const decodeRowsFromSchema: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, tableName: string, dialect: DecoderDialectId, query?: QueryDescriptor) => ReadonlyArray<T>;
|
|
3278
3313
|
|
|
3314
|
+
/**
|
|
3315
|
+
* Decode the rows of a SELECT: by the query's aggregations when it has them,
|
|
3316
|
+
* by the table's columns otherwise. Every dialect store's read path calls this.
|
|
3317
|
+
*/
|
|
3318
|
+
export declare const decodeSelectRows: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, query: QueryDescriptor, dialect: DecoderDialectId) => ReadonlyArray<T>;
|
|
3319
|
+
|
|
3279
3320
|
/**
|
|
3280
3321
|
* Decrypt every `.encrypted()` column's value on read. A value that
|
|
3281
3322
|
* isn't a framework ciphertext (legacy plaintext, `null`) passes
|
|
@@ -3816,6 +3857,9 @@ export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown, bin
|
|
|
3816
3857
|
*/
|
|
3817
3858
|
export declare const encodeRowForSchema: <T extends Record<string, unknown>>(row: T, tableName: string, types?: ReadonlyArray<ColumnType>) => T;
|
|
3818
3859
|
|
|
3860
|
+
/** 16 bytes → the 26-character lowercase Crockford-base32 suffix of the spec. */
|
|
3861
|
+
export declare const encodeTypeIdSuffix: (src: Uint8Array) => string;
|
|
3862
|
+
|
|
3819
3863
|
/** The UNBOUND envelope: `enc:v1:<iv>:<tag>:<ct>`. */
|
|
3820
3864
|
export declare const ENCRYPTED_PREFIX = "enc:v1:";
|
|
3821
3865
|
|
|
@@ -3975,6 +4019,13 @@ export declare interface FallbackLogger {
|
|
|
3975
4019
|
readonly debug: (message: string, fields?: Record<string, unknown>) => void;
|
|
3976
4020
|
}
|
|
3977
4021
|
|
|
4022
|
+
/**
|
|
4023
|
+
* A key id: a short slug, so it can ride inside every envelope. Explicit ids
|
|
4024
|
+
* are chosen by the operator (`VOLTRO_FIELD_ENCRYPTION_KEYS`); derived ids are
|
|
4025
|
+
* `k` + 10 hex characters of a fingerprint that is not the key.
|
|
4026
|
+
*/
|
|
4027
|
+
export declare const FIELD_KEY_ID_PATTERN: RegExp;
|
|
4028
|
+
|
|
3978
4029
|
/**
|
|
3979
4030
|
* Where a ciphertext BELONGS — the table, the column and, when the row's
|
|
3980
4031
|
* identity is known at write time, the row. Fed to AES-GCM as additional
|
|
@@ -4008,6 +4059,16 @@ export declare interface FieldBinding {
|
|
|
4008
4059
|
* its string form and a read of the numeric column agree. */
|
|
4009
4060
|
export declare const fieldBinding: (table: string, column: string, rowId?: unknown) => FieldBinding;
|
|
4010
4061
|
|
|
4062
|
+
/**
|
|
4063
|
+
* Every address a column's values may have been sealed under: its own, and the
|
|
4064
|
+
* names a DECLARED rename says it had — `table('new').renamedFrom('old')`, a
|
|
4065
|
+
* column's `.renamedFrom('old')`. A rename is catalog-only, so the rows keep the
|
|
4066
|
+
* bytes bound to the old name; without this every value of a renamed column
|
|
4067
|
+
* stopped opening. Only declared names are added: a value moved anywhere else
|
|
4068
|
+
* still refuses. The own address comes first — a re-key seals under it.
|
|
4069
|
+
*/
|
|
4070
|
+
export declare const fieldBindingsOf: (table: TableLike, column: string, rowId?: unknown) => ReadonlyArray<FieldBinding>;
|
|
4071
|
+
|
|
4011
4072
|
/** The cipher the store middleware injects. Operates on opaque strings. */
|
|
4012
4073
|
export declare interface FieldCipher {
|
|
4013
4074
|
/**
|
|
@@ -4030,6 +4091,15 @@ export declare interface FieldCipher {
|
|
|
4030
4091
|
* a cipher with one key.
|
|
4031
4092
|
*/
|
|
4032
4093
|
readonly sealedWithPreviousKey?: (ciphertext: string, binding?: FieldBinding) => boolean;
|
|
4094
|
+
/** The id of the key new values are sealed under — a keyring's active key. */
|
|
4095
|
+
readonly activeKeyId?: string;
|
|
4096
|
+
/**
|
|
4097
|
+
* The id of the key that opens this value: the one the value names when that
|
|
4098
|
+
* key opens it, otherwise the key of the keyring that does (a value written
|
|
4099
|
+
* before ciphertexts carried an id). `undefined` when no key of the keyring
|
|
4100
|
+
* opens it.
|
|
4101
|
+
*/
|
|
4102
|
+
readonly keyIdOf?: (ciphertext: string, binding?: FieldBinding) => string | undefined;
|
|
4033
4103
|
}
|
|
4034
4104
|
|
|
4035
4105
|
/**
|
|
@@ -4714,6 +4784,17 @@ export declare const insertIgnoreRowOutcome: <T extends AnyTable>(store: TypedIn
|
|
|
4714
4784
|
readonly outcome: "inserted" | "ignored";
|
|
4715
4785
|
}>;
|
|
4716
4786
|
|
|
4787
|
+
/** Options of {@link DataStore.insertMany}. */
|
|
4788
|
+
export declare interface InsertManyOptions {
|
|
4789
|
+
/**
|
|
4790
|
+
* `'rows'` (the default) resolves to the inserted rows as stored. `'none'`
|
|
4791
|
+
* resolves to `[]`, so a store need not send the rows back: a bulk insert
|
|
4792
|
+
* into a table no change event or recorder observes then costs one
|
|
4793
|
+
* statement per chunk and no result rows.
|
|
4794
|
+
*/
|
|
4795
|
+
readonly returning?: 'rows' | 'none';
|
|
4796
|
+
}
|
|
4797
|
+
|
|
4717
4798
|
/**
|
|
4718
4799
|
* Insert MANY rows, typed against the table — `insertRow`'s batch, and nothing
|
|
4719
4800
|
* else: it forwards to `store.insertMany` unchanged, so the chunking, the
|
|
@@ -4734,8 +4815,9 @@ export declare const insertIgnoreRowOutcome: <T extends AnyTable>(store: TypedIn
|
|
|
4734
4815
|
*
|
|
4735
4816
|
* An empty array is a legal no-op, so a caller does not have to guard the call
|
|
4736
4817
|
* — `store.insertMany` decides what that means, and it means "insert nothing".
|
|
4818
|
+
* `{ returning: 'none' }` is forwarded as well: it resolves to `[]`.
|
|
4737
4819
|
*/
|
|
4738
|
-
export declare const insertManyRows: <T extends AnyTable>(store: TypedInsertManyStore, table: T, rows: ReadonlyArray<InferInsertRow<T
|
|
4820
|
+
export declare const insertManyRows: <T extends AnyTable>(store: TypedInsertManyStore, table: T, rows: ReadonlyArray<InferInsertRow<T>>, options?: InsertManyOptions) => Promise<ReadonlyArray<InferRow<T>>>;
|
|
4739
4821
|
|
|
4740
4822
|
/**
|
|
4741
4823
|
* Insert a row, typed against the table: the payload must carry every required
|
|
@@ -6181,6 +6263,10 @@ Joins extends JoinsMap = {}> {
|
|
|
6181
6263
|
* on sqlite (its writers are serialised already).
|
|
6182
6264
|
*/
|
|
6183
6265
|
forUpdate: () => Query<RowOf, IxNames, Joins>;
|
|
6266
|
+
/** Hold a shared SQL row lock until transaction end; concurrent readers may
|
|
6267
|
+
* proceed. SQLite-family stores retain their transaction isolation without
|
|
6268
|
+
* row-lock SQL, and memory retains optimistic validation. */
|
|
6269
|
+
forShare: () => Query<RowOf, IxNames, Joins>;
|
|
6184
6270
|
/**
|
|
6185
6271
|
* Cross-tenant: opt OUT of the runtime's automatic
|
|
6186
6272
|
* `tenantId = <subject.tenantId>` scope on `tenant()` tables. Use for
|
|
@@ -6561,13 +6647,14 @@ export declare interface QueryDescriptor<R = Row> {
|
|
|
6561
6647
|
readonly includeExpired?: boolean;
|
|
6562
6648
|
/**
|
|
6563
6649
|
* Lock the matched rows for the rest of the enclosing transaction — set by
|
|
6564
|
-
* `.forUpdate()
|
|
6565
|
-
*
|
|
6650
|
+
* `.forUpdate()` for exclusive intent, `.forShare()` for concurrent readers
|
|
6651
|
+
* that must fence writers. SQL dialects retain the lock until transaction end;
|
|
6652
|
+
* sqlite serialises writers already and
|
|
6566
6653
|
* emits nothing. Outside a transaction the lock is released as the statement
|
|
6567
6654
|
* ends, which is harmless and useless — the point is a read-modify-write
|
|
6568
6655
|
* whose read and write share one transaction.
|
|
6569
6656
|
*/
|
|
6570
|
-
readonly lock?: 'update';
|
|
6657
|
+
readonly lock?: 'update' | 'share';
|
|
6571
6658
|
/**
|
|
6572
6659
|
* Opt OUT of the runtime's automatic tenant scope on `tenant()` tables.
|
|
6573
6660
|
* Set by `.unscoped()`. Honored by the runtime, same as `includeDeleted`.
|
|
@@ -7063,6 +7150,15 @@ export declare interface ReferenceOptions {
|
|
|
7063
7150
|
readonly column?: string;
|
|
7064
7151
|
}
|
|
7065
7152
|
|
|
7153
|
+
/**
|
|
7154
|
+
* Refuse an UPDATE that changes the id of a row with `.encrypted()` columns.
|
|
7155
|
+
* Each sealed value is bound to its row's id: an update that moved the row to a
|
|
7156
|
+
* new id left every sealed value in it bound to the old one, reported success,
|
|
7157
|
+
* and from then on every read of the row failed. Move such a row by writing it
|
|
7158
|
+
* under the new id (insert, then delete the old one) — the store seals it there.
|
|
7159
|
+
*/
|
|
7160
|
+
export declare const refuseIdChangeOfSealedRow: (patch: Row, table: TableLike | undefined, rowId: unknown) => void;
|
|
7161
|
+
|
|
7066
7162
|
/**
|
|
7067
7163
|
* Build the error a dialect store throws when the framework refuses a write.
|
|
7068
7164
|
*
|
|
@@ -7286,7 +7382,10 @@ export declare const resolveActorSnapshot: (store: ActorLookupStore, subjectId:
|
|
|
7286
7382
|
export declare type ResolveAggregateResult<A, RowOf, Joins extends JoinsMap> = A extends {
|
|
7287
7383
|
readonly op: 'min' | 'max';
|
|
7288
7384
|
readonly column: infer C extends string;
|
|
7289
|
-
} ? ResolveJoinedSource<C, RowOf, Joins> | null : A extends
|
|
7385
|
+
} ? ResolveJoinedSource<C, RowOf, Joins> | null : A extends {
|
|
7386
|
+
readonly op: 'sum';
|
|
7387
|
+
readonly column: infer C extends string;
|
|
7388
|
+
} ? [NonNullable<ResolveJoinedSource<C, RowOf, Joins>>] extends [string] ? string | null : number | null : A extends AggregateColumn<infer T> ? T : never;
|
|
7290
7389
|
|
|
7291
7390
|
/**
|
|
7292
7391
|
* Pick the branch mechanism. Prioritises the Neon copy-on-write fast-path when
|
|
@@ -8385,7 +8484,13 @@ export declare interface SubqueryInPredicate {
|
|
|
8385
8484
|
*/
|
|
8386
8485
|
export declare type SubqueryResults = Map< QueryDescriptor, Set<unknown> | number>;
|
|
8387
8486
|
|
|
8388
|
-
|
|
8487
|
+
/** `SUM(column)` — a `number` over `integer()` / `real()`, the exact decimal
|
|
8488
|
+
* STRING over `decimal()` / `bigint()` (the column's own type), `null` over no
|
|
8489
|
+
* rows. On a typed query the result type follows the column. */
|
|
8490
|
+
export declare const sum: <C extends string>(column: C, alias?: string) => AggregateColumn<number | null> & {
|
|
8491
|
+
readonly op: "sum";
|
|
8492
|
+
readonly column: C;
|
|
8493
|
+
};
|
|
8389
8494
|
|
|
8390
8495
|
export declare const sumOver: (column: string, alias?: string) => WindowBuilder;
|
|
8391
8496
|
|
|
@@ -9277,7 +9382,7 @@ export declare interface TypedInsertIgnoreOutcomeStore {
|
|
|
9277
9382
|
|
|
9278
9383
|
/** The minimal store surface `insertManyRows` needs. */
|
|
9279
9384
|
export declare interface TypedInsertManyStore {
|
|
9280
|
-
readonly insertMany: (table: string, rows: ReadonlyArray<Row
|
|
9385
|
+
readonly insertMany: (table: string, rows: ReadonlyArray<Row>, options?: InsertManyOptions) => Promise<ReadonlyArray<Row>>;
|
|
9281
9386
|
}
|
|
9282
9387
|
|
|
9283
9388
|
/** The minimal store surface `insertRow` needs — satisfied by `ctx.store`. */
|
|
@@ -9305,6 +9410,14 @@ export declare interface TypedUpsertStore {
|
|
|
9305
9410
|
readonly upsert: (table: string, row: Row, options: UpsertOptions) => Promise<Row>;
|
|
9306
9411
|
}
|
|
9307
9412
|
|
|
9413
|
+
/**
|
|
9414
|
+
* A fresh TypeID for `prefix`: `user_01h455vb4pex5vsknk084sn02q`. This is what
|
|
9415
|
+
* the `typeid` id scheme writes on insert; call it yourself when a row's id
|
|
9416
|
+
* has to exist before the insert (a self-referencing `createdBy`, a child row
|
|
9417
|
+
* written in the same flow).
|
|
9418
|
+
*/
|
|
9419
|
+
export declare const typeId: (prefix: string) => string;
|
|
9420
|
+
|
|
9308
9421
|
/**
|
|
9309
9422
|
* `(SELECT ...) UNION (SELECT ...) ...` — dedup-merge. Q6.
|
|
9310
9423
|
*
|
|
@@ -9460,6 +9573,9 @@ export declare const upsertUpdatePatch: (row: Row, existing: Row, options: Upser
|
|
|
9460
9573
|
/** Shared driver lowering: omit undefined values and refuse identity rewrites. */
|
|
9461
9574
|
export declare const upsertUpdateValues: (options: UpsertOptions) => Record<string, unknown>;
|
|
9462
9575
|
|
|
9576
|
+
/** The 16 bytes of a fresh UUIDv7 (RFC 9562), monotonic within this process. */
|
|
9577
|
+
export declare const uuidV7Bytes: (now?: number) => Uint8Array;
|
|
9578
|
+
|
|
9463
9579
|
/**
|
|
9464
9580
|
* Validate one column-name key on a table's fields map. Throws on
|
|
9465
9581
|
* empty / invalid characters / > 63 bytes. Records a WARN above 50.
|
|
@@ -9706,6 +9822,9 @@ export declare const VOLTRO_LOCAL_FIRST_MIXIN_ID: "voltro/localFirst";
|
|
|
9706
9822
|
*/
|
|
9707
9823
|
export declare const _voltroApiKeysTable: SchemaTable;
|
|
9708
9824
|
|
|
9825
|
+
/** Finalized role-observation history survives graceful replica shutdown. */
|
|
9826
|
+
export declare const _voltroApiRoleWorkloadBucketsTable: SchemaTable;
|
|
9827
|
+
|
|
9709
9828
|
export declare const _voltroCdcOffsetsTable: TableLike;
|
|
9710
9829
|
|
|
9711
9830
|
/**
|
|
@@ -10001,6 +10120,18 @@ export declare interface WriteAttribution {
|
|
|
10001
10120
|
readonly via?: 'agent';
|
|
10002
10121
|
}
|
|
10003
10122
|
|
|
10123
|
+
/**
|
|
10124
|
+
* Does anything read the row images of a write to `table`? A set-based write
|
|
10125
|
+
* (`updateMany` / `deleteMany`) answers with a count; the stores fetch its rows
|
|
10126
|
+
* back — `RETURNING *`, `OUTPUT`, a SELECT first — only to hand them to change
|
|
10127
|
+
* events and in-transaction recorders. A `.nonReactive()` table that no
|
|
10128
|
+
* recorder watches has neither, and the rows then crossed the wire for nobody:
|
|
10129
|
+
* every retired aggregate generation, `rowData` included, on every refresh.
|
|
10130
|
+
*
|
|
10131
|
+
* Asked per statement, not cached: recorders register and suspend at runtime.
|
|
10132
|
+
*/
|
|
10133
|
+
export declare const writeImagesObserved: (table: string) => boolean;
|
|
10134
|
+
|
|
10004
10135
|
export declare type WriteRecorder = (port: TxnRecorderPort, write: RecordedWrite) => Promise<void>;
|
|
10005
10136
|
|
|
10006
10137
|
/** Are recorders suspended right here? Exported so a caller can SAY so. */
|