@voltro/database 0.59.0 → 0.60.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/sql.js +43 -43
  3. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -39,6 +39,64 @@ _Changes staged for the next release accumulate here (rolled up from
39
39
 
40
40
  ---
41
41
 
42
+ ## [0.60.0] — 2026-08-31
43
+
44
+ ### ⚠ BREAKING
45
+
46
+ - **@voltro/plugin-sentry** — **A declared failure no longer reaches Sentry by default, and the source-map upload now injects debug ids.** Two separate defects, both found by the same deployment on its first day of real server-side events.
47
+
48
+ **1. The contract was being reported as an incident.** The rpc interceptor skipped only clean interrupts; everything else went to `captureException`. So a failure declared in a procedure's `error:` union — the thing the client gets typed and branches on — arrived as `level: error`, `handled: yes`. The first server-side issue a deployment ever received was a person clicking a team they are not a member of.
49
+
50
+ Effect separates a failure from a defect, this framework leans on that split deliberately (a store refusal was made typed so an app could branch on it; an unlookupable conflict key was deliberately left a defect, because it is a broken call rather than a condition in the data), and a descriptor carries it in `error:`. Reporting both as an incident discarded that one layer up.
51
+
52
+ `shouldCapture` now skips a cause that is failures-ONLY. A defect is reported as before, including a defect that travelled beside a failure — the rule is failures-only rather than "any failure present" precisely so one cannot hide the other. `captureFailures: true` restores the old behaviour; a predicate keeps the ones that are signal.
53
+
54
+ **The browser half moved with it**, or the option would have been half-wired: a rejected call is an rpc error on the client too, published to the client error bus and captured by the browser bridge. `initSentryBrowser` takes the same option and applies it to `rpc.*` events carrying a `_tag`. Route render failures and `reportClientError` calls are never filtered — nobody declared those.
55
+
56
+ **2. `sentry-cli sourcemaps upload` does NOT write debug ids.** `inject` is a separate subcommand; `upload` only uses ids that are already present, and falls back to matching on the artifact NAME when they are not. That fallback cannot work for a server bundle: the artifact is named from `--url-prefix` (`~/chunk- ABC.js`) while the frame carries the absolute path the node process loaded, and nothing rewrites either side.
57
+
58
+ Measured downstream: 4300 artifacts uploaded, release finalised, every frame still minified. Nothing was red — the exact shape this code's own header warns about, an upload that matched nothing looking like one that worked. The comment above the uploader asserted the injection happened, which made it a description standing where a check belonged.
59
+
60
+ `inject` now runs first, over the same directories, and `sourcemapDebugIds.test.ts` drives the real binary to assert an id lands in both the JS and the map. `--url-prefix` stays as the fallback for the browser bundle, whose frames really are URLs.
61
+
62
+ The boot line names the new setting (`sentry active … captureFailures=false`), because a default the framework picks for you is one nobody finds again.
63
+
64
+ **`voltro update` carries you across this** — codemod `0.60.0/01_declared_failures_are_not_incidents`. If you pin versions by hand and never run it, print the notes without changing anything: `voltro update --codemods-only --from <your current version> --dry-run` (this one ships in 0.60.0).
65
+
66
+ ### Added
67
+
68
+ - **@voltro/cli, @voltro/plugin-sentry** — **The web server process now initialises Sentry and reports its own errors.**
69
+
70
+ A framework app runs two server processes. `voltro serve` is the api, where `sentryPlugin()` initialises the SDK through the plugin lifecycle. `voltro start` is the web server — SSR, loaders, ISR, the revalidation legs — and it has no plugin lifecycle, so it had none.
71
+
72
+ That was not a cosmetic difference in boot output. A web pod legitimately logs less than an api pod, because it has no store, no rpc, no scheduler, no workflows and no plugins. What it also had was **no error reporting**: an SSR shell throw is caught, logged and answered with a 500, so no browser ever renders it and the client-side ErrorBoundary bridge cannot see it either. Both ends of the integration worked and the middle was dark — while the docs' "React render error ✅ auto" row, true of the client path, read as covering all of them.
73
+
74
+ Set `SENTRY_DSN` on the web deployment and the boot says `sentry active` with the same message and the same field names as the api half, from the same function — `initSentryServer` in `@voltro/plugin-sentry/server`, which the api plugin now calls too. One init, because a copy of `skipOpenTelemetrySetup`, the traces default, the overrides-first spread and the degrade-on-missing-SDK path would have drifted the moment either half gained a case.
75
+
76
+ Three deliberate asymmetries, each because the two processes are not the same thing:
77
+
78
+ - **`traces: false` on the web side.** The api contributes a span processor to the framework's tracer; the web server has no tracer at all, so tracing on would put `traces: true` in a boot line while nothing produces a span. - **No DSN is SILENT here.** On the api side `sentryPlugin()` is a declaration and an inert one contradicts it. There is no declaration here. - **`@voltro/plugin-sentry` must be installed in the WEB app.** With a DSN set and the package missing, the boot names the command rather than failing — monitoring must never be what stops a deploy.
79
+
80
+ Measured against a real production `voltro start`, both branches. Note that production `voltro start` loads the app's precompiled start bundle, so a web deployment picks this up when that bundle is rebuilt — the framework version alone is not enough.
81
+
82
+ ### Fixed
83
+
84
+ - **@voltro/workflow, @voltro/runtime, @voltro/database, @voltro/cli, @voltro/plugin-sentry** — **Six raw writes removed from production log streams — and the guard that was supposed to catch them rewritten, because it was green for two independent reasons.**
85
+
86
+ A pod tail showed `[voltro:workflow] shard-lock coordination: row-based (dialect=mariadb, mode=row)` sitting between JSON records. `@voltro/logger` is what makes a line JSON in a pod and pretty on a TTY; a `process.stderr.write` bypasses that decision at exactly the place nobody looks, because a dev terminal renders both the same.
87
+
88
+ Fixed at the source: the workflow cluster layer (2), `rpcServer`'s computed-cache warning, the subscription outbox's and the RYW store's `warn`/`onError` defaults — those two are not fallbacks, the callers pass nothing, so the default IS the production path — and the migration file discovery's skip notice, which lands in the migrate job's stream.
89
+
90
+ **The guard is the part worth reading.** `prodLogDiscipline.test.ts` existed for this exact class and reported clean, for two reasons that had to be fixed separately:
91
+
92
+ - Its file set was a hand-written list of five. A guard that opts files IN says nothing about any file added after it was written. - Its matcher was LINE-LOCAL, so `process.stderr.write(` on one line and the `` `[tag] `` on the next never matched — 4 of the 9 call sites in the repo are written that way, including one in a file that WAS on the list. The guard had been pointed straight at an offender and called it clean.
93
+
94
+ It is opt-OUT now: every server-side package's source is scanned, exceptions carry a reason, and a second test fails if an exception's call site disappears — an allowlist entry for code that is gone reads as a rule with a hole in it.
95
+
96
+ Verified against a real `voltro serve` under `NODE_ENV=production`: 35 records, zero framework lines that are not JSON.
97
+
98
+ ---
99
+
42
100
  ## [0.59.0] — 2026-08-30
43
101
 
44
102
  ### ⚠ BREAKING
package/dist/sql.js CHANGED
@@ -3136,7 +3136,7 @@ BEGIN
3136
3136
  return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
3137
3137
  }
3138
3138
  }
3139
- }, na = /* @__PURE__ */ new Set([
3139
+ }, na = T({ scope: "voltro:migrate" }), ra = /* @__PURE__ */ new Set([
3140
3140
  "node_modules",
3141
3141
  "dist",
3142
3142
  "build",
@@ -3145,11 +3145,11 @@ BEGIN
3145
3145
  ".next",
3146
3146
  ".git",
3147
3147
  ".framework"
3148
- ]), ra = async (e) => {
3148
+ ]), ia = async (e) => {
3149
3149
  let t = [], n = async (e) => {
3150
3150
  let r = await ee.readdir(e, { withFileTypes: !0 }).catch(() => []);
3151
3151
  for (let i of r) {
3152
- if (na.has(i.name)) continue;
3152
+ if (ra.has(i.name)) continue;
3153
3153
  let r = te(e, i.name);
3154
3154
  i.isDirectory() ? await n(r) : i.isFile() && m.test(i.name) && t.push(r);
3155
3155
  }
@@ -3158,12 +3158,12 @@ BEGIN
3158
3158
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
3159
3159
  return n.localeCompare(r);
3160
3160
  });
3161
- }, ia = async (e) => {
3161
+ }, aa = async (e) => {
3162
3162
  let t = [];
3163
3163
  for (let n of e) {
3164
3164
  let e = (await import(ne(n).href)).default;
3165
3165
  if (!g(e)) {
3166
- process.stderr.write(`[voltro:migrate] ${n} has no default-exported \`migration(...)\` — skipped\n`);
3166
+ na.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
3167
3167
  continue;
