@voltro/database 0.85.0 → 0.86.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 +666 -0
- package/THIRD-PARTY-NOTICES.md +5 -33
- package/dist/actorSnapshot.js +24 -0
- package/dist/arrayCodec.js +32 -0
- package/dist/branchExecute.js +92 -0
- package/dist/branching.js +106 -0
- package/dist/bulkInsertLimits.js +25 -0
- package/dist/cdcOffsetsTables.js +19 -0
- package/dist/changeEvent.js +41 -0
- package/dist/changeIdentity.js +65 -0
- package/dist/changeListenerCeiling.js +6 -0
- package/dist/columnReference.js +17 -0
- package/dist/columns.js +326 -0
- package/dist/committedChanges.js +12 -0
- package/dist/connectionIdentity.js +36 -0
- package/dist/coreTables.js +16 -0
- package/dist/coreTablesRegistry.js +10 -0
- package/dist/dataTransfers.js +22 -0
- package/dist/dbCause.js +222 -0
- package/dist/dbMetrics.js +65 -0
- package/dist/decimalComparison.js +27 -0
- package/dist/derivedRowId.js +5 -0
- package/dist/dialect.js +13 -0
- package/dist/enumRenames.js +14 -0
- package/dist/expiresMixin.js +10 -0
- package/dist/fieldEncryption.js +98 -0
- package/dist/frameworkTables.js +130 -0
- package/dist/ginIndex.js +10 -0
- package/dist/hybridSearch.js +32 -0
- package/dist/idGenerator.js +57 -0
- package/dist/identifierLimits.js +32 -0
- package/dist/index.d.ts +18 -7
- package/dist/index.js +81 -2183
- package/dist/indexAudit.js +61 -0
- package/dist/indexStorage.js +58 -0
- package/dist/joinCompiler.js +160 -0
- package/dist/jsonEagerCompiler.js +436 -0
- package/dist/jsonPatch.js +78 -0
- package/dist/jsonPatchAssignments.js +13 -0
- package/dist/jsonPath.js +31 -0
- package/dist/localFirstMixin.js +12 -0
- package/dist/migrate.js +624 -0
- package/dist/migration.js +18 -0
- package/dist/migrations/appliedAtValue.js +8 -0
- package/dist/migrations/applier.js +1085 -0
- package/dist/migrations/boot.js +196 -0
- package/dist/migrations/branchRehearsal.js +122 -0
- package/dist/migrations/columnEquivalence.js +85 -0
- package/dist/migrations/ddlError.js +63 -0
- package/dist/migrations/declaredSchema.js +162 -0
- package/dist/migrations/deployLedger.js +19 -0
- package/dist/migrations/fileBased.js +57 -0
- package/dist/migrations/fileContext.js +482 -0
- package/dist/migrations/fileDiscovery.js +318 -0
- package/dist/migrations/fileSkipProbes.js +117 -0
- package/dist/migrations/fingerprint.js +46 -0
- package/dist/migrations/fkCycles.js +13 -0
- package/dist/migrations/frameworkLiveTables.js +25 -0
- package/dist/migrations/idempotentDdl.js +37 -0
- package/dist/migrations/indexPredicate.js +50 -0
- package/dist/migrations/introspect.js +799 -0
- package/dist/migrations/ledgerRows.js +4 -0
- package/dist/migrations/lock.js +91 -0
- package/dist/migrations/migrationTableExists.js +9 -0
- package/dist/migrations/mssqlColumnDependencies.js +76 -0
- package/dist/migrations/mysqlEngine.js +11 -0
- package/dist/migrations/namespaceCharset.js +51 -0
- package/dist/migrations/planner.js +775 -0
- package/dist/migrations/postgresEnumCheck.js +19 -0
- package/dist/migrations/reactiveTriggerDrift.js +58 -0
- package/dist/migrations/reactiveTriggerName.js +7 -0
- package/dist/migrations/renameMssqlCheck.js +21 -0
- package/dist/migrations/restoreSnapshots.js +206 -0
- package/dist/migrations/resumeLedger.js +86 -0
- package/dist/migrations/rollingDeploy.js +106 -0
- package/dist/migrations/schemaOwner.js +46 -0
- package/dist/migrations/schemaOwnerTable.js +4 -0
- package/dist/migrations/softDropSnapshot.js +20 -0
- package/dist/migrations/sqlLimit.js +8 -0
- package/dist/migrations/sqliteConstraintIdentity.js +97 -0
- package/dist/migrations/sqliteDecimalBoot.js +22 -0
- package/dist/migrations/sqliteDecimalPublication.js +257 -0
- package/dist/migrations/sqliteDecimalReview.js +30 -0
- package/dist/migrations/sqliteDecimalReviewStore.js +188 -0
- package/dist/migrations/sqliteDecimalReviewWitness.js +38 -0
- package/dist/migrations/sqliteDecimalSource.js +69 -0
- package/dist/migrations/sqliteDecimalStage.js +135 -0
- package/dist/migrations/sqliteForeignKeys.js +38 -0
- package/dist/migrations/sqliteMigrationBatch.js +37 -0
- package/dist/migrations/sqliteRetainedSource.js +106 -0
- package/dist/migrations/sqliteRowIdentity.js +63 -0
- package/dist/migrations/sqliteSchemaEpoch.js +12 -0
- package/dist/migrations/sqliteSnapshotGuard.js +10 -0
- package/dist/migrations/sqliteTableContents.js +34 -0
- package/dist/migrations/sqliteTableCopy.js +25 -0
- package/dist/migrations/sqliteTableSchema.js +19 -0
- package/dist/migrations/sqliteWitnessProtection.js +8 -0
- package/dist/migrations/squash.js +81 -0
- package/dist/migrations/storeCharset.js +66 -0
- package/dist/migrations/transactionCause.js +10 -0
- package/dist/migrations/undeclaredCharset.js +40 -0
- package/dist/migrations/uniqueActiveLowering.js +39 -0
- package/dist/mixins.js +22 -0
- package/dist/mssqlDecimalDistinct.js +51 -0
- package/dist/mssqlJsonValueCheck.js +42 -0
- package/dist/mssqlTextStorage.js +9 -0
- package/dist/namespace.js +21 -0
- package/dist/{wire-CG2j7J3f.js → optimisticVersion.js} +2 -2
- package/dist/pendingAttribution.js +79 -0
- package/dist/pluginRef.js +17 -0
- package/dist/predicate.js +266 -0
- package/dist/predicateCoercion.js +13 -0
- package/dist/projectedColumn.js +37 -0
- package/dist/queryBuilder.js +382 -0
- package/dist/rawSql.js +8 -0
- package/dist/relations.js +69 -0
- package/dist/relationsRegistry.js +38 -0
- package/dist/replaceInProgress.js +53 -0
- package/dist/requiredColumns.js +26 -0
- package/dist/residency.js +52 -0
- package/dist/retention.js +62 -0
- package/dist/rowDecoder.js +123 -0
- package/dist/rowKey.js +8 -0
- package/dist/rowSchema.js +31 -0
- package/dist/scopeKey.js +8 -0
- package/dist/seed.js +33 -0
- package/dist/snowflake.js +26 -0
- package/dist/sql.d.ts +27 -6
- package/dist/sql.js +41 -6905
- package/dist/sqlCompiler.js +343 -0
- package/dist/sqlError.js +8 -0
- package/dist/sqlPoolCapacity.js +12 -0
- package/dist/sqliteDecimal.js +22 -0
- package/dist/sqliteDecimalAggregateSql.js +61 -0
- package/dist/sqliteDecimalColumnSql.js +108 -0
- package/dist/sqliteDecimalConversion.js +15 -0
- package/dist/sqliteDecimalCte.js +154 -0
- package/dist/sqliteDecimalEncodeSql.js +32 -0
- package/dist/sqliteDecimalOutputs.js +74 -0
- package/dist/sqliteDecimalPredicate.js +66 -0
- package/dist/sqliteDecimalQuery.js +183 -0
- package/dist/sqliteDecimalQueryPlan.js +37 -0
- package/dist/sqliteDecimalResultSql.js +44 -0
- package/dist/sqliteDecimalRowQuery.js +63 -0
- package/dist/sqliteDecimalSetQuery.js +50 -0
- package/dist/sqliteDecimalSource.js +63 -0
- package/dist/sqliteDecimalStorage.js +29 -0
- package/dist/sqliteDecimalSubquery.js +19 -0
- package/dist/sqliteDecimalWindowQuery.js +196 -0
- package/dist/sqliteValueCoercion.js +4 -0
- package/dist/stampId.js +21 -0
- package/dist/storeErrors.js +9 -0
- package/dist/storeRefusal.js +20 -0
- package/dist/stream.js +36 -0
- package/dist/subjectGraph.js +175 -0
- package/dist/table.js +394 -0
- package/dist/tableRegistry.js +16 -0
- package/dist/tenantSelection.js +27 -0
- package/dist/transactionOutcome.js +97 -0
- package/dist/transientContention.js +36 -0
- package/dist/typedStore.js +16 -0
- package/dist/upsertUpdate.js +20 -0
- package/dist/vectorEmbedding.js +31 -0
- package/dist/view.js +39 -0
- package/dist/wire.js +6 -2
- package/dist/writeAttribution.js +16 -0
- package/dist/writeRecorder.js +37 -0
- package/package.json +3 -3
- package/dist/replaceInProgress-DC88Pdiy.js +0 -3735
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { withMigrationLock as e } from "./lock.js";
|
|
2
|
+
import { withMigrationTransaction as t } from "./transactionCause.js";
|
|
3
|
+
import { Effect as n } from "effect";
|
|
4
|
+
import { createHash as r, randomUUID as i } from "node:crypto";
|
|
5
|
+
import { SqlClient as a } from "effect/sql";
|
|
6
|
+
//#region src/migrations/squash.ts
|
|
7
|
+
var o = (e) => n.gen(function* () {
|
|
8
|
+
let t = yield* a.SqlClient;
|
|
9
|
+
if (!Number.isFinite(Date.parse(e.before))) return yield* n.fail(/* @__PURE__ */ Error("squash: cut-off must be a valid date"));
|
|
10
|
+
let i = yield* t`
|
|
11
|
+
SELECT id, fingerprint, ${t("appliedAt")} FROM _voltro_migration_plans
|
|
12
|
+
WHERE source = 'auto-diff'
|
|
13
|
+
AND ${t("squashedAt")} IS NULL
|
|
14
|
+
AND ${t("appliedAt")} < ${e.before}
|
|
15
|
+
ORDER BY ${t("appliedAt")} DESC, id DESC
|
|
16
|
+
`;
|
|
17
|
+
if (i.length === 0) return yield* n.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
|
|
18
|
+
let o = i[0];
|
|
19
|
+
if (o.fingerprint !== e.fingerprint) return yield* n.fail(/* @__PURE__ */ Error(`squash: latest pre-squash fingerprint (${o.fingerprint.slice(0, 12)}…) differs from current declared-schema fingerprint (${e.fingerprint.slice(0, 12)}…). The cut-off may select an older schema state, or declared changes may not have been applied.\n\nCheck the cut-off and selected history against the current declarations. Apply genuinely pending changes with \`voltro db apply\`; otherwise choose a cut-off whose newest eligible fingerprint matches the current schema.`));
|
|
20
|
+
let s = r("sha256").update(JSON.stringify({
|
|
21
|
+
before: e.before,
|
|
22
|
+
fingerprint: e.fingerprint,
|
|
23
|
+
rows: i.map((e) => [
|
|
24
|
+
e.id,
|
|
25
|
+
e.fingerprint,
|
|
26
|
+
e.appliedAt
|
|
27
|
+
])
|
|
28
|
+
})).digest("hex");
|
|
29
|
+
return {
|
|
30
|
+
eligible: i,
|
|
31
|
+
preview: {
|
|
32
|
+
before: e.before,
|
|
33
|
+
fingerprint: e.fingerprint,
|
|
34
|
+
planIds: i.map((e) => e.id),
|
|
35
|
+
count: i.length,
|
|
36
|
+
token: s
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}), s = (e) => o(e).pipe(n.map((e) => e.preview)), c = (r) => n.gen(function* () {
|
|
40
|
+
let s = yield* a.SqlClient;
|
|
41
|
+
return yield* e(s, t(s, n.gen(function* () {
|
|
42
|
+
let { eligible: e, preview: t } = yield* o(r);
|
|
43
|
+
if (r.expectedPreview !== void 0 && r.expectedPreview !== t.token) return yield* n.fail(/* @__PURE__ */ Error("squash: selected history changed after preview; review a new preview before confirming"));
|
|
44
|
+
yield* s`
|
|
45
|
+
UPDATE _voltro_migration_plans
|
|
46
|
+
SET ${s("squashedAt")} = CURRENT_TIMESTAMP
|
|
47
|
+
WHERE id IN ${s.in(e.map((e) => e.id))}
|
|
48
|
+
`;
|
|
49
|
+
let a = `plan_squash_${i()}`;
|
|
50
|
+
return yield* s`
|
|
51
|
+
INSERT INTO _voltro_migration_plans
|
|
52
|
+
(id, fingerprint, operations, ${s("rollbackPlan")}, ${s("appliedBy")}, environment, source,
|
|
53
|
+
${s("onlineStrategy")}, ${s("durationMs")}, notes, ${s("squashedAt")}, ${s("appliedAt")}, ${s("createdAt")}, ${s("updatedAt")})
|
|
54
|
+
VALUES (
|
|
55
|
+
${a},
|
|
56
|
+
${r.fingerprint},
|
|
57
|
+
${JSON.stringify({
|
|
58
|
+
kind: "squash-snapshot",
|
|
59
|
+
rowsSquashed: e.length
|
|
60
|
+
})},
|
|
61
|
+
${null},
|
|
62
|
+
${r.appliedBy},
|
|
63
|
+
${r.environment},
|
|
64
|
+
${"squash-snapshot"},
|
|
65
|
+
${null},
|
|
66
|
+
${0},
|
|
67
|
+
${r.note ?? null},
|
|
68
|
+
${null},
|
|
69
|
+
CURRENT_TIMESTAMP,
|
|
70
|
+
CURRENT_TIMESTAMP,
|
|
71
|
+
CURRENT_TIMESTAMP
|
|
72
|
+
)
|
|
73
|
+
`, {
|
|
74
|
+
squashedCount: e.length,
|
|
75
|
+
snapshotFingerprint: r.fingerprint,
|
|
76
|
+
snapshotId: a
|
|
77
|
+
};
|
|
78
|
+
})));
|
|
79
|
+
});
|
|
80
|
+
//#endregion
|
|
81
|
+
export { s as previewMigrationSquash, c as squashMigrationPlans };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { isMysqlFamily as e } from "../dialect.js";
|
|
2
|
+
import { isSoftDropSnapshotName as t } from "./frameworkLiveTables.js";
|
|
3
|
+
//#region src/migrations/storeCharset.ts
|
|
4
|
+
var n = ["utf8mb3", "utf8mb4"], r = (e) => e === "utf8mb3" || e === "utf8mb4", i = (e) => {
|
|
5
|
+
switch (e.type) {
|
|
6
|
+
case "text":
|
|
7
|
+
case "enum": return !0;
|
|
8
|
+
case "id": return e.idScheme?.kind !== "numeric" && e.idStorage !== "numeric";
|
|
9
|
+
case "reference": return e.referenceStorage !== "numeric";
|
|
10
|
+
default: return !1;
|
|
11
|
+
}
|
|
12
|
+
}, a = (e, t) => e.map((e) => ({
|
|
13
|
+
...e,
|
|
14
|
+
columns: e.columns.map((e) => i(e) && e.charset === void 0 ? {
|
|
15
|
+
...e,
|
|
16
|
+
charset: t
|
|
17
|
+
} : e)
|
|
18
|
+
})), o = (e) => e.columns.flatMap((e) => e.charset === void 0 ? [] : [{
|
|
19
|
+
column: e.name,
|
|
20
|
+
charset: e.charset
|
|
21
|
+
}]), s = "utf8mb4", c = (e) => e.columns.some((e) => e.type === "json" || e.type === "array" || e.storageType === "json"), l = (n) => {
|
|
22
|
+
if (!e(n.dialect)) return [];
|
|
23
|
+
let r = [];
|
|
24
|
+
for (let e of [...n.live.tables].sort((e, t) => e.name.localeCompare(t.name))) {
|
|
25
|
+
if (t(e.name)) continue;
|
|
26
|
+
let i = o(e);
|
|
27
|
+
if (i.length === 0) continue;
|
|
28
|
+
if (n.charset !== void 0) {
|
|
29
|
+
let t = i.filter((e) => e.charset !== n.charset);
|
|
30
|
+
t.length > 0 && r.push({
|
|
31
|
+
table: e.name,
|
|
32
|
+
kind: "disagrees-with-declaration",
|
|
33
|
+
columns: t,
|
|
34
|
+
expected: n.charset
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (c(e)) {
|
|
39
|
+
let t = i.filter((e) => e.charset !== s);
|
|
40
|
+
t.length > 0 && r.push({
|
|
41
|
+
table: e.name,
|
|
42
|
+
kind: "json-outruns-text",
|
|
43
|
+
columns: t,
|
|
44
|
+
expected: s
|
|
45
|
+
});
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
let a = new Set(i.map((e) => e.charset));
|
|
49
|
+
a.size > 1 && r.push({
|
|
50
|
+
table: e.name,
|
|
51
|
+
kind: "mixed",
|
|
52
|
+
columns: i,
|
|
53
|
+
expected: [...a].sort().join(" / ")
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return r;
|
|
57
|
+
}, u = (e) => {
|
|
58
|
+
let t = e.columns.map((e) => `${e.column} (${e.charset})`).join(", ");
|
|
59
|
+
switch (e.kind) {
|
|
60
|
+
case "disagrees-with-declaration": return `${e.table}: declared ${e.expected}, stored otherwise — ${t}`;
|
|
61
|
+
case "json-outruns-text": return `${e.table}: its json column holds every character (utf8mb4); these text columns do not — ${t}`;
|
|
62
|
+
case "mixed": return `${e.table}: its string columns are not in one character set — ${t}`;
|
|
63
|
+
}
|
|
64
|
+
}, d = "declare the store's character set in app.config.ts — store: { dialect: 'mariadb' | 'mysql', charset: 'utf8mb4' } — and run `voltro db plan`: every table the app declares is created with it and converted to it (a table rewrite; foreign keys are re-created around it). `utf8mb3` is accepted too, for a database that must stay there.";
|
|
65
|
+
//#endregion
|
|
66
|
+
export { n as MYSQL_CHARSETS, d as STORE_CHARSET_REMEDY, o as charsetColumnsOf, i as columnTakesCharset, u as describeStoreCharsetFinding, r as isMysqlCharset, a as stampDeclaredCharset, l as storeCharsetFindings };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Cause as e, Effect as t, Equal as n } from "effect";
|
|
2
|
+
//#region src/migrations/transactionCause.ts
|
|
3
|
+
var r = (r, i) => t.suspend(() => {
|
|
4
|
+
let a;
|
|
5
|
+
return r.withTransaction(i.pipe(t.tapCause((e) => t.sync(() => {
|
|
6
|
+
a = e;
|
|
7
|
+
})))).pipe(t.catchCause((r) => t.failCause(a !== void 0 && !n.equals(a, r) ? e.combine(a, r) : r)));
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { r as withMigrationTransaction };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isFrameworkOwnedLiveTable as e, isSoftDropSnapshotName as t, isStagingTableName as n } from "./frameworkLiveTables.js";
|
|
2
|
+
import { withMigrationLock as r } from "./lock.js";
|
|
3
|
+
import { columnLevelChecksMysql as i } from "./applier.js";
|
|
4
|
+
import { Effect as a } from "effect";
|
|
5
|
+
//#region src/migrations/undeclaredCharset.ts
|
|
6
|
+
var o = "utf8mb4", s = (r, i) => e(r) && !i.has(r) && !r.startsWith("_cloud_") && !r.startsWith("__turso_internal_") && !t(r) && !n(r), c = (e) => e.columnDefault !== null && e.columnDefault.toUpperCase() !== "NULL", l = (e, t, n, r) => {
|
|
7
|
+
if (n !== o) return {
|
|
8
|
+
tables: [],
|
|
9
|
+
left: []
|
|
10
|
+
};
|
|
11
|
+
let i = e.filter((e) => s(e.table, t) && (r === void 0 || r.has(e.table)) && e.charset !== o), a = i.filter((e) => c(e) || e.generated), l = /* @__PURE__ */ new Map();
|
|
12
|
+
for (let e of i) c(e) || e.generated || l.set(e.table, [...l.get(e.table) ?? [], e]);
|
|
13
|
+
return {
|
|
14
|
+
tables: [...l.entries()].sort(([e], [t]) => e.localeCompare(t)).map(([e, t]) => ({
|
|
15
|
+
table: e,
|
|
16
|
+
columns: t
|
|
17
|
+
})),
|
|
18
|
+
left: a
|
|
19
|
+
};
|
|
20
|
+
}, u = (e) => e.tables.length === 0 && e.left.length === 0, d = (e) => [...e.tables.map((e) => `${e.table}: ${e.columns.length} string column${e.columns.length === 1 ? "" : "s"} ${[...new Set(e.columns.map((e) => e.charset))].sort().join("/")} → ${o}`), ...e.left.map((e) => `${e.table}.${e.column} stays ${e.charset}: it has a ${e.generated ? "generation expression" : "default"}, which this step does not rewrite — convert it by hand`)], f = (e) => e.map((e) => Object.fromEntries(Object.entries(e).map(([e, t]) => [e.toLowerCase(), t]))), p = (e) => a.map(e.unsafe("SELECT c.table_name, c.column_name, c.character_set_name, c.column_type, c.is_nullable, c.column_default, c.extra\n FROM information_schema.columns c\n JOIN information_schema.tables t ON t.table_schema = c.table_schema AND t.table_name = c.table_name\n WHERE c.table_schema = DATABASE() AND t.table_type = 'BASE TABLE' AND c.character_set_name IS NOT NULL\n ORDER BY c.table_name, c.ordinal_position"), (e) => f(e).map((e) => ({
|
|
21
|
+
table: String(e.table_name),
|
|
22
|
+
column: String(e.column_name),
|
|
23
|
+
charset: String(e.character_set_name),
|
|
24
|
+
columnType: String(e.column_type),
|
|
25
|
+
nullable: String(e.is_nullable).toUpperCase() === "YES",
|
|
26
|
+
columnDefault: e.column_default === null || e.column_default === void 0 ? null : String(e.column_default),
|
|
27
|
+
generated: /GENERATED/i.test(String(e.extra ?? "")) && !/DEFAULT_GENERATED/i.test(String(e.extra ?? ""))
|
|
28
|
+
}))), m = (e) => `\`${e.replace(/`/g, "``")}\``, h = (e, t = /* @__PURE__ */ new Map()) => e.tables.map((e) => `ALTER TABLE ${m(e.table)} ${e.columns.map((n) => {
|
|
29
|
+
let r = t.get(e.table)?.get(n.column);
|
|
30
|
+
return `MODIFY COLUMN ${m(n.column)} ${n.columnType} CHARACTER SET ${o}${n.nullable ? "" : " NOT NULL"}${r === void 0 ? "" : ` CHECK (${r})`}`;
|
|
31
|
+
}).join(", ")}`), g = (e, t) => a.gen(function* () {
|
|
32
|
+
let n = /* @__PURE__ */ new Map();
|
|
33
|
+
for (let r of t.tables) n.set(r.table, yield* i(e, r.table));
|
|
34
|
+
for (let r of h(t, n)) yield* e.unsafe(r).unprepared;
|
|
35
|
+
}), _ = (e, t) => r(e, a.gen(function* () {
|
|
36
|
+
let n = l(yield* p(e), t.declaredNames, t.charset);
|
|
37
|
+
return yield* g(e, n), n;
|
|
38
|
+
}), { schema: t.lockSchema });
|
|
39
|
+
//#endregion
|
|
40
|
+
export { g as applyUndeclaredCharsetWork, _ as convergeUndeclaredCharset, d as describeUndeclaredCharsetWork, s as isUndeclaredCharsetTable, u as isUndeclaredCharsetWorkEmpty, p as readUndeclaredCharsetColumns, h as undeclaredCharsetStatements, l as undeclaredCharsetWork };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/migrations/uniqueActiveLowering.ts
|
|
2
|
+
var e = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, t = (e) => e.replace(/"/g, "`"), n = (e) => typeof e == "string" ? e : e.name ?? String(e), r = (e, t) => `_ua_${t}_${e}`.slice(0, 64), i = (i, a) => {
|
|
3
|
+
if (a !== "mysql" && a !== "mariadb" || !i.appliedIndexes.some(e)) return i;
|
|
4
|
+
let o = { ...i.fields }, s = [], c = [];
|
|
5
|
+
for (let a of i.appliedIndexes) {
|
|
6
|
+
if (!e(a)) {
|
|
7
|
+
s.push(a);
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
let l = t(a.where), u = [];
|
|
11
|
+
for (let e of a.fields) {
|
|
12
|
+
let t = n(e);
|
|
13
|
+
if (!(t in i.fields)) throw Error(`@voltro/migrate: uniqueActive '${a.name}' on '${i.tableName}' references unknown column '${t}'.`);
|
|
14
|
+
let s = r(a.name, t);
|
|
15
|
+
u.push(s), o[s] = {
|
|
16
|
+
type: "text",
|
|
17
|
+
nullable: !0,
|
|
18
|
+
unique: !1,
|
|
19
|
+
maxLength: 255,
|
|
20
|
+
generatedAs: {
|
|
21
|
+
expr: `CASE WHEN ${l} THEN CAST(\`${t}\` AS CHAR(255)) ELSE NULL END`,
|
|
22
|
+
stored: !0
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
c.push({
|
|
27
|
+
name: a.name,
|
|
28
|
+
fields: u
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
...i,
|
|
33
|
+
fields: o,
|
|
34
|
+
appliedIndexes: s,
|
|
35
|
+
appliedUniques: [...i.appliedUniques ?? [], ...c]
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { i as lowerUniqueActive };
|
package/dist/mixins.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { materializeFields as e } from "./columns.js";
|
|
2
|
+
//#region src/mixins.ts
|
|
3
|
+
var t = (t) => ({
|
|
4
|
+
fields: e(t.fields),
|
|
5
|
+
...t.id === void 0 ? {} : { id: t.id },
|
|
6
|
+
...t.requires === void 0 ? {} : { requires: t.requires },
|
|
7
|
+
...t.indexes === void 0 ? {} : { indexes: t.indexes },
|
|
8
|
+
...t.behaviors === void 0 ? {} : { behaviors: t.behaviors },
|
|
9
|
+
...t.policies === void 0 ? {} : { policies: t.policies }
|
|
10
|
+
}), n = t, r = (e) => {
|
|
11
|
+
let t = /* @__PURE__ */ new Set(), n = [], r = (e) => {
|
|
12
|
+
let i = e.id ?? e;
|
|
13
|
+
if (!t.has(i)) {
|
|
14
|
+
if (t.add(i), e.requires !== void 0) for (let t of e.requires) r(t);
|
|
15
|
+
n.push(e);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
for (let t of e) r(t);
|
|
19
|
+
return n;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { n as defineMixin, t as mixin, r as resolveMixinGraph };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getTable as e } from "./tableRegistry.js";
|
|
2
|
+
import { prepareProjectedColumn as t } from "./projectedColumn.js";
|
|
3
|
+
//#region src/mssqlDecimalDistinct.ts
|
|
4
|
+
var n = (n) => {
|
|
5
|
+
if (!n.distinct && !n.distinctOn?.length || n.aggregations?.length || n.setOp) return;
|
|
6
|
+
let r = t(n), i = n.sourceTable?.tableName === n.table ? n.sourceTable : e(n.table), a = n.joinedProjection ?? (n.projection?.length ? n.projection : Object.keys(i?.fields ?? {})).map((e) => ({
|
|
7
|
+
source: e,
|
|
8
|
+
outputKey: e.split(".").at(-1)
|
|
9
|
+
})), o = {};
|
|
10
|
+
for (let e of a) {
|
|
11
|
+
let t = r(e.source);
|
|
12
|
+
if (!t) return;
|
|
13
|
+
o[e.outputKey] = t;
|
|
14
|
+
}
|
|
15
|
+
if (!Object.values(o).some((e) => e.type === "decimal")) return;
|
|
16
|
+
let s = new Set([
|
|
17
|
+
n.table,
|
|
18
|
+
...(n.ctes ?? []).map((e) => e.name),
|
|
19
|
+
...(n.joins ?? []).map((e) => e.table)
|
|
20
|
+
].map((e) => e.toLowerCase())), c = "__voltro_mssql_decimal_result";
|
|
21
|
+
for (; s.has(c.toLowerCase());) c += "_";
|
|
22
|
+
let l = n.order.length >= 8 && a.length >= 8 ? /* @__PURE__ */ new Map() : void 0;
|
|
23
|
+
if (l) for (let e of a) l.has(e.source) || l.set(e.source, e.outputKey);
|
|
24
|
+
return {
|
|
25
|
+
table: c,
|
|
26
|
+
sourceTable: {
|
|
27
|
+
tableName: c,
|
|
28
|
+
fields: o
|
|
29
|
+
},
|
|
30
|
+
predicate: void 0,
|
|
31
|
+
projection: void 0,
|
|
32
|
+
order: n.order.map((e) => ({
|
|
33
|
+
...e,
|
|
34
|
+
column: (l === void 0 ? a.find((t) => t.source === e.column)?.outputKey : l.get(e.column)) ?? e.column
|
|
35
|
+
})),
|
|
36
|
+
take: n.take,
|
|
37
|
+
skip: n.skip,
|
|
38
|
+
ctes: [...n.ctes ?? [], {
|
|
39
|
+
name: c,
|
|
40
|
+
descriptor: {
|
|
41
|
+
...n,
|
|
42
|
+
ctes: [],
|
|
43
|
+
order: [],
|
|
44
|
+
take: void 0,
|
|
45
|
+
skip: void 0
|
|
46
|
+
}
|
|
47
|
+
}]
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { n as mssqlDecimalDistinct };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/mssqlJsonValueCheck.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
let t = `(N'{"v":' + ${e} + N'}')`, n = `ISJSON(${t}) = 1`, r = `JSON_MODIFY(CASE WHEN ${n} THEN ${t} ELSE N'{}' END, '$.v', NULL)`;
|
|
4
|
+
return `(${e} IS NULL OR (${n} AND ${[
|
|
5
|
+
32,
|
|
6
|
+
9,
|
|
7
|
+
10,
|
|
8
|
+
13
|
|
9
|
+
].reduce((e, t) => `REPLACE(${e}, NCHAR(${t}), N'')`, r)} = N'{}'))`;
|
|
10
|
+
}, t = (e) => {
|
|
11
|
+
let t = [], n = /\s+|N?'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|[A-Za-z_][A-Za-z_0-9]*|[0-9]+|[()+,=]/giy, r = 0;
|
|
12
|
+
for (; r < e.length;) {
|
|
13
|
+
n.lastIndex = r;
|
|
14
|
+
let i = n.exec(e);
|
|
15
|
+
if (!i) return;
|
|
16
|
+
let a = i[0];
|
|
17
|
+
/^\s+$/.test(a) || t.push(/^(?:N?')|^\[/i.test(a) ? a.replace(/^n'/, "N'") : a.toLowerCase()), r = n.lastIndex;
|
|
18
|
+
}
|
|
19
|
+
return t;
|
|
20
|
+
}, n = (n, r) => {
|
|
21
|
+
let i = `[${n.replaceAll("]", "]]")}]`, a = `(N'{"v":'+${i})+N'}'`, o = `isjson(${a})=(1)`, s = `json_modify(case when ${o} then ${a} else N'{}' end,'$.v',NULL)`, c = [
|
|
22
|
+
32,
|
|
23
|
+
9,
|
|
24
|
+
10,
|
|
25
|
+
13
|
|
26
|
+
].reduce((e, t) => `replace(${e},nchar((${t})),N'')`, s), l = [
|
|
27
|
+
["value", e(i)],
|
|
28
|
+
["value", `(${i} IS NULL OR ${o} AND ${c}=N'{}')`],
|
|
29
|
+
["container", `(${i} IS NULL OR ISJSON(${i}) = 1)`],
|
|
30
|
+
["container", `(${i} IS NULL OR isjson(${i})=(1))`]
|
|
31
|
+
], u = t(r);
|
|
32
|
+
if (u) return l.find(([, e]) => {
|
|
33
|
+
let n = t(e);
|
|
34
|
+
return n?.length === u.length && n.every((e, t) => e === u[t]);
|
|
35
|
+
})?.[0];
|
|
36
|
+
}, r = (e) => {
|
|
37
|
+
if (e.length === 0) return;
|
|
38
|
+
let t = e.filter((e) => e.enabled);
|
|
39
|
+
return t.some((e) => e.validation === "container") ? t.some((e) => e.validation === "container" && e.trusted) ? "container" : "unverified" : t.some((e) => e.validation === "value" && e.trusted) ? "value" : "unverified";
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { n as classifyMssqlJsonCheck, r as mssqlJsonValidation, e as mssqlJsonValueCheck };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/mssqlTextStorage.ts
|
|
2
|
+
var e = (e, t) => {
|
|
3
|
+
if (e.type === "text" && e.generatedAs === void 0) {
|
|
4
|
+
if (e.maxLength !== void 0) return e.maxLength;
|
|
5
|
+
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { e as mssqlTextStorageLength };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/namespace.ts
|
|
2
|
+
var e = class extends Error {
|
|
3
|
+
_tag = "TenantNamespaceUnresolved";
|
|
4
|
+
constructor(e) {
|
|
5
|
+
super(e), this.name = "TenantNamespaceUnresolved";
|
|
6
|
+
}
|
|
7
|
+
}, t = class extends Error {
|
|
8
|
+
_tag = "TenantNamespaceInvalid";
|
|
9
|
+
constructor(e) {
|
|
10
|
+
super(e), this.name = "TenantNamespaceInvalid";
|
|
11
|
+
}
|
|
12
|
+
}, n = 63, r = "tenant_", i = (e) => e.toLowerCase().replace(/[^a-z0-9_]/g, "_"), a = (a) => {
|
|
13
|
+
if (a == null || a === "") throw new e("namespace isolation is on but the request has no resolvable tenant (subject.tenantId is null/empty). Refusing to run against a shared/default namespace — this would be a cross-tenant read. Authenticate with a tenant-scoped subject, or disable namespace isolation for this surface.");
|
|
14
|
+
let o = i(a);
|
|
15
|
+
if (o.replace(/_/g, "") === "") throw new t(`tenant id '${a}' has no usable identifier characters after sanitisation — cannot derive a distinct namespace.`);
|
|
16
|
+
let s = `${r}${o}`;
|
|
17
|
+
if (s.length > n) throw new t(`namespace '${s}' for tenant '${a}' exceeds the ${n}-byte identifier limit. Use a shorter tenant id.`);
|
|
18
|
+
return s;
|
|
19
|
+
}, o = (e, t) => e === null ? t : `${e}.${t}`;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { t as TenantNamespaceInvalid, e as TenantNamespaceUnresolved, o as qualifyTable, a as resolveTenantNamespace, i as sanitizeIdentifierFragment };
|
|
@@ -27,6 +27,6 @@ var t = class extends e.TaggedError()("VersionConflict", {
|
|
|
27
27
|
expected: e.expected,
|
|
28
28
|
actual: e.current
|
|
29
29
|
});
|
|
30
|
-
}, a = 1
|
|
30
|
+
}, a = 1;
|
|
31
31
|
//#endregion
|
|
32
|
-
export {
|
|
32
|
+
export { a as INITIAL_VERSION, t as VersionConflict, r as planVersionedUpdate, i as settleVersionedUpdate, n as versionColumnOf };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/pendingAttribution.ts
|
|
2
|
+
var e = 3e4, t = 1e4, n = /* @__PURE__ */ new Map(), r = [], i = (e, t) => {
|
|
3
|
+
let n = r[e];
|
|
4
|
+
r[e] = r[t], r[t] = n, r[e].heapIndex = e, n.heapIndex = t;
|
|
5
|
+
}, a = (e) => {
|
|
6
|
+
for (; e > 0;) {
|
|
7
|
+
let t = Math.floor((e - 1) / 2);
|
|
8
|
+
if (r[t].at <= r[e].at) break;
|
|
9
|
+
i(t, e), e = t;
|
|
10
|
+
}
|
|
11
|
+
return e;
|
|
12
|
+
}, o = (e) => {
|
|
13
|
+
for (; e * 2 + 1 < r.length;) {
|
|
14
|
+
let t = e * 2 + 1;
|
|
15
|
+
if (t + 1 < r.length && r[t + 1].at < r[t].at && t++, r[e].at <= r[t].at) break;
|
|
16
|
+
i(e, t), e = t;
|
|
17
|
+
}
|
|
18
|
+
}, s = (e) => {
|
|
19
|
+
let t = n.get(e.key);
|
|
20
|
+
e.previous ? e.previous.next = e.next : e.next && (t.head = e.next), e.next ? e.next.previous = e.previous : e.previous && (t.tail = e.previous), !e.previous && !e.next && n.delete(e.key);
|
|
21
|
+
let i = e.heapIndex, s = r.pop();
|
|
22
|
+
i < r.length && (r[i] = s, s.heapIndex = i, o(a(i)));
|
|
23
|
+
}, c = (e, t, n) => `${e}\u0000${t}\u0000${String(n)}`, l = (t) => {
|
|
24
|
+
for (; r[0] !== void 0 && t - r[0].at >= e;) s(r[0]);
|
|
25
|
+
}, u = (e, i) => {
|
|
26
|
+
if (i.traceId === void 0 && i.subjectId === void 0 && i.procedure === void 0 && i.via === void 0) return;
|
|
27
|
+
let o = Date.now();
|
|
28
|
+
if (r.length >= t && l(o), r.length >= t) return;
|
|
29
|
+
let s = n.get(e), c = {
|
|
30
|
+
key: e,
|
|
31
|
+
attribution: i,
|
|
32
|
+
at: o,
|
|
33
|
+
heapIndex: r.length,
|
|
34
|
+
previous: s?.tail
|
|
35
|
+
};
|
|
36
|
+
s ? (s.tail.next = c, s.tail = c) : n.set(e, {
|
|
37
|
+
head: c,
|
|
38
|
+
tail: c
|
|
39
|
+
}), r.push(c), a(c.heapIndex);
|
|
40
|
+
}, d = (t) => {
|
|
41
|
+
let r = n.get(t)?.head;
|
|
42
|
+
if (r !== void 0 && (s(r), !(Date.now() - r.at >= e))) return r.attribution;
|
|
43
|
+
}, f = (e) => n.has(e), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), g = 250, _ = (e) => {
|
|
44
|
+
let t = m.get(e);
|
|
45
|
+
if (t === void 0) return;
|
|
46
|
+
m.delete(e);
|
|
47
|
+
let n = h.get(e);
|
|
48
|
+
n !== void 0 && (clearTimeout(n), h.delete(e));
|
|
49
|
+
for (let e of t) e();
|
|
50
|
+
}, v = (e) => {
|
|
51
|
+
p.set(e, (p.get(e) ?? 0) + 1);
|
|
52
|
+
}, y = (e) => {
|
|
53
|
+
let t = (p.get(e) ?? 0) - 1;
|
|
54
|
+
t > 0 ? p.set(e, t) : (p.delete(e), _(e));
|
|
55
|
+
}, b = (e, t, n, r) => {
|
|
56
|
+
let i = n == null ? void 0 : c(e, t, n), a = () => r(i === void 0 ? void 0 : d(i));
|
|
57
|
+
if (i === void 0 || f(i)) {
|
|
58
|
+
a();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
let o = m.get(e);
|
|
62
|
+
if (o === void 0 && (p.get(e) ?? 0) === 0) {
|
|
63
|
+
a();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (o !== void 0) {
|
|
67
|
+
o.push(a);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
m.set(e, [a]);
|
|
71
|
+
let s = setTimeout(() => _(e), g);
|
|
72
|
+
typeof s == "object" && typeof s.unref == "function" && s.unref(), h.set(e, s);
|
|
73
|
+
}, x = () => {
|
|
74
|
+
n.clear(), r.length = 0, p.clear();
|
|
75
|
+
for (let e of h.values()) clearTimeout(e);
|
|
76
|
+
h.clear(), m.clear();
|
|
77
|
+
}, S = () => r.length;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { c as attributionKey, v as beginLocalWrite, d as claimPendingAttribution, x as clearPendingAttribution, y as endLocalWrite, S as pendingAttributionCount, u as registerPendingAttribution, b as resolveEchoAttribution };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ColumnBuilder as e, text as t } from "./columns.js";
|
|
2
|
+
//#region src/pluginRef.ts
|
|
3
|
+
var n = Symbol.for("@voltro/database/pluginRefSpec"), r = (e) => {
|
|
4
|
+
if (typeof e == "object" && e) return ("__definition" in e && typeof e.__definition == "function" ? e.__definition() : e)[n];
|
|
5
|
+
}, i = (r, i = {}) => {
|
|
6
|
+
let a = {
|
|
7
|
+
target: r,
|
|
8
|
+
orphanPolicy: i.orphanPolicy ?? "keep",
|
|
9
|
+
onSoftDelete: i.onSoftDelete ?? !1
|
|
10
|
+
}, o = {
|
|
11
|
+
...t().__definition(),
|
|
12
|
+
[n]: a
|
|
13
|
+
};
|
|
14
|
+
return new e(o);
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { i as pluginRef, r as pluginRefSpecOf };
|