3168
3168
  }
3169
3169
  t.push({
@@ -3172,11 +3172,11 @@ BEGIN
3172
3172
  });
3173
3173
  }
3174
3174
  return t;
3175
- }, aa = (e) => e`
3175
+ }, oa = (e) => e`
3176
3176
  SELECT ${e("id")}
3177
3177
  FROM ${e("_voltro_migration_plans")}
3178
3178
  WHERE ${e("source")} = 'file'
3179
- `.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))), oa = class extends Error {
3179
+ `.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))), sa = class extends Error {
3180
3180
  migrationId;
3181
3181
  file;
3182
3182
  cause;
@@ -3184,7 +3184,7 @@ BEGIN
3184
3184
  constructor(e, t, n) {
3185
3185
  super(`migration ${e}: up() SUCCEEDED but the ledger row could not be written.\n The change IS in the database. It is NOT recorded, so the next run would apply it AGAIN.\n Do not re-run ${t} until this is resolved.\n Cause: ${n instanceof Error ? n.message : String(n)}`), this.migrationId = e, this.file = t, this.cause = n, this.name = "FileMigrationLedgerError";
3186
3186
  }
3187
- }, sa = (e, t, n, r) => S.gen(function* () {
3187
+ }, ca = (e, t, n, r) => S.gen(function* () {
3188
3188
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3189
3189
  sql: e,
3190
3190
  log: {
@@ -3218,10 +3218,10 @@ BEGIN
3218
3218
  }])},
3219
3219
  ${r}, ${n}, ${"file"},
3220
3220
  ${c}, ${l}, ${t.migration.description})
3221
- `.pipe(S.mapError((e) => new oa(t.migration.id, t.file, e))), { durationMs: c };
3222
- }), ca = (e, t) => S.gen(function* () {
3221
+ `.pipe(S.mapError((e) => new sa(t.migration.id, t.file, e))), { durationMs: c };
3222
+ }), la = (e, t) => S.gen(function* () {
3223
3223
  let n = yield* S.tryPromise({
3224
- try: () => ra(te(t, "migrations")),
3224
+ try: () => ia(te(t, "migrations")),
3225
3225
  catch: (e) => e
3226
3226
  });
3227
3227
  if (n.length === 0) return {
@@ -3229,20 +3229,20 @@ BEGIN
3229
3229
  skipped: []
3230
3230
  };
3231
3231
  let r = yield* S.tryPromise({
3232
- try: () => ia(n),
3232
+ try: () => aa(n),
3233
3233
  catch: (e) => e
3234
3234
  });
3235
3235
  if (r.length === 0) return {
3236
3236
  pending: [],
3237
3237
  skipped: []
3238
3238
  };
3239
- let i = new Set(yield* aa(e));
3239
+ let i = new Set(yield* oa(e));
3240
3240
  return {
3241
3241
  pending: r.filter((e) => !i.has(e.migration.id)),
3242
3242
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3243
3243
  };
3244
- }), la = (e, t) => ca(e, t).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), ua = (e, t) => S.gen(function* () {
3245
- let { pending: n, skipped: r } = yield* ca(e, t.projectRoot);
3244
+ }), ua = (e, t) => la(e, t).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), da = (e, t) => S.gen(function* () {
3245
+ let { pending: n, skipped: r } = yield* la(e, t.projectRoot);
3246
3246
  if (n.length === 0) return {
3247
3247
  applied: [],
3248
3248
  skipped: r
@@ -3256,7 +3256,7 @@ BEGIN
3256
3256
  id: r.migration.id,
3257
3257
  file: r.file
3258
3258
  }));
3259
- let { durationMs: n } = yield* sa(e, r, t.env, t.appliedBy);
3259
+ let { durationMs: n } = yield* ca(e, r, t.env, t.appliedBy);
3260
3260
  i.push({
3261
3261
  id: r.migration.id,
3262
3262
  durationMs: n
@@ -3273,18 +3273,18 @@ BEGIN
3273
3273
  applied: i,
3274
3274
  skipped: r
3275
3275
  };
3276
- }), da = (e, t) => e`
3276
+ }), fa = (e, t) => e`
3277
3277
  SELECT ${e("id")}
3278
3278
  FROM ${e("_voltro_migration_plans")}
3279
3279
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3280
3280
  LIMIT 1
3281
- `, fa = (e, t) => S.gen(function* () {
3282
- if (!(yield* da(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3281
+ `, pa = (e, t) => S.gen(function* () {
3282
+ if (!(yield* fa(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3283
3283
  let n = yield* S.tryPromise({
3284
- try: () => ra(te(t.projectRoot, "migrations")),
3284
+ try: () => ia(te(t.projectRoot, "migrations")),
3285
3285
  catch: (e) => e
3286
3286
  }), r = (yield* S.tryPromise({
3287
- try: () => ia(n),
3287
+ try: () => aa(n),
3288
3288
  catch: (e) => e
3289
3289
  })).find((e) => e.migration.id === t.id);
3290
3290
  if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
@@ -3317,7 +3317,7 @@ BEGIN
3317
3317
  } finally {
3318
3318
  yield* O(e, { schema: t.lockSchema }).pipe(S.orDie);
3319
3319
  }
3320
- }), pa = (e) => S.gen(function* () {
3320
+ }), ma = (e) => S.gen(function* () {
3321
3321
  let t = yield* E.SqlClient, n = yield* t`
3322
3322
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3323
3323
  WHERE source = 'auto-diff'
@@ -3362,7 +3362,7 @@ BEGIN
3362
3362
  snapshotFingerprint: e.fingerprint,
3363
3363
  snapshotId: i
3364
3364
  };
3365
- }), ma = { safe: !0 }, ha = (e) => {
3365
+ }), ha = { safe: !0 }, ga = (e) => {
3366
3366
  switch (e.kind) {
3367
3367
  case "drop-column": return {
3368
3368
  safe: !1,
@@ -3389,7 +3389,7 @@ BEGIN
3389
3389
  reason: `old instances read/write "${e.table}"."${e.column}" as ${e.from}; the new ${e.to} type can reject their writes or fail to decode their reads`,
3390
3390
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
3391
3391
  };
3392
- case "alter-column-nullability": return e.toNullable ? ma : {
3392
+ case "alter-column-nullability": return e.toNullable ? ha : {
3393
3393
  safe: !1,
3394
3394
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3395
3395
  remedy: `make code always write "${e.column}" and deploy that first; add NOT NULL in a LATER deploy (with a default to cover the gap)`
@@ -3419,12 +3419,12 @@ BEGIN
3419
3419
  case "drop-unique":
3420
3420
  case "drop-unique-composite":
3421
3421
  case "drop-foreign-key":
3422
- case "drop-check": return ma;
3422
+ case "drop-check": return ha;
3423
3423
  }
3424
- }, ga = (e) => {
3424
+ }, _a = (e) => {
3425
3425
  let t = [];
3426
3426
  for (let n of e) {
3427
- let e = ha(n.op);
3427
+ let e = ga(n.op);
3428
3428
  e.safe || t.push({
3429
3429
  op: n,
3430
3430
  reason: e.reason,
@@ -3432,7 +3432,7 @@ BEGIN
3432
3432
  });
3433
3433
  }
3434
3434
  return t;
3435
- }, _a = (e) => {
3435
+ }, va = (e) => {
3436
3436
  if (!e.enabled || e.unsafeCount === 0) return {
3437
3437
  refuse: !1,
3438
3438
  warnForced: !1,
@@ -3448,18 +3448,18 @@ BEGIN
3448
3448
  warnForced: !1,
3449
3449
  message: `${t}. Old instances would break against the new schema mid-rollout. Split into expand → deploy → contract (see the ⚠ list above), deploy with no overlap (maintenance window / scale-to-zero), or pass --force to override.`
3450
3450
  };
3451
- }, va = (e) => {
3451
+ }, ya = (e) => {
3452
3452
  let t = e.table;
3453
3453
  if (typeof t == "string") return t;
3454
3454
  let n = e.from;
3455
3455
  return typeof n == "string" ? n : void 0;
3456
- }, ya = (e) => ({
3456
+ }, ba = (e) => ({
3457
3457
  kind: e.op.kind,
3458
- table: va(e.op),
3458
+ table: ya(e.op),
3459
3459
  classification: e.classification,
3460
3460
  reason: e.reason,
3461
3461
  blockedFix: e.blocked?.fix
3462
- }), ba = (e) => e.operations.map(ya), xa = async (e) => {
3462
+ }), xa = (e) => e.operations.map(ba), Sa = async (e) => {
3463
3463
  let t = e.log ?? (() => {}), n = {
3464
3464
  branchId: e.branchId,
3465
3465
  mechanism: e.mechanism,
@@ -3478,10 +3478,10 @@ BEGIN
3478
3478
  applied: !1,
3479
3479
  converged: !1,
3480
3480
  residual: r,
3481
- infidelity: ba(o)
3481
+ infidelity: xa(o)
3482
3482
  };
3483
3483
  else {
3484
- let i = await e.plan(), o = ba(i), s = o.filter((e) => e.classification === "lossy"), c = Zi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ya);
3484
+ let i = await e.plan(), o = xa(i), s = o.filter((e) => e.classification === "lossy"), c = Zi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ba);
3485
3485
  if (l.length > 0) a = {
3486
3486
  ...n,
3487
3487
  outcome: "blocked",
@@ -3506,7 +3506,7 @@ BEGIN
3506
3506
  };
3507
3507
  else {
3508
3508
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3509
- let i = ba(await e.replan());
3509
+ let i = xa(await e.replan());
3510
3510
  a = {
3511
3511
  ...n,
3512
3512
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3544,7 +3544,7 @@ BEGIN
3544
3544
  ...a,
3545
3545
  tornDown: o
3546
3546
  };
3547
- }, Sa = (e) => {
3547
+ }, Ca = (e) => {
3548
3548
  switch (e.outcome) {
3549
3549
  case "clean": return 0;
3550
3550
  case "lossy": return 2;
@@ -3553,22 +3553,22 @@ BEGIN
3553
3553
  case "infidelity": return 1;
3554
3554
  case "failed": return 1;
3555
3555
  }
3556
- }, Ca = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, wa = (e) => {
3556
+ }, wa = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Ta = (e) => {
3557
3557
  let t = [];
3558
3558
  if (t.push(`branch rehearsal · ${e.branchId} · mechanism ${e.mechanism}`), t.push(` branched ${e.branchedTables} table(s), replayed ${e.replayedForeignKeys} foreign key(s)`), e.outcome === "failed") t.push(` FAILED: ${e.error ?? "unknown error"}`);
3559
3559
  else if (e.outcome === "infidelity") {
3560
3560
  t.push(" BRANCH IS NOT A FAITHFUL COPY of the parent — the rehearsal proves nothing about your migration."), t.push(" The parent's own schema still differs from the branch by:");
3561
- for (let n of e.infidelity) t.push(Ca(n));
3561
+ for (let n of e.infidelity) t.push(wa(n));
3562
3562
  } else {
3563
3563
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
3564
- for (let n of e.operations) t.push(Ca(n));
3565
- if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(Ca(n));
3564
+ for (let n of e.operations) t.push(wa(n));
3565
+ if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(wa(n));
3566
3566
  }
3567
3567
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3568
- }, Ta = (e, ...t) => ({
3568
+ }, Ea = (e, ...t) => ({
3569
3569
  _tag: "RawSqlFragment",
3570
3570
  strings: [...e],
3571
3571
  values: [...t]
3572
- }), Ea = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3572
+ }), Da = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3573
3573
  //#endregion
3574
- export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN, oa as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, de as VOLTRO_MIGRATION_LOCK_KEY, je as acquireMigrationLock, W as appliedAtValue, It as applyNamespacedSchema, Bi as applyPlan, Et as applySchema, _a as assessRollingDeployGate, Sa as branchRehearsalExitCode, Vn as chunkTables, ha as classifyRollingDeploySafety, I as declaredSnapshot, $e as defaultArrayClause, Qe as defaultClause, N as defaultJsonClause, ta as describeOutcome, Yi as destructiveScope, Xt as detectReactiveTriggerDrift, ni as emitAddIndexMysql, Lr as emitCreateTableMysql, _r as emitDropColumnDdl, vr as emitDropColumnDdlMysql, Tt as emitFrameworkBootstrapSql, Ct as emitNamespaceProvisionDdl, wt as emitNamespacedSchemaSql, St as emitSchemaSql, er as engineFromVersion, Wt as fingerprintSchema, _e as fnv1a64, wa as formatBranchRehearsal, Zt as formatReactiveTriggerDrift, Ji as ignoreTablesFromEnv, $n as introspectSchema, ar as isAlreadySatisfied, g as isFileMigration, Ea as isRawSqlFragment, Ot as isReRunSafeDdl, Fn as mapPgType, o as migration, ve as migrationLockKeyForSchema, ye as migrationLockNameForSchema, Qr as mysqlIndexPrefixFor, Ye as notifyFunctionName, P as numericIdSql, Pn as parseEnumCheck, la as pendingFileMigrationIds, Nn as planMigrations, Lt as provisionTenantNamespace, Je as reactiveTriggerName, pt as reactiveTriggerRepairSql, Ui as recordUpToDate, xa as rehearseMigrationOnBranch, ya as rehearsedOperation, O as releaseMigrationLock, Fr as renderColumnMysql, Ar as renderColumnPg, pe as resolveMigrationLockSchema, U as resolveMysqlEngine, fa as rollbackFileBasedMigration, ga as rollingDeployUnsafeOps, ua as runFileBasedMigrations, Rt as runFrameworkBootstrap, Ft as runMigrate, ea as runPlannedMigrations, Gt as shortFingerprint, Kt as snapshotColumn, Ta as sql, M as sqlType, pa as squashMigrationPlans, Zi as unblockLossy, Me as withMigrationLock };
3574
+ export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN, sa as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, de as VOLTRO_MIGRATION_LOCK_KEY, je as acquireMigrationLock, W as appliedAtValue, It as applyNamespacedSchema, Bi as applyPlan, Et as applySchema, va as assessRollingDeployGate, Ca as branchRehearsalExitCode, Vn as chunkTables, ga as classifyRollingDeploySafety, I as declaredSnapshot, $e as defaultArrayClause, Qe as defaultClause, N as defaultJsonClause, ta as describeOutcome, Yi as destructiveScope, Xt as detectReactiveTriggerDrift, ni as emitAddIndexMysql, Lr as emitCreateTableMysql, _r as emitDropColumnDdl, vr as emitDropColumnDdlMysql, Tt as emitFrameworkBootstrapSql, Ct as emitNamespaceProvisionDdl, wt as emitNamespacedSchemaSql, St as emitSchemaSql, er as engineFromVersion, Wt as fingerprintSchema, _e as fnv1a64, Ta as formatBranchRehearsal, Zt as formatReactiveTriggerDrift, Ji as ignoreTablesFromEnv, $n as introspectSchema, ar as isAlreadySatisfied, g as isFileMigration, Da as isRawSqlFragment, Ot as isReRunSafeDdl, Fn as mapPgType, o as migration, ve as migrationLockKeyForSchema, ye as migrationLockNameForSchema, Qr as mysqlIndexPrefixFor, Ye as notifyFunctionName, P as numericIdSql, Pn as parseEnumCheck, ua as pendingFileMigrationIds, Nn as planMigrations, Lt as provisionTenantNamespace, Je as reactiveTriggerName, pt as reactiveTriggerRepairSql, Ui as recordUpToDate, Sa as rehearseMigrationOnBranch, ba as rehearsedOperation, O as releaseMigrationLock, Fr as renderColumnMysql, Ar as renderColumnPg, pe as resolveMigrationLockSchema, U as resolveMysqlEngine, pa as rollbackFileBasedMigration, _a as rollingDeployUnsafeOps, da as runFileBasedMigrations, Rt as runFrameworkBootstrap, Ft as runMigrate, ea as runPlannedMigrations, Gt as shortFingerprint, Kt as snapshotColumn, Ea as sql, M as sqlType, ma as squashMigrationPlans, Zi as unblockLossy, Me as withMigrationLock };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/database",
3
- "version": "0.59.0",
3
+ "version": "0.60.0",
4
4
  "description": "Browser-safe schema DSL, query builder, and cross-dialect migration planner for Voltro — one schema, every SQL backend.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@effect/sql": "^0.52.0",
47
- "@voltro/logger": "0.59.0",
47
+ "@voltro/logger": "0.60.0",
48
48
  "typeid-js": "^1.2.0",
49
49
  "ulidx": "^2.4.1"
50
50
  },