@abloatai/cli 0.57.0 → 0.58.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 (2) hide show
  1. package/dist/cli.cjs +1074 -559
  2. package/package.json +4 -3
package/dist/cli.cjs CHANGED
@@ -827,9 +827,9 @@ var init_query = __esm({
827
827
  CLOSE = {};
828
828
  Query = class extends Promise {
829
829
  constructor(strings, args, handler, canceller, options = {}) {
830
- let resolve10, reject;
830
+ let resolve11, reject;
831
831
  super((a, b4) => {
832
- resolve10 = a;
832
+ resolve11 = a;
833
833
  reject = b4;
834
834
  });
835
835
  this.tagged = Array.isArray(strings.raw);
@@ -840,7 +840,7 @@ var init_query = __esm({
840
840
  this.options = options;
841
841
  this.state = null;
842
842
  this.statement = null;
843
- this.resolve = (x2) => (this.active = false, resolve10(x2));
843
+ this.resolve = (x2) => (this.active = false, resolve11(x2));
844
844
  this.reject = (x2) => (this.active = false, reject(x2));
845
845
  this.active = false;
846
846
  this.cancelled = null;
@@ -888,12 +888,12 @@ var init_query = __esm({
888
888
  if (this.executed && !this.active)
889
889
  return { done: true };
890
890
  prev && prev();
891
- const promise = new Promise((resolve10, reject) => {
891
+ const promise = new Promise((resolve11, reject) => {
892
892
  this.cursorFn = (value) => {
893
- resolve10({ value, done: false });
893
+ resolve11({ value, done: false });
894
894
  return new Promise((r2) => prev = r2);
895
895
  };
896
- this.resolve = () => (this.active = false, resolve10({ done: true }));
896
+ this.resolve = () => (this.active = false, resolve11({ done: true }));
897
897
  this.reject = (x2) => (this.active = false, reject(x2));
898
898
  });
899
899
  this.execute();
@@ -1491,12 +1491,12 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
1491
1491
  x2.on("drain", drain);
1492
1492
  return x2;
1493
1493
  }
1494
- async function cancel({ pid, secret }, resolve10, reject) {
1494
+ async function cancel({ pid, secret }, resolve11, reject) {
1495
1495
  try {
1496
1496
  cancelMessage = bytes_default().i32(16).i32(80877102).i32(pid).i32(secret).end(16);
1497
1497
  await connect2();
1498
1498
  socket.once("error", reject);
1499
- socket.once("close", resolve10);
1499
+ socket.once("close", resolve11);
1500
1500
  } catch (error2) {
1501
1501
  reject(error2);
1502
1502
  }
@@ -2519,7 +2519,7 @@ var init_subscribe = __esm({
2519
2519
 
2520
2520
  // ../../node_modules/postgres/src/large.js
2521
2521
  function largeObject(sql, oid, mode = 131072 | 262144) {
2522
- return new Promise(async (resolve10, reject) => {
2522
+ return new Promise(async (resolve11, reject) => {
2523
2523
  await sql.begin(async (sql2) => {
2524
2524
  let finish;
2525
2525
  !oid && ([{ oid }] = await sql2`select lo_creat(-1) as oid`);
@@ -2545,7 +2545,7 @@ function largeObject(sql, oid, mode = 131072 | 262144) {
2545
2545
  ) seek
2546
2546
  `
2547
2547
  };
2548
- resolve10(lo);
2548
+ resolve11(lo);
2549
2549
  return new Promise(async (r2) => finish = r2);
2550
2550
  async function readable({
2551
2551
  highWaterMark = 2048 * 8,
@@ -2707,8 +2707,8 @@ function Postgres(a, b4) {
2707
2707
  }
2708
2708
  async function reserve() {
2709
2709
  const queue = queue_default();
2710
- const c = open.length ? open.shift() : await new Promise((resolve10, reject) => {
2711
- const query = { reserve: resolve10, reject };
2710
+ const c = open.length ? open.shift() : await new Promise((resolve11, reject) => {
2711
+ const query = { reserve: resolve11, reject };
2712
2712
  queries.push(query);
2713
2713
  closed.length && connect2(closed.shift(), query);
2714
2714
  });
@@ -2745,9 +2745,9 @@ function Postgres(a, b4) {
2745
2745
  let uncaughtError, result;
2746
2746
  name && await sql2`savepoint ${sql2(name)}`;
2747
2747
  try {
2748
- result = await new Promise((resolve10, reject) => {
2748
+ result = await new Promise((resolve11, reject) => {
2749
2749
  const x2 = fn2(sql2);
2750
- Promise.resolve(Array.isArray(x2) ? Promise.all(x2) : x2).then(resolve10, reject);
2750
+ Promise.resolve(Array.isArray(x2) ? Promise.all(x2) : x2).then(resolve11, reject);
2751
2751
  });
2752
2752
  if (uncaughtError)
2753
2753
  throw uncaughtError;
@@ -2804,8 +2804,8 @@ function Postgres(a, b4) {
2804
2804
  return c.execute(query) ? move(c, busy) : move(c, full);
2805
2805
  }
2806
2806
  function cancel(query) {
2807
- return new Promise((resolve10, reject) => {
2808
- query.state ? query.active ? connection_default(options).cancel(query.state, resolve10, reject) : query.cancelled = { resolve: resolve10, reject } : (queries.remove(query), query.cancelled = true, query.reject(Errors.generic("57014", "canceling statement due to user request")), resolve10());
2807
+ return new Promise((resolve11, reject) => {
2808
+ query.state ? query.active ? connection_default(options).cancel(query.state, resolve11, reject) : query.cancelled = { resolve: resolve11, reject } : (queries.remove(query), query.cancelled = true, query.reject(Errors.generic("57014", "canceling statement due to user request")), resolve11());
2809
2809
  });
2810
2810
  }
2811
2811
  async function end({ timeout = null } = {}) {
@@ -2824,11 +2824,11 @@ function Postgres(a, b4) {
2824
2824
  async function close() {
2825
2825
  await Promise.all(connections.map((c) => c.end()));
2826
2826
  }
2827
- async function destroy(resolve10) {
2827
+ async function destroy(resolve11) {
2828
2828
  await Promise.all(connections.map((c) => c.terminate()));
2829
2829
  while (queries.length)
2830
2830
  queries.shift().reject(Errors.connection("CONNECTION_DESTROYED", options));
2831
- resolve10();
2831
+ resolve11();
2832
2832
  }
2833
2833
  function connect2(c, query) {
2834
2834
  move(c, connecting);
@@ -3349,7 +3349,7 @@ function ambientEnvKeyNote(cwd) {
3349
3349
  return `Note: ${ambient.source} in this directory holds an ABLO_API_KEY, which this command does not load \u2014 it reads only the process environment and your stored login, so a file cannot silently choose a branch. Export the variable, or pass \`--env-file ` + ambient.source + "` to a connect command, to choose it explicitly.";
3350
3350
  }
3351
3351
  function resolveManagementKey() {
3352
- if (process.env.ABLO_MANAGEMENT_KEY) return process.env.ABLO_MANAGEMENT_KEY;
3352
+ if (process.env.ABLO_API_KEY?.startsWith("mk_")) return process.env.ABLO_API_KEY;
3353
3353
  const cfg = readConfig();
3354
3354
  if (!cfg) return void 0;
3355
3355
  const entry = cfg.profiles[activeProfileName(cfg)]?.management;
@@ -3358,7 +3358,7 @@ function resolveManagementKey() {
3358
3358
  return entry.apiKey;
3359
3359
  }
3360
3360
  function resolveOrgManagementKey(options = {}) {
3361
- if (process.env.ABLO_MANAGEMENT_KEY) return process.env.ABLO_MANAGEMENT_KEY;
3361
+ if (process.env.ABLO_API_KEY?.startsWith("mk_")) return process.env.ABLO_API_KEY;
3362
3362
  const cfg = readConfig({ persistMigrations: options.persistConfigMigrations });
3363
3363
  if (!cfg) return void 0;
3364
3364
  const profiles = [.../* @__PURE__ */ new Set([
@@ -3458,7 +3458,7 @@ function requireKey() {
3458
3458
  if (!apiKey) {
3459
3459
  console.error(
3460
3460
  import_picocolors3.default.red(" No project management credential.") + import_picocolors3.default.dim(
3461
- ` Run ${import_picocolors3.default.bold("npx ablo login")} \u2014 or set ${import_picocolors3.default.bold("ABLO_MANAGEMENT_KEY")} to an ${import_picocolors3.default.bold("mk_")} credential.`
3461
+ ` Run ${import_picocolors3.default.bold("npx ablo login")} \u2014 or set ${import_picocolors3.default.bold("ABLO_API_KEY")} to an ${import_picocolors3.default.bold("mk_")} credential.`
3462
3462
  )
3463
3463
  );
3464
3464
  process.exit(1);
@@ -3481,15 +3481,18 @@ async function request(path, apiKey, init3 = {}, baseUrl2) {
3481
3481
  }
3482
3482
  return { status: res.status, body };
3483
3483
  }
3484
+ function projectListResult(status2, body) {
3485
+ if (status2 !== 200) {
3486
+ const code = typeof body === "object" && body !== null && "code" in body ? body.code : void 0;
3487
+ return { ok: false, reason: typeof code === "string" ? code : `HTTP ${status2}` };
3488
+ }
3489
+ const parsed = import_wire.projectListResponseSchema.safeParse(body);
3490
+ return parsed.success ? { ok: true, projects: parsed.data.data } : { ok: false, reason: "the response did not match the project list" };
3491
+ }
3484
3492
  async function listProjects(apiKey, baseUrl2) {
3485
3493
  try {
3486
3494
  const { status: status2, body } = await request("/api/v1/projects", apiKey, {}, baseUrl2);
3487
- if (status2 !== 200) {
3488
- const code = body?.code;
3489
- return { ok: false, reason: typeof code === "string" ? code : `HTTP ${status2}` };
3490
- }
3491
- const parsed = import_wire.projectListResponseSchema.safeParse(body);
3492
- return parsed.success ? { ok: true, projects: parsed.data.data } : { ok: false, reason: "the response did not match the project list" };
3495
+ return projectListResult(status2, body);
3493
3496
  } catch (err) {
3494
3497
  return { ok: false, reason: err instanceof Error ? err.message : "the request failed" };
3495
3498
  }
@@ -3538,6 +3541,10 @@ async function ensureProject(slug, name) {
3538
3541
  return null;
3539
3542
  }
3540
3543
  }
3544
+ function projectDisplayName(p2) {
3545
+ const spelling = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
3546
+ return p2.name && spelling(p2.name) !== spelling(p2.slug) ? p2.name : void 0;
3547
+ }
3541
3548
  function describeKeys(profile) {
3542
3549
  const now = Date.now();
3543
3550
  let usable = 0;
@@ -3566,8 +3573,7 @@ function describeAge(createdAt) {
3566
3573
  function printList(projects2) {
3567
3574
  const active = getActiveProject();
3568
3575
  const profiles = readConfig()?.profiles ?? {};
3569
- const spelling = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
3570
- const nameOf = (p2) => p2.name && spelling(p2.name) !== spelling(p2.slug) ? p2.name : "";
3576
+ const nameOf = (p2) => projectDisplayName(p2) ?? "";
3571
3577
  const showNames = projects2.some((p2) => nameOf(p2) !== "");
3572
3578
  const slugWidth = Math.max(...projects2.map((p2) => p2.slug.length));
3573
3579
  const nameWidth = showNames ? Math.max(...projects2.map((p2) => nameOf(p2).length)) : 0;
@@ -3970,7 +3976,7 @@ var init_observeCliError = __esm({
3970
3976
  import_errorObservation = require("@abloatai/transaction/errorObservation");
3971
3977
  import_errors5 = require("@abloatai/transaction/errors");
3972
3978
  dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
3973
- release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.57.0";
3979
+ release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.58.0";
3974
3980
  initialized = false;
3975
3981
  nativeProcessExit = process.exit.bind(process);
3976
3982
  exitBoundaryInstalled = false;
@@ -4297,7 +4303,7 @@ var init_src2 = __esm({
4297
4303
 
4298
4304
  // src/cliEnvironment.ts
4299
4305
  function cliVersion() {
4300
- return "0.57.0";
4306
+ return "0.58.0";
4301
4307
  }
4302
4308
  function cliOs() {
4303
4309
  const value = (0, import_node_os.platform)();
@@ -4729,16 +4735,9 @@ async function fetchActiveSchema(url, apiKey) {
4729
4735
  clearTimeout(t);
4730
4736
  }
4731
4737
  }
4732
- function conflictStr(c) {
4733
- if (!c) return "";
4734
- const parts = import_schema2.participantKindSchema.options.flatMap((k3) => c[k3] ? [`${k3}:${c[k3]}`] : []);
4735
- return parts.length ? `{${parts.join(",")}}` : "";
4736
- }
4737
4738
  function localModels(schema) {
4738
4739
  const json = JSON.parse((0, import_schema.serializeSchema)(schema));
4739
- const out = /* @__PURE__ */ new Map();
4740
- for (const [key, def] of Object.entries(json.models)) out.set(key, conflictStr(def.conflict));
4741
- return out;
4740
+ return new Set(Object.keys(json.models));
4742
4741
  }
4743
4742
  function printPlan(local, remote) {
4744
4743
  if (!remote?.models) {
@@ -4746,21 +4745,17 @@ function printPlan(local, remote) {
4746
4745
  `);
4747
4746
  return;
4748
4747
  }
4749
- const remoteMap = /* @__PURE__ */ new Map();
4750
- for (const m2 of remote.models) remoteMap.set(m2.key, conflictStr(m2.conflict));
4751
- const added = [...local.keys()].filter((k3) => !remoteMap.has(k3));
4752
- const removed = [...remoteMap.keys()].filter((k3) => !local.has(k3));
4753
- const changed = [...local.keys()].filter((k3) => remoteMap.has(k3) && remoteMap.get(k3) !== local.get(k3));
4748
+ const remoteKeys = new Set(remote.models.map((model) => model.key));
4749
+ const added = [...local].filter((key) => !remoteKeys.has(key));
4750
+ const removed = [...remoteKeys].filter((key) => !local.has(key));
4754
4751
  const verLabel = remote.version != null ? `v${remote.version}` : "active";
4755
- if (added.length === 0 && removed.length === 0 && changed.length === 0) {
4752
+ if (added.length === 0 && removed.length === 0) {
4756
4753
  console.log(` ${import_picocolors5.default.dim("plan")} ${import_picocolors5.default.dim(`no model-level changes vs deployed ${verLabel} (any field changes apply on push)`)}
4757
4754
  `);
4758
4755
  return;
4759
4756
  }
4760
4757
  console.log(` ${import_picocolors5.default.dim("plan")} ${import_picocolors5.default.dim(`vs deployed ${verLabel}:`)}`);
4761
4758
  for (const k3 of added) console.log(` ${import_picocolors5.default.green(`+ ${k3}`)} ${import_picocolors5.default.dim("(new model)")}`);
4762
- for (const k3 of changed)
4763
- console.log(` ${import_picocolors5.default.yellow(`~ ${k3}`)} ${import_picocolors5.default.dim(`conflict ${remoteMap.get(k3) || "(default)"} \u2192 ${local.get(k3) || "(default)"}`)}`);
4764
4759
  for (const k3 of removed) console.log(` ${import_picocolors5.default.red(`- ${k3}`)} ${import_picocolors5.default.dim("(removed \u2014 destructive, needs --force)")}`);
4765
4760
  console.log("");
4766
4761
  }
@@ -5051,7 +5046,7 @@ async function push(argv) {
5051
5046
  }
5052
5047
  process.exit(1);
5053
5048
  }
5054
- var import_picocolors5, import_errors7, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, import_schema2, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT, PUSH_USAGE;
5049
+ var import_picocolors5, import_errors7, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT, PUSH_USAGE;
5055
5050
  var init_push = __esm({
5056
5051
  "src/push.ts"() {
5057
5052
  "use strict";
@@ -5069,7 +5064,6 @@ var init_push = __esm({
5069
5064
  init_target();
5070
5065
  init_theme();
5071
5066
  init_renderError();
5072
- import_schema2 = require("@abloatai/transaction/coordination/schema");
5073
5067
  init_telemetry();
5074
5068
  DEFAULT_SCHEMA_PATH = "ablo/schema.ts";
5075
5069
  DEFAULT_EXPORT = "schema";
@@ -5096,6 +5090,84 @@ var init_push = __esm({
5096
5090
  }
5097
5091
  });
5098
5092
 
5093
+ // src/dbProvider.ts
5094
+ function hostAndPort(hostOrTarget) {
5095
+ const withoutScheme = hostOrTarget.trim().replace(/^[a-z0-9+.-]+:\/\//i, "");
5096
+ const at = withoutScheme.lastIndexOf("@");
5097
+ const withoutUserinfo = at === -1 ? withoutScheme : withoutScheme.slice(at + 1);
5098
+ const authority = withoutUserinfo.split("/")[0] ?? "";
5099
+ const parts = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(authority);
5100
+ return { hostname: (parts?.[1] ?? authority).toLowerCase(), port: parts?.[2] ?? "" };
5101
+ }
5102
+ function inDomain(hostname, domain) {
5103
+ return hostname === domain || hostname.endsWith(`.${domain}`);
5104
+ }
5105
+ function detectProvider(hostOrTarget) {
5106
+ const { hostname } = hostAndPort(hostOrTarget);
5107
+ const spec = PROVIDERS.find((p2) => p2.domains.some((domain) => inDomain(hostname, domain)));
5108
+ return spec?.id ?? "generic";
5109
+ }
5110
+ function detectPooler(hostOrTarget) {
5111
+ const { hostname, port } = hostAndPort(hostOrTarget);
5112
+ const provider = detectProvider(hostOrTarget);
5113
+ const spec = PROVIDERS.find((p2) => p2.id === provider);
5114
+ if (spec?.isPooledHost?.(hostname)) {
5115
+ const direct = spec.directTarget?.(hostOrTarget);
5116
+ return direct === void 0 ? { provider, confidence: "host" } : { provider, direct, confidence: "host" };
5117
+ }
5118
+ if (POOLER_PORTS.has(port)) return { provider, confidence: "port" };
5119
+ return null;
5120
+ }
5121
+ function replicationGrantRole(provider) {
5122
+ const specs = PROVIDERS;
5123
+ const spec = specs.find((candidate) => candidate.id === provider);
5124
+ return spec?.replicationGrantRole ?? null;
5125
+ }
5126
+ function logicalReplicationGuidance(provider) {
5127
+ const spec = PROVIDERS.find((p2) => p2.id === provider);
5128
+ if (spec) return spec.logicalReplication;
5129
+ return `run the ALTER SYSTEM above, then restart Postgres (wal_level is not reloadable). On a managed host that refuses ALTER SYSTEM, set wal_level to logical in its dashboard instead`;
5130
+ }
5131
+ var PROVIDERS, POOLER_PORTS;
5132
+ var init_dbProvider = __esm({
5133
+ "src/dbProvider.ts"() {
5134
+ "use strict";
5135
+ init_cjs_shims();
5136
+ PROVIDERS = [
5137
+ {
5138
+ id: "neon",
5139
+ domains: ["neon.tech"],
5140
+ logicalReplication: `enable logical replication in your Neon project settings \u2014 it can't be set over SQL`,
5141
+ // Neon encodes pooling in the endpoint id, so the direct host is the same
5142
+ // name with the marker removed: a fix the reader applies without a lookup.
5143
+ isPooledHost: (hostname) => hostname.includes("-pooler"),
5144
+ directTarget: (hostOrTarget) => hostOrTarget.replace(/-pooler/i, "")
5145
+ },
5146
+ {
5147
+ id: "supabase",
5148
+ domains: ["supabase.co", "supabase.com"],
5149
+ logicalReplication: `raise wal_level to logical in your Supabase project's database settings`,
5150
+ // Supavisor is a separate host entirely (`aws-0-<region>.pooler.supabase.com`),
5151
+ // so there is no direct host to derive from it.
5152
+ isPooledHost: (hostname) => hostname.endsWith(".pooler.supabase.com")
5153
+ },
5154
+ {
5155
+ id: "rds",
5156
+ // Anchored to the real RDS domains, including the China partition, rather
5157
+ // than a bare `.rds.` anywhere in the name.
5158
+ domains: ["rds.amazonaws.com", "rds.amazonaws.com.cn"],
5159
+ logicalReplication: `set rds.logical_replication = 1 in the instance's parameter group, then reboot`,
5160
+ // RDS Proxy fronts the instance under a `.proxy-` subdomain.
5161
+ isPooledHost: (hostname) => hostname.includes(".proxy-"),
5162
+ // Neither the master user nor rds_superuser carries REPLICATION; AWS keeps
5163
+ // it on rdsadmin and exposes it through this role.
5164
+ replicationGrantRole: "rds_replication"
5165
+ }
5166
+ ];
5167
+ POOLER_PORTS = /* @__PURE__ */ new Set(["6432", "6543"]);
5168
+ }
5169
+ });
5170
+
5099
5171
  // src/remoteValidation.ts
5100
5172
  function dialFailureReason(err) {
5101
5173
  if (err === null || typeof err !== "object") return null;
@@ -5192,76 +5264,6 @@ var init_remoteValidation = __esm({
5192
5264
  }
5193
5265
  });
5194
5266
 
5195
- // src/dbProvider.ts
5196
- function hostAndPort(hostOrTarget) {
5197
- const withoutScheme = hostOrTarget.trim().replace(/^[a-z0-9+.-]+:\/\//i, "");
5198
- const at = withoutScheme.lastIndexOf("@");
5199
- const withoutUserinfo = at === -1 ? withoutScheme : withoutScheme.slice(at + 1);
5200
- const authority = withoutUserinfo.split("/")[0] ?? "";
5201
- const parts = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(authority);
5202
- return { hostname: (parts?.[1] ?? authority).toLowerCase(), port: parts?.[2] ?? "" };
5203
- }
5204
- function inDomain(hostname, domain) {
5205
- return hostname === domain || hostname.endsWith(`.${domain}`);
5206
- }
5207
- function detectProvider(hostOrTarget) {
5208
- const { hostname } = hostAndPort(hostOrTarget);
5209
- const spec = PROVIDERS.find((p2) => p2.domains.some((domain) => inDomain(hostname, domain)));
5210
- return spec?.id ?? "generic";
5211
- }
5212
- function detectPooler(hostOrTarget) {
5213
- const { hostname, port } = hostAndPort(hostOrTarget);
5214
- const provider = detectProvider(hostOrTarget);
5215
- const spec = PROVIDERS.find((p2) => p2.id === provider);
5216
- if (spec?.isPooledHost?.(hostname)) {
5217
- const direct = spec.directTarget?.(hostOrTarget);
5218
- return direct === void 0 ? { provider, confidence: "host" } : { provider, direct, confidence: "host" };
5219
- }
5220
- if (POOLER_PORTS.has(port)) return { provider, confidence: "port" };
5221
- return null;
5222
- }
5223
- function logicalReplicationGuidance(provider) {
5224
- const spec = PROVIDERS.find((p2) => p2.id === provider);
5225
- if (spec) return spec.logicalReplication;
5226
- return `run the ALTER SYSTEM above, then restart Postgres (wal_level is not reloadable). On a managed host that refuses ALTER SYSTEM, set wal_level to logical in its dashboard instead`;
5227
- }
5228
- var PROVIDERS, POOLER_PORTS;
5229
- var init_dbProvider = __esm({
5230
- "src/dbProvider.ts"() {
5231
- "use strict";
5232
- init_cjs_shims();
5233
- PROVIDERS = [
5234
- {
5235
- id: "neon",
5236
- domains: ["neon.tech"],
5237
- logicalReplication: `enable logical replication in your Neon project settings \u2014 it can't be set over SQL`,
5238
- // Neon encodes pooling in the endpoint id, so the direct host is the same
5239
- // name with the marker removed: a fix the reader applies without a lookup.
5240
- isPooledHost: (hostname) => hostname.includes("-pooler"),
5241
- directTarget: (hostOrTarget) => hostOrTarget.replace(/-pooler/i, "")
5242
- },
5243
- {
5244
- id: "supabase",
5245
- domains: ["supabase.co", "supabase.com"],
5246
- logicalReplication: `raise wal_level to logical in your Supabase project's database settings`,
5247
- // Supavisor is a separate host entirely (`aws-0-<region>.pooler.supabase.com`),
5248
- // so there is no direct host to derive from it.
5249
- isPooledHost: (hostname) => hostname.endsWith(".pooler.supabase.com")
5250
- },
5251
- {
5252
- id: "rds",
5253
- // Anchored to the real RDS domains, including the China partition, rather
5254
- // than a bare `.rds.` anywhere in the name.
5255
- domains: ["rds.amazonaws.com", "rds.amazonaws.com.cn"],
5256
- logicalReplication: `set rds.logical_replication = 1 in the instance's parameter group, then reboot`,
5257
- // RDS Proxy fronts the instance under a `.proxy-` subdomain.
5258
- isPooledHost: (hostname) => hostname.includes(".proxy-")
5259
- }
5260
- ];
5261
- POOLER_PORTS = /* @__PURE__ */ new Set(["6432", "6543"]);
5262
- }
5263
- });
5264
-
5265
5267
  // src/connectSetup.ts
5266
5268
  function hostLabel(connectionString) {
5267
5269
  try {
@@ -5293,12 +5295,26 @@ BEGIN
5293
5295
  END LOOP;
5294
5296
  END $$;`;
5295
5297
  }
5298
+ function replicationBypassSql(input) {
5299
+ if (input.canGrantBypassRls) return [];
5300
+ return input.tables.flatMap((table) => {
5301
+ const qualified = `${quoteIdent(input.schema)}.${quoteIdent(table)}`;
5302
+ const policy = quoteIdent(`${input.role}_snapshot`);
5303
+ return [
5304
+ // CREATE POLICY has no IF NOT EXISTS, and every step here is safe to
5305
+ // re-run, so the drop carries the idempotency.
5306
+ `DROP POLICY IF EXISTS ${policy} ON ${qualified};`,
5307
+ `CREATE POLICY ${policy} ON ${qualified} FOR SELECT TO ${quoteIdent(input.role)} USING (true);`
5308
+ ];
5309
+ });
5310
+ }
5296
5311
  function connectSetupSql(input) {
5297
5312
  const role = input.role && input.role.length > 0 ? input.role : import_footprint.ABLO_REPLICATION_ROLE;
5298
5313
  const writeRole = input.writeRole && input.writeRole.length > 0 ? input.writeRole : import_footprint.ABLO_WRITE_ROLE;
5299
5314
  const tables = input.tables ?? [];
5300
5315
  const schema = input.schema ?? "public";
5301
5316
  const publication = input.publication;
5317
+ const canGrantBypassRls = input.canGrantBypassRls !== false;
5302
5318
  const qualifiedTables = tables.map((table) => `${quoteIdent(schema)}.${quoteIdent(table)}`);
5303
5319
  const publicationTarget = tables.length > 0 ? `FOR TABLE ${qualifiedTables.join(", ")}` : "FOR ALL TABLES";
5304
5320
  const tableList = qualifiedTables.join(", ");
@@ -5318,9 +5334,11 @@ function connectSetupSql(input) {
5318
5334
  // 3. A least-privilege role: it can stream replication and SELECT the
5319
5335
  // published tables, including the initial snapshot of RLS-protected tables.
5320
5336
  // Logical decoding already exposes every published row independently of
5321
- // RLS; BYPASSRLS makes the ordinary SELECT snapshot match that same scope.
5322
- `CREATE ROLE ${quoteIdent(role)} WITH NOSUPERUSER BYPASSRLS NOCREATEDB NOCREATEROLE REPLICATION NOINHERIT LOGIN PASSWORD '<password>';`,
5337
+ // RLS, so the reader needs the ordinary SELECT snapshot to match that same
5338
+ // scope. How it gets there depends on what this admin may grant.
5339
+ `CREATE ROLE ${quoteIdent(role)} WITH NOSUPERUSER ${canGrantBypassRls ? "BYPASSRLS " : ""}NOCREATEDB NOCREATEROLE ${canGrantBypassRls ? "REPLICATION NOINHERIT" : "NOREPLICATION INHERIT"} LOGIN PASSWORD '<password>';`,
5323
5340
  ...replicationReadGrants,
5341
+ ...replicationBypassSql({ role, tables, schema, canGrantBypassRls }),
5324
5342
  // 4. A distinct DML role: no replication, role administration, ownership,
5325
5343
  // schema creation, or DDL. It runs NOBYPASSRLS with row_security on, so on a
5326
5344
  // table that HAS row-level-security policies they govern its writes and it
@@ -5466,7 +5484,15 @@ On Neon enable Logical Replication in the project (Console \u2192 Settings \u219
5466
5484
  `SELECT rolreplication, rolsuper, rolbypassrls FROM pg_roles WHERE rolname = current_user`
5467
5485
  );
5468
5486
  const role = roleRows[0];
5469
- const hasReplication = Boolean(role && (role.rolreplication || role.rolsuper));
5487
+ const grantRole = opts.replicationGrantRole ?? null;
5488
+ const viaGrant = grantRole ? (await sql.unsafe(
5489
+ `SELECT EXISTS (
5490
+ SELECT 1 FROM pg_roles r
5491
+ WHERE r.rolname = $1 AND pg_has_role(current_user, r.oid, 'MEMBER')
5492
+ ) AS member`,
5493
+ [grantRole]
5494
+ ))[0]?.member === true : false;
5495
+ const hasReplication = Boolean(role && (role.rolreplication || role.rolsuper)) || viaGrant;
5470
5496
  items.push(
5471
5497
  hasReplication ? {
5472
5498
  ok: true,
@@ -5486,6 +5512,20 @@ On RDS: GRANT rds_replication TO <your_role>;`
5486
5512
  JOIN pg_class c ON c.relnamespace = n.oid AND c.relname = pt.tablename
5487
5513
  WHERE pt.pubname = $1 AND pt.schemaname = $2
5488
5514
  AND row_security_active(c.oid)
5515
+ AND NOT EXISTS (
5516
+ SELECT 1 FROM pg_policies p
5517
+ WHERE p.schemaname = pt.schemaname
5518
+ AND p.tablename = pt.tablename
5519
+ AND p.permissive = 'PERMISSIVE'
5520
+ AND p.cmd IN ('ALL', 'SELECT')
5521
+ AND p.qual = 'true'
5522
+ -- Membership, not containment: pg_policies.roles is name[], while
5523
+ -- ARRAY['public'] is text[]. Postgres has no name[] @> text[] operator, so
5524
+ -- the containment spelling fails at execution rather than at parse time:
5525
+ -- the probe threw instead of reporting, which reads as an unreachable
5526
+ -- database rather than a readable one.
5527
+ AND ('public' = ANY(p.roles) OR current_user = ANY(p.roles))
5528
+ )
5489
5529
  ORDER BY table_name`,
5490
5530
  [publication, schema]
5491
5531
  );
@@ -5495,7 +5535,9 @@ On RDS: GRANT rds_replication TO <your_role>;`
5495
5535
  ok: false,
5496
5536
  label: `${rlsRelevant.length} published table${rlsRelevant.length === 1 ? "" : "s"} hide historical rows behind RLS`,
5497
5537
  fix: `ALTER ROLE current_user WITH BYPASSRLS;
5498
- Logical replication already exposes every published row; this lets the ordinary initial SELECT read that same scope.`
5538
+ Where the provider reserves that attribute (Amazon RDS, Aurora), give the reader a policy instead:
5539
+ CREATE POLICY <reader>_snapshot ON <table> FOR SELECT TO <reader> USING (true);
5540
+ Logical replication already exposes every published row; either lets the ordinary initial SELECT read that same scope.`
5499
5541
  }
5500
5542
  );
5501
5543
  const badRows = await sql.unsafe(
@@ -6033,7 +6075,7 @@ async function fetchDataSourceState(apiUrl3, apiKey, timeoutMs = 4e3) {
6033
6075
  async function readLocalSchemaHash(schemaPath = DEFAULT_SCHEMA_PATH) {
6034
6076
  try {
6035
6077
  const schema = await loadSchema(schemaPath, DEFAULT_EXPORT);
6036
- return (0, import_schema4.schemaHash)(schema);
6078
+ return (0, import_schema3.schemaHash)(schema);
6037
6079
  } catch {
6038
6080
  return null;
6039
6081
  }
@@ -6104,7 +6146,7 @@ function blockers(input) {
6104
6146
  }
6105
6147
  return found;
6106
6148
  }
6107
- var import_wire5, import_schema4, WRITE_READY_VERDICT;
6149
+ var import_wire5, import_schema3, WRITE_READY_VERDICT;
6108
6150
  var init_readiness = __esm({
6109
6151
  "src/readiness.ts"() {
6110
6152
  "use strict";
@@ -6113,7 +6155,7 @@ var init_readiness = __esm({
6113
6155
  init_push();
6114
6156
  init_dbProvider();
6115
6157
  init_remoteValidation();
6116
- import_schema4 = require("@abloatai/transaction/schema");
6158
+ import_schema3 = require("@abloatai/transaction/schema");
6117
6159
  WRITE_READY_VERDICT = "write infrastructure is ready. Your database constraints and row-level policies still apply.";
6118
6160
  }
6119
6161
  });
@@ -6141,7 +6183,17 @@ function connectApplyPlan(input) {
6141
6183
  const schema = input.schema ?? "public";
6142
6184
  const publication = input.publication;
6143
6185
  const provider = input.provider ?? "generic";
6144
- const recipe = connectSetupSql({ tables, role, writeRole, schema, publication });
6186
+ const canGrantBypassRls = input.canGrantBypassRls !== false;
6187
+ const canGrantReplication = input.canGrantReplication !== false;
6188
+ const grantedReplicationRole = canGrantReplication ? null : replicationGrantRole(provider);
6189
+ const recipe = connectSetupSql({
6190
+ tables,
6191
+ role,
6192
+ writeRole,
6193
+ schema,
6194
+ publication,
6195
+ canGrantBypassRls
6196
+ });
6145
6197
  const isWal = (s) => s.startsWith("ALTER SYSTEM SET wal_level");
6146
6198
  const isPublication = (s) => s.startsWith("CREATE PUBLICATION");
6147
6199
  const isRoleCreate = (s) => s.startsWith("CREATE ROLE ");
@@ -6189,19 +6241,46 @@ END $$;`
6189
6241
  {
6190
6242
  key: "replication-role",
6191
6243
  title: "Create the read-only login Ablo reads with",
6192
- detail: `${role} \u2014 it can follow your changes and snapshot the same published rows, including through RLS`,
6244
+ detail: canGrantBypassRls ? `${role} \u2014 it can follow your changes and snapshot the same published rows, including through RLS` : `${role} \u2014 it can follow your changes, and reads the published rows through a SELECT policy of its own, because this provider reserves BYPASSRLS`,
6193
6245
  sql: [
6194
6246
  idempotentRole(
6195
6247
  role,
6196
- "NOSUPERUSER BYPASSRLS NOCREATEDB NOCREATEROLE REPLICATION NOINHERIT",
6248
+ // NOINHERIT everywhere the capability is an attribute: the reader
6249
+ // should hold what it was given and nothing that arrives later.
6250
+ // Where the provider lends REPLICATION as a role instead, the
6251
+ // membership only confers it by inheriting — a NOINHERIT member holds
6252
+ // it in name, `pg_has_role(..., 'USAGE')` is false, and replication
6253
+ // fails while every "was it granted" check says yes. So the grant
6254
+ // path inherits, and its only membership is the one granted below.
6255
+ `NOSUPERUSER ${canGrantBypassRls ? "BYPASSRLS " : ""}NOCREATEDB NOCREATEROLE ${canGrantReplication ? "REPLICATION" : "NOREPLICATION"} ${grantedReplicationRole ? "INHERIT" : "NOINHERIT"}`,
6197
6256
  input.credentials.replicationClause,
6198
6257
  input.rotate === true
6199
6258
  ),
6200
6259
  // Unlike a password, this is a required invariant rather than secret
6201
6260
  // material owned by one plane. Re-assert it for an existing pre-snapshot
6202
6261
  // role so `connect apply` repairs the exact upgrade gap that otherwise
6203
- // certifies an RLS-filtered empty snapshot as complete.
6204
- `ALTER ROLE ${quoteIdent(role)} WITH BYPASSRLS;`
6262
+ // certifies an RLS-filtered empty snapshot as complete. Where the
6263
+ // attribute cannot be granted at all, the policies in the grants step
6264
+ // carry the same invariant.
6265
+ ...canGrantBypassRls ? [`ALTER ROLE ${quoteIdent(role)} WITH BYPASSRLS;`] : [],
6266
+ // The provider keeps REPLICATION on an internal superuser and lends it
6267
+ // through a role. Without this the reader authenticates and then cannot
6268
+ // open a replication slot, which surfaces far from its cause.
6269
+ ...grantedReplicationRole ? [
6270
+ // WITH INHERIT TRUE, because Postgres 16 records inheritance on
6271
+ // the MEMBERSHIP rather than only on the role. A member that does
6272
+ // not inherit holds the grant without holding what it carries:
6273
+ // `pg_has_role(..., 'MEMBER')` is true, `USAGE` is false, and
6274
+ // replication does not work while every "was it granted" check
6275
+ // says yes.
6276
+ //
6277
+ // Stated on the grant rather than left to the role's default so
6278
+ // it also repairs a reader created before this path existed.
6279
+ // `ALTER ROLE ... INHERIT` does not: it changes the default for
6280
+ // FUTURE memberships and leaves the recorded one untouched, which
6281
+ // is a fix that reports success and changes nothing.
6282
+ `GRANT ${quoteIdent(grantedReplicationRole)} TO ${quoteIdent(role)} WITH INHERIT TRUE;`
6283
+ ] : []
6205
6284
  ]
6206
6285
  },
6207
6286
  {
@@ -6301,14 +6380,14 @@ function reapplyBlocker(input) {
6301
6380
  }
6302
6381
  async function adminCanCreateRoles(sql) {
6303
6382
  const rows = await sql.unsafe(
6304
- `SELECT rolname, rolsuper, rolcreaterole FROM pg_roles WHERE rolname = current_user`
6383
+ `SELECT rolname, rolsuper, rolcreaterole, rolbypassrls, rolreplication FROM pg_roles WHERE rolname = current_user`
6305
6384
  );
6306
6385
  return rows[0] ?? null;
6307
6386
  }
6308
6387
  async function schemaDeclaredTables() {
6309
6388
  try {
6310
6389
  const schema = await loadSchema(DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT);
6311
- const json = JSON.parse((0, import_schema5.serializeSchema)(schema));
6390
+ const json = JSON.parse((0, import_schema4.serializeSchema)(schema));
6312
6391
  const tables = Object.entries(json.models).map(([key, model]) => model.tableName ?? key);
6313
6392
  return tables.length > 0 ? tables : null;
6314
6393
  } catch {
@@ -6381,7 +6460,7 @@ function alreadyConnectedElsewhere(held) {
6381
6460
  const where = held.project ? `project ${held.project}, branch ${held.branch}` : `branch ${held.branch}`;
6382
6461
  return `This database schema is already connected to ${where}. A (database, schema) binding belongs to one plane at a time.`;
6383
6462
  }
6384
- var import_wire6, import_schema5;
6463
+ var import_wire6, import_schema4;
6385
6464
  var init_connectPreflight = __esm({
6386
6465
  "src/connectPreflight.ts"() {
6387
6466
  "use strict";
@@ -6390,7 +6469,7 @@ var init_connectPreflight = __esm({
6390
6469
  import_wire6 = require("@abloatai/transaction/wire");
6391
6470
  init_controlPlane();
6392
6471
  init_push();
6393
- import_schema5 = require("@abloatai/transaction/schema");
6472
+ import_schema4 = require("@abloatai/transaction/schema");
6394
6473
  init_readiness();
6395
6474
  }
6396
6475
  });
@@ -6722,7 +6801,16 @@ ${ambient}` : ""}`,
6722
6801
  walAlreadyLogical: walReady,
6723
6802
  provider,
6724
6803
  existingPublication,
6725
- inheritGrants
6804
+ inheritGrants,
6805
+ // Read off the connected admin rather than guessed from the hostname. A
6806
+ // role can only hand out an attribute it holds, and on RDS and Aurora
6807
+ // BYPASSRLS is reserved to `rdsadmin`, so the recipe substitutes explicit
6808
+ // SELECT policies for the reader.
6809
+ canGrantBypassRls: capability?.rolbypassrls === true,
6810
+ // Same rule, second attribute: RDS and Aurora keep REPLICATION on
6811
+ // rdsadmin and lend it as `rds_replication`, so the recipe grants that
6812
+ // role rather than setting an attribute this admin cannot pass on.
6813
+ canGrantReplication: capability?.rolreplication === true
6726
6814
  });
6727
6815
  const steps = buildPlan("scram-verifier");
6728
6816
  if (pubReconcile.removed.length > 0 || pubReconcile.recreated) {
@@ -6804,7 +6892,14 @@ ${ambient}` : ""}`,
6804
6892
  }
6805
6893
  const replicationProbe = await probeAsRole(
6806
6894
  replicationUrl,
6807
- (sql) => probeReadiness(sql, { coordinatedTables, schema: args.schema, publication })
6895
+ (sql) => probeReadiness(sql, {
6896
+ coordinatedTables,
6897
+ schema: args.schema,
6898
+ publication,
6899
+ // The reader may hold REPLICATION through the provider's role rather than
6900
+ // the attribute, which is the only shape available on RDS and Aurora.
6901
+ replicationGrantRole: replicationGrantRole(provider)
6902
+ })
6808
6903
  );
6809
6904
  const writeProbe = await probeAsRole(
6810
6905
  writeUrl,
@@ -7454,7 +7549,11 @@ ${ambient}` : ""}`,
7454
7549
  `);
7455
7550
  const replication = await probeAndReport(dbUrl, "replication", {
7456
7551
  schema: args.schema,
7457
- publication
7552
+ publication,
7553
+ // Derived from the host being dialled: where the provider lends REPLICATION
7554
+ // as a role rather than granting the attribute, membership is what the
7555
+ // reader actually holds.
7556
+ replicationGrantRole: replicationGrantRole(detectProvider(dbUrl))
7458
7557
  });
7459
7558
  console.log(`
7460
7559
  ${import_picocolors12.default.bold("Direct-write role")}
@@ -7747,6 +7846,7 @@ var init_connect = __esm({
7747
7846
  init_cjs_shims();
7748
7847
  import_errors11 = require("@abloatai/transaction/errors");
7749
7848
  import_picocolors12 = __toESM(require_picocolors(), 1);
7849
+ init_dbProvider();
7750
7850
  init_src();
7751
7851
  import_footprint3 = require("@abloatai/transaction/footprint");
7752
7852
  init_dbRole();
@@ -7993,7 +8093,7 @@ var require_util = __commonJS({
7993
8093
  return path;
7994
8094
  }
7995
8095
  exports2.normalize = normalize;
7996
- function join8(aRoot, aPath) {
8096
+ function join9(aRoot, aPath) {
7997
8097
  if (aRoot === "") {
7998
8098
  aRoot = ".";
7999
8099
  }
@@ -8025,7 +8125,7 @@ var require_util = __commonJS({
8025
8125
  }
8026
8126
  return joined;
8027
8127
  }
8028
- exports2.join = join8;
8128
+ exports2.join = join9;
8029
8129
  exports2.isAbsolute = function(aPath) {
8030
8130
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
8031
8131
  };
@@ -8198,7 +8298,7 @@ var require_util = __commonJS({
8198
8298
  parsed.path = parsed.path.substring(0, index + 1);
8199
8299
  }
8200
8300
  }
8201
- sourceURL = join8(urlGenerate(parsed), sourceURL);
8301
+ sourceURL = join9(urlGenerate(parsed), sourceURL);
8202
8302
  }
8203
8303
  return normalize(sourceURL);
8204
8304
  }
@@ -28218,9 +28318,9 @@ ${lanes.join("\n")}
28218
28318
  return getSpanOfTokenAtPosition(sourceFile, node.pos);
28219
28319
  }
28220
28320
  Debug.assert(!isJSDoc(errorNode));
28221
- const isMissing = nodeIsMissing(errorNode);
28222
- const pos = isMissing || isJsxText(node) ? errorNode.pos : skipTrivia(sourceFile.text, errorNode.pos);
28223
- if (isMissing) {
28321
+ const isMissing2 = nodeIsMissing(errorNode);
28322
+ const pos = isMissing2 || isJsxText(node) ? errorNode.pos : skipTrivia(sourceFile.text, errorNode.pos);
28323
+ if (isMissing2) {
28224
28324
  Debug.assert(pos === errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
28225
28325
  Debug.assert(pos === errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
28226
28326
  } else {
@@ -132697,7 +132797,7 @@ ${lanes.join("\n")}
132697
132797
  }
132698
132798
  }
132699
132799
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
132700
- const resolve10 = factory2.createUniqueName("resolve");
132800
+ const resolve11 = factory2.createUniqueName("resolve");
132701
132801
  const reject = factory2.createUniqueName("reject");
132702
132802
  const parameters = [
132703
132803
  factory2.createParameterDeclaration(
@@ -132706,7 +132806,7 @@ ${lanes.join("\n")}
132706
132806
  /*dotDotDotToken*/
132707
132807
  void 0,
132708
132808
  /*name*/
132709
- resolve10
132809
+ resolve11
132710
132810
  ),
132711
132811
  factory2.createParameterDeclaration(
132712
132812
  /*modifiers*/
@@ -132723,7 +132823,7 @@ ${lanes.join("\n")}
132723
132823
  factory2.createIdentifier("require"),
132724
132824
  /*typeArguments*/
132725
132825
  void 0,
132726
- [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve10, reject]
132826
+ [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve11, reject]
132727
132827
  )
132728
132828
  )
132729
132829
  ]);
@@ -172646,9 +172746,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
172646
172746
  const sourceFile = getValidSourceFile(fileName);
172647
172747
  const span = createTextSpanFromBounds(start, end);
172648
172748
  const formatContext = ts_formatting_exports.getFormatContext(formatOptions, host);
172649
- return flatMap(deduplicate(errorCodes68, equateValues, compareValues), (errorCode) => {
172749
+ return flatMap(deduplicate(errorCodes68, equateValues, compareValues), (errorCode2) => {
172650
172750
  cancellationToken.throwIfCancellationRequested();
172651
- return ts_codefix_exports.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences });
172751
+ return ts_codefix_exports.getFixes({ errorCode: errorCode2, sourceFile, span, program, host, cancellationToken, formatContext, preferences });
172652
172752
  });
172653
172753
  }
172654
172754
  function getCombinedCodeFix(scope, fixId56, formatOptions, preferences = emptyOptions) {
@@ -174486,8 +174586,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174486
174586
  fixIds: [fixId2],
174487
174587
  errorCodes: errorCodes2,
174488
174588
  getCodeActions: function getCodeActionsToAddMissingAsync(context) {
174489
- const { sourceFile, errorCode, cancellationToken, program, span } = context;
174490
- const diagnostic = find(program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span, errorCode));
174589
+ const { sourceFile, errorCode: errorCode2, cancellationToken, program, span } = context;
174590
+ const diagnostic = find(program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span, errorCode2));
174491
174591
  const directSpan = diagnostic && diagnostic.relatedInformation && find(diagnostic.relatedInformation, (r2) => r2.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code);
174492
174592
  const decl = getFixableErrorSpanDeclaration(sourceFile, directSpan);
174493
174593
  if (!decl) {
@@ -174549,8 +174649,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174549
174649
  });
174550
174650
  return decl;
174551
174651
  }
174552
- function getIsMatchingAsyncError(span, errorCode) {
174553
- return ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code);
174652
+ function getIsMatchingAsyncError(span, errorCode2) {
174653
+ return ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode2 && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code);
174554
174654
  }
174555
174655
  var fixId3 = "addMissingAwait";
174556
174656
  var propertyAccessCode = Diagnostics.Property_0_does_not_exist_on_type_1.code;
@@ -174581,16 +174681,16 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174581
174681
  fixIds: [fixId3],
174582
174682
  errorCodes: errorCodes3,
174583
174683
  getCodeActions: function getCodeActionsToAddMissingAwait(context) {
174584
- const { sourceFile, errorCode, span, cancellationToken, program } = context;
174585
- const expression = getAwaitErrorSpanExpression(sourceFile, errorCode, span, cancellationToken, program);
174684
+ const { sourceFile, errorCode: errorCode2, span, cancellationToken, program } = context;
174685
+ const expression = getAwaitErrorSpanExpression(sourceFile, errorCode2, span, cancellationToken, program);
174586
174686
  if (!expression) {
174587
174687
  return;
174588
174688
  }
174589
174689
  const checker = context.program.getTypeChecker();
174590
174690
  const trackChanges = (cb) => ts_textChanges_exports.ChangeTracker.with(context, cb);
174591
174691
  return compact([
174592
- getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges),
174593
- getUseSiteFix(context, expression, errorCode, checker, trackChanges)
174692
+ getDeclarationSiteFix(context, expression, errorCode2, checker, trackChanges),
174693
+ getUseSiteFix(context, expression, errorCode2, checker, trackChanges)
174594
174694
  ]);
174595
174695
  },
174596
174696
  getAllCodeActions: (context) => {
@@ -174607,18 +174707,18 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174607
174707
  });
174608
174708
  }
174609
174709
  });
174610
- function getAwaitErrorSpanExpression(sourceFile, errorCode, span, cancellationToken, program) {
174710
+ function getAwaitErrorSpanExpression(sourceFile, errorCode2, span, cancellationToken, program) {
174611
174711
  const expression = getFixableErrorSpanExpression(sourceFile, span);
174612
- return expression && isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program) && isInsideAwaitableBody(expression) ? expression : void 0;
174712
+ return expression && isMissingAwaitError(sourceFile, errorCode2, span, cancellationToken, program) && isInsideAwaitableBody(expression) ? expression : void 0;
174613
174713
  }
174614
- function getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges, fixedDeclarations) {
174714
+ function getDeclarationSiteFix(context, expression, errorCode2, checker, trackChanges, fixedDeclarations) {
174615
174715
  const { sourceFile, program, cancellationToken } = context;
174616
174716
  const awaitableInitializers = findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker);
174617
174717
  if (awaitableInitializers) {
174618
174718
  const initializerChanges = trackChanges((t) => {
174619
- forEach(awaitableInitializers.initializers, ({ expression: expression2 }) => makeChange3(t, errorCode, sourceFile, checker, expression2, fixedDeclarations));
174719
+ forEach(awaitableInitializers.initializers, ({ expression: expression2 }) => makeChange3(t, errorCode2, sourceFile, checker, expression2, fixedDeclarations));
174620
174720
  if (fixedDeclarations && awaitableInitializers.needsSecondPassForFixAll) {
174621
- makeChange3(t, errorCode, sourceFile, checker, expression, fixedDeclarations);
174721
+ makeChange3(t, errorCode2, sourceFile, checker, expression, fixedDeclarations);
174622
174722
  }
174623
174723
  });
174624
174724
  return createCodeFixActionWithoutFixAll(
@@ -174628,14 +174728,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174628
174728
  );
174629
174729
  }
174630
174730
  }
174631
- function getUseSiteFix(context, expression, errorCode, checker, trackChanges, fixedDeclarations) {
174632
- const changes = trackChanges((t) => makeChange3(t, errorCode, context.sourceFile, checker, expression, fixedDeclarations));
174731
+ function getUseSiteFix(context, expression, errorCode2, checker, trackChanges, fixedDeclarations) {
174732
+ const changes = trackChanges((t) => makeChange3(t, errorCode2, context.sourceFile, checker, expression, fixedDeclarations));
174633
174733
  return createCodeFixAction(fixId3, changes, Diagnostics.Add_await, fixId3, Diagnostics.Fix_all_expressions_possibly_missing_await);
174634
174734
  }
174635
- function isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program) {
174735
+ function isMissingAwaitError(sourceFile, errorCode2, span, cancellationToken, program) {
174636
174736
  const checker = program.getTypeChecker();
174637
174737
  const diagnostics = checker.getDiagnostics(sourceFile, cancellationToken);
174638
- return some(diagnostics, ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_forget_to_use_await.code));
174738
+ return some(diagnostics, ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode2 && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_forget_to_use_await.code));
174639
174739
  }
174640
174740
  function findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker) {
174641
174741
  const identifiers = getIdentifiersFromErrorSpanExpression(expression, checker);
@@ -174720,7 +174820,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174720
174820
  function isInsideAwaitableBody(node) {
174721
174821
  return node.flags & 65536 || !!findAncestor(node, (ancestor) => ancestor.parent && isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor || isBlock(ancestor) && (ancestor.parent.kind === 262 || ancestor.parent.kind === 218 || ancestor.parent.kind === 219 || ancestor.parent.kind === 174));
174722
174822
  }
174723
- function makeChange3(changeTracker, errorCode, sourceFile, checker, insertionSite, fixedDeclarations) {
174823
+ function makeChange3(changeTracker, errorCode2, sourceFile, checker, insertionSite, fixedDeclarations) {
174724
174824
  if (isForOfStatement(insertionSite.parent) && !insertionSite.parent.awaitModifier) {
174725
174825
  const exprType = checker.getTypeAtLocation(insertionSite);
174726
174826
  const asyncIter = checker.getAnyAsyncIterableType();
@@ -174745,7 +174845,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174745
174845
  const newNode = checker.getPromisedTypeOfPromise(type) ? factory.createAwaitExpression(side) : side;
174746
174846
  changeTracker.replaceNode(sourceFile, side, newNode);
174747
174847
  }
174748
- } else if (errorCode === propertyAccessCode && isPropertyAccessExpression(insertionSite.parent)) {
174848
+ } else if (errorCode2 === propertyAccessCode && isPropertyAccessExpression(insertionSite.parent)) {
174749
174849
  if (fixedDeclarations && isIdentifier2(insertionSite.parent.expression)) {
174750
174850
  const symbol = checker.getSymbolAtLocation(insertionSite.parent.expression);
174751
174851
  if (symbol && fixedDeclarations.has(getSymbolId(symbol))) {
@@ -174758,7 +174858,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
174758
174858
  factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite.parent.expression))
174759
174859
  );
174760
174860
  insertLeadingSemicolonIfNeeded(changeTracker, insertionSite.parent.expression, sourceFile);
174761
- } else if (contains(callableConstructableErrorCodes, errorCode) && isCallOrNewExpression(insertionSite.parent)) {
174861
+ } else if (contains(callableConstructableErrorCodes, errorCode2) && isCallOrNewExpression(insertionSite.parent)) {
174762
174862
  if (fixedDeclarations && isIdentifier2(insertionSite)) {
174763
174863
  const symbol = checker.getSymbolAtLocation(insertionSite);
174764
174864
  if (symbol && fixedDeclarations.has(getSymbolId(symbol))) {
@@ -177531,10 +177631,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
177531
177631
  registerCodeFix({
177532
177632
  errorCodes: errorCodes19,
177533
177633
  getCodeActions(context) {
177534
- const { errorCode, preferences, sourceFile, span, program } = context;
177634
+ const { errorCode: errorCode2, preferences, sourceFile, span, program } = context;
177535
177635
  const info = getFixInfos(
177536
177636
  context,
177537
- errorCode,
177637
+ errorCode2,
177538
177638
  span.start,
177539
177639
  /*useAutoImportProvider*/
177540
177640
  true
@@ -178472,14 +178572,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
178472
178572
  return { kind: 3, moduleSpecifierKind: void 0, moduleSpecifier, importKind, addAsTypeOnly, useRequire };
178473
178573
  }
178474
178574
  }
178475
- function getFixInfos(context, errorCode, pos, useAutoImportProvider) {
178575
+ function getFixInfos(context, errorCode2, pos, useAutoImportProvider) {
178476
178576
  const symbolToken = getTokenAtPosition(context.sourceFile, pos);
178477
178577
  let info;
178478
- if (errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
178578
+ if (errorCode2 === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
178479
178579
  info = getFixesInfoForUMDImport(context, symbolToken);
178480
178580
  } else if (!isIdentifier2(symbolToken)) {
178481
178581
  return void 0;
178482
- } else if (errorCode === Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code) {
178582
+ } else if (errorCode2 === Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code) {
178483
178583
  const symbolName2 = single(getSymbolNamesToImport(context.sourceFile, context.program.getTypeChecker(), symbolToken, context.program.getCompilerOptions()));
178484
178584
  const fix = getTypeOnlyPromotionFix(context.sourceFile, symbolToken, symbolName2, context.program);
178485
178585
  return fix && [{ fix, symbolName: symbolName2, errorIdentifierText: symbolToken.text }];
@@ -179309,11 +179409,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179309
179409
  registerCodeFix({
179310
179410
  errorCodes: errorCodes21,
179311
179411
  getCodeActions: function getCodeActionsToFixOverrideModifierIssues(context) {
179312
- const { errorCode, span } = context;
179313
- const info = errorCodeFixIdMap[errorCode];
179412
+ const { errorCode: errorCode2, span } = context;
179413
+ const info = errorCodeFixIdMap[errorCode2];
179314
179414
  if (!info) return emptyArray;
179315
179415
  const { descriptions, fixId: fixId56, fixAllDescriptions } = info;
179316
- const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => dispatchChanges(changes2, context, errorCode, span.start));
179416
+ const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => dispatchChanges(changes2, context, errorCode2, span.start));
179317
179417
  return [
179318
179418
  createCodeFixActionMaybeFixAll(fixName, changes, descriptions, fixId56, fixAllDescriptions)
179319
179419
  ];
@@ -179328,8 +179428,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179328
179428
  dispatchChanges(changes, context, code, start);
179329
179429
  })
179330
179430
  });
179331
- function dispatchChanges(changeTracker, context, errorCode, pos) {
179332
- switch (errorCode) {
179431
+ function dispatchChanges(changeTracker, context, errorCode2, pos) {
179432
+ switch (errorCode2) {
179333
179433
  case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code:
179334
179434
  case Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code:
179335
179435
  case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code:
@@ -179342,7 +179442,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179342
179442
  case Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code:
179343
179443
  return doRemoveOverrideModifierChange(changeTracker, context.sourceFile, pos);
179344
179444
  default:
179345
- Debug.fail("Unexpected error code: " + errorCode);
179445
+ Debug.fail("Unexpected error code: " + errorCode2);
179346
179446
  }
179347
179447
  }
179348
179448
  function doAddOverrideModifierChange(changeTracker, sourceFile, pos) {
@@ -179715,8 +179815,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179715
179815
  registerCodeFix({
179716
179816
  errorCodes: errorCodes26,
179717
179817
  getCodeActions(context) {
179718
- const { sourceFile, errorCode } = context;
179719
- const info = getInfo8(sourceFile, context.span.start, context, errorCode);
179818
+ const { sourceFile, errorCode: errorCode2 } = context;
179819
+ const info = getInfo8(sourceFile, context.span.start, context, errorCode2);
179720
179820
  if (!info) return void 0;
179721
179821
  const { node, suggestedSymbol } = info;
179722
179822
  const target = getEmitScriptTarget(context.host.getCompilationSettings());
@@ -179730,10 +179830,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179730
179830
  if (info) doChange18(changes, context.sourceFile, info.node, info.suggestedSymbol, target);
179731
179831
  })
179732
179832
  });
179733
- function getInfo8(sourceFile, pos, context, errorCode) {
179833
+ function getInfo8(sourceFile, pos, context, errorCode2) {
179734
179834
  const node = getTokenAtPosition(sourceFile, pos);
179735
179835
  const parent2 = node.parent;
179736
- if ((errorCode === Diagnostics.No_overload_matches_this_call.code || errorCode === Diagnostics.Type_0_is_not_assignable_to_type_1.code) && !isJsxAttribute(parent2)) return void 0;
179836
+ if ((errorCode2 === Diagnostics.No_overload_matches_this_call.code || errorCode2 === Diagnostics.Type_0_is_not_assignable_to_type_1.code) && !isJsxAttribute(parent2)) return void 0;
179737
179837
  const checker = context.program.getTypeChecker();
179738
179838
  let suggestedSymbol;
179739
179839
  if (isPropertyAccessExpression(parent2) && parent2.name === node) {
@@ -179824,8 +179924,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179824
179924
  errorCodes: errorCodes27,
179825
179925
  fixIds: [fixIdAddReturnStatement, fixRemoveBracesFromArrowFunctionBody, fixIdWrapTheBlockWithParen],
179826
179926
  getCodeActions: function getCodeActionsToCorrectReturnValue(context) {
179827
- const { program, sourceFile, span: { start }, errorCode } = context;
179828
- const info = getInfo9(program.getTypeChecker(), sourceFile, start, errorCode);
179927
+ const { program, sourceFile, span: { start }, errorCode: errorCode2 } = context;
179928
+ const info = getInfo9(program.getTypeChecker(), sourceFile, start, errorCode2);
179829
179929
  if (!info) return void 0;
179830
179930
  if (info.kind === 0) {
179831
179931
  return append(
@@ -179960,11 +180060,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
179960
180060
  }
179961
180061
  return checker.isTypeAssignableTo(exprType, type);
179962
180062
  }
179963
- function getInfo9(checker, sourceFile, position, errorCode) {
180063
+ function getInfo9(checker, sourceFile, position, errorCode2) {
179964
180064
  const node = getTokenAtPosition(sourceFile, position);
179965
180065
  if (!node.parent) return void 0;
179966
180066
  const declaration = findAncestor(node.parent, isFunctionLikeDeclaration);
179967
- switch (errorCode) {
180067
+ switch (errorCode2) {
179968
180068
  case Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value.code:
179969
180069
  if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) return void 0;
179970
180070
  return getFixInfo(
@@ -180159,11 +180259,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
180159
180259
  }));
180160
180260
  }
180161
180261
  });
180162
- function getInfo10(sourceFile, tokenPos, errorCode, checker, program) {
180262
+ function getInfo10(sourceFile, tokenPos, errorCode2, checker, program) {
180163
180263
  var _a, _b;
180164
180264
  const token = getTokenAtPosition(sourceFile, tokenPos);
180165
180265
  const parent2 = token.parent;
180166
- if (errorCode === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code) {
180266
+ if (errorCode2 === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code) {
180167
180267
  if (!(token.kind === 19 && isObjectLiteralExpression(parent2) && isCallExpression(parent2.parent))) return void 0;
180168
180268
  const argIndex = findIndex(parent2.parent.arguments, (arg) => arg === parent2);
180169
180269
  if (argIndex < 0) return void 0;
@@ -181020,10 +181120,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
181020
181120
  registerCodeFix({
181021
181121
  errorCodes: errorCodes31,
181022
181122
  getCodeActions: function getCodeActionsToFixNotFoundModule(context) {
181023
- const { host, sourceFile, span: { start }, errorCode } = context;
181024
- const packageName = errorCode === errorCannotFindImplicitJsxImport ? getJSXImplicitImportBase(context.program.getCompilerOptions(), sourceFile) : tryGetImportedPackageName(sourceFile, start);
181123
+ const { host, sourceFile, span: { start }, errorCode: errorCode2 } = context;
181124
+ const packageName = errorCode2 === errorCannotFindImplicitJsxImport ? getJSXImplicitImportBase(context.program.getCompilerOptions(), sourceFile) : tryGetImportedPackageName(sourceFile, start);
181025
181125
  if (packageName === void 0) return void 0;
181026
- const typesPackageName = getTypesPackageNameToInstall(packageName, host, errorCode);
181126
+ const typesPackageName = getTypesPackageNameToInstall(packageName, host, errorCode2);
181027
181127
  return typesPackageName === void 0 ? [] : [createCodeFixAction(
181028
181128
  fixName2,
181029
181129
  /*changes*/
@@ -181595,7 +181695,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
181595
181695
  registerCodeFix({
181596
181696
  errorCodes: errorCodes43,
181597
181697
  getCodeActions(context) {
181598
- const { errorCode, sourceFile, program, cancellationToken } = context;
181698
+ const { errorCode: errorCode2, sourceFile, program, cancellationToken } = context;
181599
181699
  const checker = program.getTypeChecker();
181600
181700
  const sourceFiles = program.getSourceFiles();
181601
181701
  const token = getTokenAtPosition(sourceFile, context.span.start);
@@ -181671,7 +181771,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
181671
181771
  result.push(createDeleteFix(deletion, [Diagnostics.Remove_unused_declaration_for_Colon_0, name.getText(sourceFile)]));
181672
181772
  }
181673
181773
  }
181674
- const prefix = ts_textChanges_exports.ChangeTracker.with(context, (t) => tryPrefixDeclaration(t, errorCode, sourceFile, token));
181774
+ const prefix = ts_textChanges_exports.ChangeTracker.with(context, (t) => tryPrefixDeclaration(t, errorCode2, sourceFile, token));
181675
181775
  if (prefix.length) {
181676
181776
  result.push(createCodeFixAction(fixName3, prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible));
181677
181777
  }
@@ -181797,8 +181897,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
181797
181897
  changes.delete(sourceFile, parent2);
181798
181898
  }
181799
181899
  }
181800
- function tryPrefixDeclaration(changes, errorCode, sourceFile, token) {
181801
- if (errorCode === Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code) return;
181900
+ function tryPrefixDeclaration(changes, errorCode2, sourceFile, token) {
181901
+ if (errorCode2 === Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code) return;
181802
181902
  if (token.kind === 140) {
181803
181903
  token = cast(token.parent, isInferTypeNode).typeParameter.name;
181804
181904
  }
@@ -181938,14 +182038,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
181938
182038
  fixIds: [fixId34],
181939
182039
  getAllCodeActions: (context) => codeFixAll(context, errorCodes44, (changes, diag2) => doChange27(changes, diag2.file, diag2.start, diag2.length, diag2.code))
181940
182040
  });
181941
- function doChange27(changes, sourceFile, start, length2, errorCode) {
182041
+ function doChange27(changes, sourceFile, start, length2, errorCode2) {
181942
182042
  const token = getTokenAtPosition(sourceFile, start);
181943
182043
  const statement = findAncestor(token, isStatement);
181944
182044
  if (statement.getStart(sourceFile) !== token.getStart(sourceFile)) {
181945
182045
  const logData = JSON.stringify({
181946
182046
  statementKind: Debug.formatSyntaxKind(statement.kind),
181947
182047
  tokenKind: Debug.formatSyntaxKind(token.kind),
181948
- errorCode,
182048
+ errorCode: errorCode2,
181949
182049
  start,
181950
182050
  length: length2
181951
182051
  });
@@ -183268,7 +183368,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183268
183368
  registerCodeFix({
183269
183369
  errorCodes: errorCodes51,
183270
183370
  getCodeActions(context) {
183271
- const { sourceFile, program, span: { start }, errorCode, cancellationToken, host, preferences } = context;
183371
+ const { sourceFile, program, span: { start }, errorCode: errorCode2, cancellationToken, host, preferences } = context;
183272
183372
  const token = getTokenAtPosition(sourceFile, start);
183273
183373
  let declaration;
183274
183374
  const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => {
@@ -183276,7 +183376,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183276
183376
  changes2,
183277
183377
  sourceFile,
183278
183378
  token,
183279
- errorCode,
183379
+ errorCode2,
183280
183380
  program,
183281
183381
  cancellationToken,
183282
183382
  /*markSeen*/
@@ -183286,7 +183386,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183286
183386
  );
183287
183387
  });
183288
183388
  const name = declaration && getNameOfDeclaration(declaration);
183289
- return !name || changes.length === 0 ? void 0 : [createCodeFixAction(fixId40, changes, [getDiagnostic(errorCode, token), getTextOfNode(name)], fixId40, Diagnostics.Infer_all_types_from_usage)];
183389
+ return !name || changes.length === 0 ? void 0 : [createCodeFixAction(fixId40, changes, [getDiagnostic(errorCode2, token), getTextOfNode(name)], fixId40, Diagnostics.Infer_all_types_from_usage)];
183290
183390
  },
183291
183391
  fixIds: [fixId40],
183292
183392
  getAllCodeActions(context) {
@@ -183297,8 +183397,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183297
183397
  });
183298
183398
  }
183299
183399
  });
183300
- function getDiagnostic(errorCode, token) {
183301
- switch (errorCode) {
183400
+ function getDiagnostic(errorCode2, token) {
183401
+ switch (errorCode2) {
183302
183402
  case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
183303
183403
  case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
183304
183404
  return isSetAccessorDeclaration(getContainingFunction(token)) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage;
@@ -183312,8 +183412,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183312
183412
  return Diagnostics.Infer_type_of_0_from_usage;
183313
183413
  }
183314
183414
  }
183315
- function mapSuggestionDiagnostic(errorCode) {
183316
- switch (errorCode) {
183415
+ function mapSuggestionDiagnostic(errorCode2) {
183416
+ switch (errorCode2) {
183317
183417
  case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code:
183318
183418
  return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code;
183319
183419
  case Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
@@ -183331,16 +183431,16 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183331
183431
  case Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
183332
183432
  return Diagnostics.Member_0_implicitly_has_an_1_type.code;
183333
183433
  }
183334
- return errorCode;
183434
+ return errorCode2;
183335
183435
  }
183336
- function doChange33(changes, sourceFile, token, errorCode, program, cancellationToken, markSeen, host, preferences) {
183436
+ function doChange33(changes, sourceFile, token, errorCode2, program, cancellationToken, markSeen, host, preferences) {
183337
183437
  if (!isParameterPropertyModifier(token.kind) && token.kind !== 80 && token.kind !== 26 && token.kind !== 110) {
183338
183438
  return void 0;
183339
183439
  }
183340
183440
  const { parent: parent2 } = token;
183341
183441
  const importAdder = createImportAdder(sourceFile, program, preferences, host);
183342
- errorCode = mapSuggestionDiagnostic(errorCode);
183343
- switch (errorCode) {
183442
+ errorCode2 = mapSuggestionDiagnostic(errorCode2);
183443
+ switch (errorCode2) {
183344
183444
  // Variable and Property declarations
183345
183445
  case Diagnostics.Member_0_implicitly_has_an_1_type.code:
183346
183446
  case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
@@ -183381,7 +183481,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183381
183481
  return void 0;
183382
183482
  }
183383
183483
  let declaration;
183384
- switch (errorCode) {
183484
+ switch (errorCode2) {
183385
183485
  // Parameter declarations
183386
183486
  case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
183387
183487
  if (isSetAccessorDeclaration(containingFunction)) {
@@ -183420,7 +183520,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
183420
183520
  }
183421
183521
  break;
183422
183522
  default:
183423
- return Debug.fail(String(errorCode));
183523
+ return Debug.fail(String(errorCode2));
183424
183524
  }
183425
183525
  importAdder.writeFixes(changes);
183426
183526
  return declaration;
@@ -219332,8 +219432,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
219332
219432
  installPackage(options) {
219333
219433
  this.packageInstallId++;
219334
219434
  const request3 = { kind: "installPackage", ...options, id: this.packageInstallId };
219335
- const promise = new Promise((resolve10, reject) => {
219336
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve10, reject });
219435
+ const promise = new Promise((resolve11, reject) => {
219436
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve11, reject });
219337
219437
  });
219338
219438
  this.installer.send(request3);
219339
219439
  return promise;
@@ -221634,7 +221734,7 @@ var require_path_browserify = __commonJS({
221634
221734
  }
221635
221735
  var posix = {
221636
221736
  // path.resolve([from ...], to)
221637
- resolve: function resolve10() {
221737
+ resolve: function resolve11() {
221638
221738
  var resolvedPath = "";
221639
221739
  var resolvedAbsolute = false;
221640
221740
  var cwd;
@@ -221681,7 +221781,7 @@ var require_path_browserify = __commonJS({
221681
221781
  assertPath(path);
221682
221782
  return path.length > 0 && path.charCodeAt(0) === 47;
221683
221783
  },
221684
- join: function join8() {
221784
+ join: function join9() {
221685
221785
  if (arguments.length === 0)
221686
221786
  return ".";
221687
221787
  var joined;
@@ -226534,41 +226634,41 @@ var require_queue = __commonJS({
226534
226634
  queue.drained = drained;
226535
226635
  return queue;
226536
226636
  function push2(value) {
226537
- var p2 = new Promise(function(resolve10, reject) {
226637
+ var p2 = new Promise(function(resolve11, reject) {
226538
226638
  pushCb(value, function(err, result) {
226539
226639
  if (err) {
226540
226640
  reject(err);
226541
226641
  return;
226542
226642
  }
226543
- resolve10(result);
226643
+ resolve11(result);
226544
226644
  });
226545
226645
  });
226546
226646
  p2.catch(noop3);
226547
226647
  return p2;
226548
226648
  }
226549
226649
  function unshift(value) {
226550
- var p2 = new Promise(function(resolve10, reject) {
226650
+ var p2 = new Promise(function(resolve11, reject) {
226551
226651
  unshiftCb(value, function(err, result) {
226552
226652
  if (err) {
226553
226653
  reject(err);
226554
226654
  return;
226555
226655
  }
226556
- resolve10(result);
226656
+ resolve11(result);
226557
226657
  });
226558
226658
  });
226559
226659
  p2.catch(noop3);
226560
226660
  return p2;
226561
226661
  }
226562
226662
  function drained() {
226563
- var p2 = new Promise(function(resolve10) {
226663
+ var p2 = new Promise(function(resolve11) {
226564
226664
  process.nextTick(function() {
226565
226665
  if (queue.idle()) {
226566
- resolve10();
226666
+ resolve11();
226567
226667
  } else {
226568
226668
  var previousDrain = queue.drain;
226569
226669
  queue.drain = function() {
226570
226670
  if (typeof previousDrain === "function") previousDrain();
226571
- resolve10();
226671
+ resolve11();
226572
226672
  queue.drain = previousDrain;
226573
226673
  };
226574
226674
  }
@@ -227065,9 +227165,9 @@ var require_stream3 = __commonJS({
227065
227165
  });
227066
227166
  }
227067
227167
  _getStat(filepath) {
227068
- return new Promise((resolve10, reject) => {
227168
+ return new Promise((resolve11, reject) => {
227069
227169
  this._stat(filepath, this._fsStatSettings, (error, stats) => {
227070
- return error === null ? resolve10(stats) : reject(error);
227170
+ return error === null ? resolve11(stats) : reject(error);
227071
227171
  });
227072
227172
  });
227073
227173
  }
@@ -227092,10 +227192,10 @@ var require_async5 = __commonJS({
227092
227192
  this._readerStream = new stream_1.default(this._settings);
227093
227193
  }
227094
227194
  dynamic(root, options) {
227095
- return new Promise((resolve10, reject) => {
227195
+ return new Promise((resolve11, reject) => {
227096
227196
  this._walkAsync(root, options, (error, entries) => {
227097
227197
  if (error === null) {
227098
- resolve10(entries);
227198
+ resolve11(entries);
227099
227199
  } else {
227100
227200
  reject(error);
227101
227201
  }
@@ -227105,10 +227205,10 @@ var require_async5 = __commonJS({
227105
227205
  async static(patterns, options) {
227106
227206
  const entries = [];
227107
227207
  const stream = this._readerStream.static(patterns, options);
227108
- return new Promise((resolve10, reject) => {
227208
+ return new Promise((resolve11, reject) => {
227109
227209
  stream.once("error", reject);
227110
227210
  stream.on("data", (entry) => entries.push(entry));
227111
- stream.once("end", () => resolve10(entries));
227211
+ stream.once("end", () => resolve11(entries));
227112
227212
  });
227113
227213
  }
227114
227214
  };
@@ -260014,12 +260114,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260014
260114
  };
260015
260115
  var NodeRuntimeFileSystem = class {
260016
260116
  delete(path2) {
260017
- return new Promise((resolve10, reject) => {
260117
+ return new Promise((resolve11, reject) => {
260018
260118
  fs__namespace.rm(path2, { recursive: true }, (err) => {
260019
260119
  if (err)
260020
260120
  reject(err);
260021
260121
  else
260022
- resolve10();
260122
+ resolve11();
260023
260123
  });
260024
260124
  });
260025
260125
  }
@@ -260038,12 +260138,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260038
260138
  }));
260039
260139
  }
260040
260140
  readFile(filePath, encoding = "utf-8") {
260041
- return new Promise((resolve10, reject) => {
260141
+ return new Promise((resolve11, reject) => {
260042
260142
  fs__namespace.readFile(filePath, encoding, (err, data) => {
260043
260143
  if (err)
260044
260144
  reject(err);
260045
260145
  else
260046
- resolve10(data);
260146
+ resolve11(data);
260047
260147
  });
260048
260148
  });
260049
260149
  }
@@ -260051,12 +260151,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260051
260151
  return fs__namespace.readFileSync(filePath, encoding);
260052
260152
  }
260053
260153
  async writeFile(filePath, fileText) {
260054
- await new Promise((resolve10, reject) => {
260154
+ await new Promise((resolve11, reject) => {
260055
260155
  fs__namespace.writeFile(filePath, fileText, (err) => {
260056
260156
  if (err)
260057
260157
  reject(err);
260058
260158
  else
260059
- resolve10();
260159
+ resolve11();
260060
260160
  });
260061
260161
  });
260062
260162
  }
@@ -260070,12 +260170,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260070
260170
  fs__namespace.mkdirSync(dirPath, { recursive: true });
260071
260171
  }
260072
260172
  move(srcPath, destPath) {
260073
- return new Promise((resolve10, reject) => {
260173
+ return new Promise((resolve11, reject) => {
260074
260174
  fs__namespace.rename(srcPath, destPath, (err) => {
260075
260175
  if (err)
260076
260176
  reject(err);
260077
260177
  else
260078
- resolve10();
260178
+ resolve11();
260079
260179
  });
260080
260180
  });
260081
260181
  }
@@ -260083,12 +260183,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260083
260183
  fs__namespace.renameSync(srcPath, destPath);
260084
260184
  }
260085
260185
  copy(srcPath, destPath) {
260086
- return new Promise((resolve10, reject) => {
260186
+ return new Promise((resolve11, reject) => {
260087
260187
  fs__namespace.copyFile(srcPath, destPath, (err) => {
260088
260188
  if (err)
260089
260189
  reject(err);
260090
260190
  else
260091
- resolve10();
260191
+ resolve11();
260092
260192
  });
260093
260193
  });
260094
260194
  }
@@ -260096,15 +260196,15 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
260096
260196
  fs__namespace.copyFileSync(srcPath, destPath);
260097
260197
  }
260098
260198
  stat(path2) {
260099
- return new Promise((resolve10, reject) => {
260199
+ return new Promise((resolve11, reject) => {
260100
260200
  fs__namespace.stat(path2, (err, stat) => {
260101
260201
  if (err) {
260102
260202
  if (err.code === "ENOENT" || err.code === "ENOTDIR")
260103
- resolve10(void 0);
260203
+ resolve11(void 0);
260104
260204
  else
260105
260205
  reject(err);
260106
260206
  } else {
260107
- resolve10(stat);
260207
+ resolve11(stat);
260108
260208
  }
260109
260209
  });
260110
260210
  });
@@ -283781,7 +283881,7 @@ Node text: ${this.#forgottenText}`;
283781
283881
 
283782
283882
  // src/index.ts
283783
283883
  init_cjs_shims();
283784
- var import_picocolors31 = __toESM(require_picocolors(), 1);
283884
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
283785
283885
 
283786
283886
  // src/migrate.ts
283787
283887
  init_cjs_shims();
@@ -283791,7 +283891,7 @@ var import_picocolors6 = __toESM(require_picocolors(), 1);
283791
283891
  var import_fs5 = require("fs");
283792
283892
  init_src();
283793
283893
  init_dbRole();
283794
- var import_schema3 = require("@abloatai/transaction/schema");
283894
+ var import_schema2 = require("@abloatai/transaction/schema");
283795
283895
  var import_source = require("@abloatai/transaction/source");
283796
283896
  init_push();
283797
283897
  var MIGRATE_USAGE = ` ablo migrate \u2014 create the tables your schema needs in your own database (DATABASE_URL)
@@ -283838,8 +283938,8 @@ function parseMigrateArgs(argv) {
283838
283938
  return { schemaPath, exportName, targetSchema, dryRun, outputFile };
283839
283939
  }
283840
283940
  function planFor(schema, targetSchema = "public") {
283841
- const schemaJson = JSON.parse((0, import_schema3.serializeSchema)(schema));
283842
- const plan = (0, import_schema3.generateProvisionPlan)(schemaJson, targetSchema, {
283941
+ const schemaJson = JSON.parse((0, import_schema2.serializeSchema)(schema));
283942
+ const plan = (0, import_schema2.generateProvisionPlan)(schemaJson, targetSchema, {
283843
283943
  foreignKeys: targetSchema === "public"
283844
283944
  });
283845
283945
  const adapterTables = (0, import_source.adapterTableMigrations)().map((m2) => m2.up);
@@ -283861,8 +283961,8 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
283861
283961
  } });
283862
283962
  const total = statements.length;
283863
283963
  const startedAt = Date.now();
283864
- const lockTimeout = (0, import_schema3.resolveDdlLockTimeout)();
283865
- const maxLockAttempts = (0, import_schema3.resolveDdlMaxLockAttempts)();
283964
+ const lockTimeout = (0, import_schema2.resolveDdlLockTimeout)();
283965
+ const maxLockAttempts = (0, import_schema2.resolveDdlMaxLockAttempts)();
283866
283966
  if (!observer.quiet) log.info("applying migration plan", { targetSchema, statements: total });
283867
283967
  try {
283868
283968
  for (let attempt = 1; ; attempt++) {
@@ -283876,7 +283976,7 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
283876
283976
  observer.onStatement?.(index + 1, total);
283877
283977
  } catch (err) {
283878
283978
  const pg = err ?? {};
283879
- if (pg.code === import_schema3.PG_LOCK_NOT_AVAILABLE) throw err;
283979
+ if (pg.code === import_schema2.PG_LOCK_NOT_AVAILABLE) throw err;
283880
283980
  log.error("migration plan failed", {
283881
283981
  code: "migration_failed",
283882
283982
  durationMs: Date.now() - startedAt,
@@ -283894,10 +283994,10 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
283894
283994
  break;
283895
283995
  } catch (err) {
283896
283996
  const pg = err ?? {};
283897
- if (pg.code === import_schema3.PG_LOCK_NOT_AVAILABLE && attempt < maxLockAttempts) {
283898
- const backoffMs = (0, import_schema3.ddlLockRetryBackoffMs)(attempt);
283997
+ if (pg.code === import_schema2.PG_LOCK_NOT_AVAILABLE && attempt < maxLockAttempts) {
283998
+ const backoffMs = (0, import_schema2.ddlLockRetryBackoffMs)(attempt);
283899
283999
  log.warn("schema change blocked by a lock; backing off and retrying", { targetSchema, attempt, backoffMs });
283900
- await new Promise((resolve10) => setTimeout(resolve10, backoffMs));
284000
+ await new Promise((resolve11) => setTimeout(resolve11, backoffMs));
283901
284001
  continue;
283902
284002
  }
283903
284003
  throw err;
@@ -284239,11 +284339,11 @@ function parseFeedbackArgs(argv) {
284239
284339
  const positional2 = [];
284240
284340
  let detail;
284241
284341
  let command;
284242
- let errorCode;
284342
+ let errorCode2;
284243
284343
  let from;
284244
284344
  let yes = false;
284245
284345
  let json = false;
284246
- const flagValue = (flag2, value) => {
284346
+ const flagValue2 = (flag2, value) => {
284247
284347
  if (value === void 0 || value.startsWith("--")) {
284248
284348
  throw new import_errors12.AbloValidationError(`\`${flag2}\` needs a value.`, {
284249
284349
  code: "cli_invalid_arguments"
@@ -284255,16 +284355,16 @@ function parseFeedbackArgs(argv) {
284255
284355
  const arg = argv[i];
284256
284356
  switch (arg) {
284257
284357
  case "--detail":
284258
- detail = flagValue("--detail", argv[++i]);
284358
+ detail = flagValue2("--detail", argv[++i]);
284259
284359
  break;
284260
284360
  case "--command":
284261
- command = flagValue("--command", argv[++i]);
284361
+ command = flagValue2("--command", argv[++i]);
284262
284362
  break;
284263
284363
  case "--error-code":
284264
- errorCode = flagValue("--error-code", argv[++i]);
284364
+ errorCode2 = flagValue2("--error-code", argv[++i]);
284265
284365
  break;
284266
284366
  case "--from":
284267
- from = flagValue("--from", argv[++i]);
284367
+ from = flagValue2("--from", argv[++i]);
284268
284368
  break;
284269
284369
  case "--yes":
284270
284370
  yes = true;
@@ -284299,7 +284399,7 @@ function parseFeedbackArgs(argv) {
284299
284399
  summary,
284300
284400
  ...detail !== void 0 ? { detail } : {},
284301
284401
  ...command !== void 0 ? { command } : {},
284302
- ...errorCode !== void 0 ? { errorCode } : {},
284402
+ ...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {},
284303
284403
  ...from !== void 0 ? { from } : {},
284304
284404
  yes,
284305
284405
  json
@@ -284420,8 +284520,8 @@ init_controlPlane();
284420
284520
  init_config();
284421
284521
  var BRANCH_USAGE = `Usage:
284422
284522
  ablo branch list [--json]
284423
- ablo branch create <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--credential]
284424
- ablo branch ensure <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--credential]
284523
+ ablo branch create <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--hosted] [--credential]
284524
+ ablo branch ensure <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--hosted] [--credential]
284425
284525
  ablo branch credential <id|slug> [--ttl-hours <1-168>] [--json]
284426
284526
  ablo branch status <branch-id|slug> [--json]
284427
284527
  ablo branch check <branch-id|slug> [--json]
@@ -284434,7 +284534,7 @@ function requireKey2(explicit) {
284434
284534
  const key = explicit ?? resolveManagementKey();
284435
284535
  if (!key) {
284436
284536
  throw new Error(
284437
- "No project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY."
284537
+ "No project management credential. Run `npx ablo login` or set ABLO_API_KEY to an mk_ credential."
284438
284538
  );
284439
284539
  }
284440
284540
  return key;
@@ -284574,7 +284674,8 @@ async function create(slug, argv, idempotent, context = {}) {
284574
284674
  slug: parsedSlug.data,
284575
284675
  ...parentId ? { parent_branch_id: parentId } : {},
284576
284676
  ...valueAfter(argv, "--kind") ? { kind: valueAfter(argv, "--kind") } : {},
284577
- ...valueAfter(argv, "--expires-at") ? { expires_at: valueAfter(argv, "--expires-at") } : {}
284677
+ ...valueAfter(argv, "--expires-at") ? { expires_at: valueAfter(argv, "--expires-at") } : {},
284678
+ ...argv.includes("--hosted") ? { storage: "hosted" } : {}
284578
284679
  }
284579
284680
  }, context);
284580
284681
  if (response.status !== 201) {
@@ -284672,29 +284773,118 @@ async function branches(argv) {
284672
284773
 
284673
284774
  // src/branchDev.ts
284674
284775
  init_cjs_shims();
284675
- var import_node_crypto5 = require("crypto");
284776
+ var import_node_crypto6 = require("crypto");
284676
284777
  var import_node_child_process = require("child_process");
284677
284778
  var import_branches2 = require("@abloatai/transaction/branches");
284678
- var import_errors14 = require("@abloatai/transaction/errors");
284779
+ var import_errors15 = require("@abloatai/transaction/errors");
284679
284780
  init_config();
284680
284781
  init_telemetry();
284681
284782
 
284682
284783
  // src/dev.ts
284683
284784
  init_cjs_shims();
284684
- var import_errors13 = require("@abloatai/transaction/errors");
284785
+ var import_errors14 = require("@abloatai/transaction/errors");
284685
284786
  var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
284686
284787
  var import_picocolors16 = __toESM(require_picocolors(), 1);
284687
284788
  init_dist2();
284688
284789
  var import_fs7 = require("fs");
284689
284790
  var import_path5 = require("path");
284690
- var import_schema6 = require("@abloatai/transaction/schema");
284791
+ var import_schema5 = require("@abloatai/transaction/schema");
284691
284792
  init_push();
284692
284793
  init_controlPlane();
284794
+ var import_wire8 = require("@abloatai/transaction/wire");
284693
284795
  init_config();
284694
284796
  init_readiness();
284695
284797
  init_theme();
284696
284798
  init_dbRole();
284697
284799
  var import_source3 = require("@abloatai/transaction/source");
284800
+
284801
+ // src/localConnectorLease.ts
284802
+ init_cjs_shims();
284803
+ var import_node_crypto5 = require("crypto");
284804
+ var import_node_fs3 = require("fs");
284805
+ var import_node_os2 = require("os");
284806
+ var import_node_path2 = require("path");
284807
+ var import_errors13 = require("@abloatai/transaction/errors");
284808
+ function acquireLocalConnectorLease(identity, options = {}) {
284809
+ const directory = options.directory ?? (0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "ablo-source-connectors");
284810
+ const pid = options.pid ?? process.pid;
284811
+ const isProcessAlive = options.isProcessAlive ?? processIsAlive;
284812
+ const key = (0, import_node_crypto5.createHash)("sha256").update(`${(0, import_node_path2.resolve)(identity.cwd)}\0${identity.baseUrl}\0${identity.branch}`).digest("hex").slice(0, 24);
284813
+ const path = (0, import_node_path2.join)(directory, `${key}.lock`);
284814
+ const token = (0, import_node_crypto5.randomUUID)();
284815
+ const record = { pid, token };
284816
+ (0, import_node_fs3.mkdirSync)(directory, { recursive: true, mode: 448 });
284817
+ for (let attempt = 0; attempt < 2; attempt += 1) {
284818
+ try {
284819
+ const fd = (0, import_node_fs3.openSync)(path, "wx", 384);
284820
+ try {
284821
+ (0, import_node_fs3.writeFileSync)(fd, JSON.stringify(record));
284822
+ } finally {
284823
+ (0, import_node_fs3.closeSync)(fd);
284824
+ }
284825
+ let released = false;
284826
+ return {
284827
+ release() {
284828
+ if (released) return;
284829
+ released = true;
284830
+ try {
284831
+ const current = readLease(path);
284832
+ if (current?.token === token) (0, import_node_fs3.unlinkSync)(path);
284833
+ } catch {
284834
+ }
284835
+ }
284836
+ };
284837
+ } catch (error) {
284838
+ if (!isAlreadyExists(error)) throw error;
284839
+ const owner = readLease(path);
284840
+ if (owner && isProcessAlive(owner.pid)) {
284841
+ throw new import_errors13.AbloValidationError(
284842
+ `Another ablo dev --local process (PID ${owner.pid}) already owns this branch's local Data Source. Stop it before starting another connector.`,
284843
+ { code: "cli_invalid_arguments" }
284844
+ );
284845
+ }
284846
+ try {
284847
+ (0, import_node_fs3.unlinkSync)(path);
284848
+ } catch (unlinkError) {
284849
+ if (!isMissing(unlinkError)) throw unlinkError;
284850
+ }
284851
+ }
284852
+ }
284853
+ throw new import_errors13.AbloValidationError(
284854
+ "Could not acquire this branch's local Data Source connector lease. Retry after the other connector exits.",
284855
+ { code: "cli_invalid_arguments" }
284856
+ );
284857
+ }
284858
+ function readLease(path) {
284859
+ try {
284860
+ const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
284861
+ return typeof parsed.pid === "number" && typeof parsed.token === "string" ? { pid: parsed.pid, token: parsed.token } : void 0;
284862
+ } catch {
284863
+ return void 0;
284864
+ }
284865
+ }
284866
+ function processIsAlive(pid) {
284867
+ try {
284868
+ process.kill(pid, 0);
284869
+ return true;
284870
+ } catch (error) {
284871
+ return !isNoSuchProcess(error);
284872
+ }
284873
+ }
284874
+ function errorCode(error) {
284875
+ return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
284876
+ }
284877
+ function isAlreadyExists(error) {
284878
+ return errorCode(error) === "EEXIST";
284879
+ }
284880
+ function isMissing(error) {
284881
+ return errorCode(error) === "ENOENT";
284882
+ }
284883
+ function isNoSuchProcess(error) {
284884
+ return errorCode(error) === "ESRCH";
284885
+ }
284886
+
284887
+ // src/dev.ts
284698
284888
  function parseDevArgs(argv) {
284699
284889
  let schemaPath = DEFAULT_SCHEMA_PATH;
284700
284890
  let exportName = DEFAULT_EXPORT;
@@ -284727,7 +284917,7 @@ function parseDevArgs(argv) {
284727
284917
  sourcePath = argv[++i] ?? sourcePath;
284728
284918
  break;
284729
284919
  default:
284730
- throw new import_errors13.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284920
+ throw new import_errors14.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284731
284921
  }
284732
284922
  }
284733
284923
  url = apiBaseUrl(url);
@@ -284745,7 +284935,7 @@ function parseDevArgs(argv) {
284745
284935
  async function loadLocalSourceHandler(sourcePath) {
284746
284936
  const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
284747
284937
  if (!(0, import_fs7.existsSync)(abs)) {
284748
- throw new import_errors13.AbloValidationError(
284938
+ throw new import_errors14.AbloValidationError(
284749
284939
  `local Data Source not found at ${import_picocolors16.default.bold(sourcePath)}. Add the signed Data Source handler described by ${import_picocolors16.default.bold("npx ablo docs data-sources")}, or pass ${import_picocolors16.default.bold("--source <path>")}.`,
284750
284940
  { code: "cli_invalid_arguments" }
284751
284941
  );
@@ -284756,7 +284946,7 @@ async function loadLocalSourceHandler(sourcePath) {
284756
284946
  const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
284757
284947
  const handler = mod.POST ?? nested?.POST;
284758
284948
  if (typeof handler !== "function") {
284759
- throw new import_errors13.AbloValidationError(
284949
+ throw new import_errors14.AbloValidationError(
284760
284950
  `${import_picocolors16.default.bold(sourcePath)} must export a ${import_picocolors16.default.bold("POST(request)")} Data Source handler.`,
284761
284951
  { code: "cli_invalid_arguments" }
284762
284952
  );
@@ -284764,27 +284954,20 @@ async function loadLocalSourceHandler(sourcePath) {
284764
284954
  return handler;
284765
284955
  }
284766
284956
  async function registerLocalSource(args) {
284767
- const response = await fetch(`${args.url}/v1/datasources`, {
284957
+ await requestControlPlane({
284958
+ path: "/v1/datasources",
284768
284959
  method: "POST",
284769
- headers: {
284770
- authorization: `Bearer ${args.apiKey}`,
284771
- "content-type": "application/json"
284772
- },
284773
- body: JSON.stringify({
284960
+ ...args.apiKey ? { apiKey: args.apiKey } : {},
284961
+ baseUrl: args.url,
284962
+ body: {
284774
284963
  connection: "endpoint",
284775
284964
  endpoint: "http://localhost/ablo-dev/reverse-channel",
284776
284965
  signingKey: args.apiKey,
284777
284966
  reverseChannel: true,
284778
284967
  metadata: { managed_by: "ablo dev --local" }
284779
- })
284968
+ },
284969
+ responseSchema: import_wire8.datasourceSummarySchema
284780
284970
  });
284781
- if (!response.ok) {
284782
- const body = await response.text();
284783
- throw new import_errors13.AbloValidationError(
284784
- `Could not register the local Data Source (${response.status}): ${body}`,
284785
- { code: "cli_invalid_arguments" }
284786
- );
284787
- }
284788
284971
  }
284789
284972
  function classifyKey(apiKey) {
284790
284973
  if (!apiKey) {
@@ -284941,7 +285124,7 @@ async function dev(argv, runtime = {}) {
284941
285124
  else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
284942
285125
  if (runtime.branch) args.planeLabel = runtime.branch.slug;
284943
285126
  if (args.local && !args.watch) {
284944
- throw new import_errors13.AbloValidationError(
285127
+ throw new import_errors14.AbloValidationError(
284945
285128
  `${import_picocolors16.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors16.default.bold("--no-watch")}.`,
284946
285129
  { code: "cli_invalid_arguments" }
284947
285130
  );
@@ -284963,6 +285146,7 @@ async function dev(argv, runtime = {}) {
284963
285146
  );
284964
285147
  }
284965
285148
  let localAbort = null;
285149
+ let localLease = null;
284966
285150
  if (args.local) {
284967
285151
  process.env.ABLO_API_KEY = args.apiKey;
284968
285152
  if (!process.env.DATABASE_URL) {
@@ -284970,7 +285154,18 @@ async function dev(argv, runtime = {}) {
284970
285154
  if (databaseUrl) process.env.DATABASE_URL = databaseUrl.value;
284971
285155
  }
284972
285156
  const handler = await loadLocalSourceHandler(args.sourcePath);
284973
- await registerLocalSource(args);
285157
+ localLease = acquireLocalConnectorLease({
285158
+ cwd: process.cwd(),
285159
+ baseUrl: args.url,
285160
+ branch: args.planeLabel
285161
+ });
285162
+ try {
285163
+ await registerLocalSource(args);
285164
+ } catch (error) {
285165
+ localLease.release();
285166
+ localLease = null;
285167
+ throw error;
285168
+ }
284974
285169
  localAbort = new AbortController();
284975
285170
  const connector = (0, import_source3.createSourceConnector)({
284976
285171
  apiKey: args.apiKey,
@@ -284988,13 +285183,16 @@ async function dev(argv, runtime = {}) {
284988
285183
  });
284989
285184
  void connector.run(localAbort.signal).catch((error) => {
284990
285185
  console.error(import_picocolors16.default.red(` local connector stopped: ${error instanceof Error ? error.message : String(error)}`));
285186
+ }).finally(() => {
285187
+ localLease?.release();
285188
+ localLease = null;
284991
285189
  });
284992
285190
  console.log(` ${import_picocolors16.default.dim("source")} ${args.sourcePath} ${import_picocolors16.default.dim("(outbound connector; no public URL)")}`);
284993
285191
  }
284994
285192
  const schema = await loadSchema(args.schemaPath, args.exportName);
284995
285193
  const modelCount = Object.keys(schema.models).length;
284996
285194
  console.log(
284997
- ` ${import_picocolors16.default.dim("schema")} ${import_picocolors16.default.bold(args.schemaPath)} ${import_picocolors16.default.dim(`(${modelCount} models, hash ${(0, import_schema6.schemaHash)(schema)})`)}`
285195
+ ` ${import_picocolors16.default.dim("schema")} ${import_picocolors16.default.bold(args.schemaPath)} ${import_picocolors16.default.dim(`(${modelCount} models, hash ${(0, import_schema5.schemaHash)(schema)})`)}`
284998
285196
  );
284999
285197
  if (!runtime.branch) {
285000
285198
  console.log(` ${import_picocolors16.default.dim("key")} ${args.apiKey.slice(0, 12)}\u2026`);
@@ -285007,6 +285205,7 @@ async function dev(argv, runtime = {}) {
285007
285205
  s.stop(first.message, first.ok ? 0 : 1);
285008
285206
  if (!first.ok) {
285009
285207
  localAbort?.abort();
285208
+ localLease?.release();
285010
285209
  process.exit(1);
285011
285210
  }
285012
285211
  if (runtime.branch) {
@@ -285063,6 +285262,7 @@ async function dev(argv, runtime = {}) {
285063
285262
  const stop = () => {
285064
285263
  watcher.close();
285065
285264
  localAbort?.abort();
285265
+ localLease?.release();
285066
285266
  console.log(`
285067
285267
  ${import_picocolors16.default.dim("stopped.")}`);
285068
285268
  process.exit(0);
@@ -285092,7 +285292,7 @@ function parseBranchDevArgs(argv) {
285092
285292
  const arg = argv[index];
285093
285293
  if (!arg) continue;
285094
285294
  if (arg === "--no-branch") {
285095
- throw new import_errors14.AbloValidationError(
285295
+ throw new import_errors15.AbloValidationError(
285096
285296
  "--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
285097
285297
  { code: "cli_invalid_arguments" }
285098
285298
  );
@@ -285100,7 +285300,7 @@ function parseBranchDevArgs(argv) {
285100
285300
  if (arg === "--branch") {
285101
285301
  branchSlug = argv[++index];
285102
285302
  if (!branchSlug) {
285103
- throw new import_errors14.AbloValidationError("--branch requires a slug", {
285303
+ throw new import_errors15.AbloValidationError("--branch requires a slug", {
285104
285304
  code: "cli_invalid_arguments"
285105
285305
  });
285106
285306
  }
@@ -285109,7 +285309,7 @@ function parseBranchDevArgs(argv) {
285109
285309
  if (arg === "--branch-ttl-hours") {
285110
285310
  const value = Number(argv[++index]);
285111
285311
  if (!Number.isInteger(value) || value < 1 || value > 168) {
285112
- throw new import_errors14.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
285312
+ throw new import_errors15.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
285113
285313
  code: "cli_invalid_arguments"
285114
285314
  });
285115
285315
  }
@@ -285127,12 +285327,12 @@ function parseBranchDevArgs(argv) {
285127
285327
  function branchSlugFromRef(ref) {
285128
285328
  const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
285129
285329
  if (!base) {
285130
- throw new import_errors14.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
285330
+ throw new import_errors15.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
285131
285331
  code: "cli_invalid_arguments"
285132
285332
  });
285133
285333
  }
285134
285334
  const nonRoot = base === "production" ? "production-dev" : base;
285135
- const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto5.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
285335
+ const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto6.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
285136
285336
  return import_branches2.branchSlugSchema.parse(shortened);
285137
285337
  }
285138
285338
  function gitBranch() {
@@ -285149,7 +285349,7 @@ function gitBranch() {
285149
285349
  function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
285150
285350
  const value = explicit ?? env.ABLO_BRANCH ?? env.GITHUB_HEAD_REF ?? env.GITHUB_REF_NAME ?? env.VERCEL_GIT_COMMIT_REF ?? env.CI_COMMIT_REF_NAME ?? readGitBranch();
285151
285351
  if (!value) {
285152
- throw new import_errors14.AbloValidationError(
285352
+ throw new import_errors15.AbloValidationError(
285153
285353
  "Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
285154
285354
  { code: "cli_invalid_arguments" }
285155
285355
  );
@@ -285167,13 +285367,13 @@ async function runBranchDev(argv, dependencies = {}) {
285167
285367
  const slug = branchSlugFromRef(ref);
285168
285368
  const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
285169
285369
  if (!managementKey) {
285170
- throw new import_errors14.AbloValidationError(
285171
- "Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY.",
285370
+ throw new import_errors15.AbloValidationError(
285371
+ "Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_API_KEY to an mk_ credential.",
285172
285372
  { code: "cli_invalid_arguments" }
285173
285373
  );
285174
285374
  }
285175
285375
  if (!managementKey.startsWith("mk_")) {
285176
- throw new import_errors14.AbloValidationError(
285376
+ throw new import_errors15.AbloValidationError(
285177
285377
  "Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
285178
285378
  { code: "cli_invalid_arguments" }
285179
285379
  );
@@ -285202,7 +285402,7 @@ async function runBranchDev(argv, dependencies = {}) {
285202
285402
  // src/whoami.ts
285203
285403
  init_cjs_shims();
285204
285404
  var import_picocolors17 = __toESM(require_picocolors(), 1);
285205
- var import_errors15 = require("@abloatai/transaction/errors");
285405
+ var import_errors16 = require("@abloatai/transaction/errors");
285206
285406
  init_config();
285207
285407
  init_controlPlane();
285208
285408
 
@@ -285277,7 +285477,7 @@ function parseWhoamiArgs(argv) {
285277
285477
  case "--key": {
285278
285478
  const value = argv[++i];
285279
285479
  if (!value || value.startsWith("--")) {
285280
- throw new import_errors15.AbloValidationError("`--key` needs a credential value.", {
285480
+ throw new import_errors16.AbloValidationError("`--key` needs a credential value.", {
285281
285481
  code: "cli_invalid_arguments"
285282
285482
  });
285283
285483
  }
@@ -285287,12 +285487,12 @@ function parseWhoamiArgs(argv) {
285287
285487
  case "--key-env": {
285288
285488
  const value = argv[++i];
285289
285489
  if (!value || value.startsWith("--")) {
285290
- throw new import_errors15.AbloValidationError("`--key-env` needs an environment variable name.", {
285490
+ throw new import_errors16.AbloValidationError("`--key-env` needs an environment variable name.", {
285291
285491
  code: "cli_invalid_arguments"
285292
285492
  });
285293
285493
  }
285294
285494
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
285295
- throw new import_errors15.AbloValidationError(
285495
+ throw new import_errors16.AbloValidationError(
285296
285496
  `\`${value}\` is not a valid environment variable name.`,
285297
285497
  { code: "cli_invalid_arguments" }
285298
285498
  );
@@ -285301,13 +285501,13 @@ function parseWhoamiArgs(argv) {
285301
285501
  break;
285302
285502
  }
285303
285503
  default:
285304
- throw new import_errors15.AbloValidationError(`unknown whoami flag: ${arg}`, {
285504
+ throw new import_errors16.AbloValidationError(`unknown whoami flag: ${arg}`, {
285305
285505
  code: "cli_invalid_arguments"
285306
285506
  });
285307
285507
  }
285308
285508
  }
285309
285509
  if (key && keyEnv) {
285310
- throw new import_errors15.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
285510
+ throw new import_errors16.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
285311
285511
  code: "cli_invalid_arguments"
285312
285512
  });
285313
285513
  }
@@ -285318,7 +285518,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
285318
285518
  if (args.keyEnv) {
285319
285519
  const found = readProjectEnvVariable(args.keyEnv, cwd);
285320
285520
  if (!found) {
285321
- throw new import_errors15.AbloAuthenticationError(
285521
+ throw new import_errors16.AbloAuthenticationError(
285322
285522
  `${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
285323
285523
  { code: "cli_api_key_missing" }
285324
285524
  );
@@ -285342,12 +285542,12 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
285342
285542
  if (managementKey) {
285343
285543
  return {
285344
285544
  key: managementKey,
285345
- source: process.env.ABLO_MANAGEMENT_KEY ? "env:ABLO_MANAGEMENT_KEY" : "stored login",
285346
- targetSource: process.env.ABLO_MANAGEMENT_KEY ? "env" : "stored"
285545
+ source: "stored login",
285546
+ targetSource: "stored"
285347
285547
  };
285348
285548
  }
285349
285549
  const ambient = ambientEnvKeyNote();
285350
- throw new import_errors15.AbloAuthenticationError(
285550
+ throw new import_errors16.AbloAuthenticationError(
285351
285551
  `No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
285352
285552
 
285353
285553
  ${ambient}` : ""}`,
@@ -285365,7 +285565,7 @@ async function whoami(argv) {
285365
285565
  });
285366
285566
  const confirmed = target.confirmed;
285367
285567
  if (!confirmed) {
285368
- throw new import_errors15.AbloAuthenticationError(
285568
+ throw new import_errors16.AbloAuthenticationError(
285369
285569
  "The server did not confirm an identity for this credential.",
285370
285570
  { code: "identity_resolve_failed" }
285371
285571
  );
@@ -285423,15 +285623,15 @@ init_push();
285423
285623
  // src/setup/run.ts
285424
285624
  init_cjs_shims();
285425
285625
  var import_picocolors19 = __toESM(require_picocolors(), 1);
285426
- var import_errors16 = require("@abloatai/transaction/errors");
285626
+ var import_errors17 = require("@abloatai/transaction/errors");
285427
285627
  init_theme();
285428
285628
 
285429
285629
  // src/setup/discover.ts
285430
285630
  init_cjs_shims();
285431
- var import_node_fs3 = require("fs");
285432
- var import_node_crypto6 = require("crypto");
285631
+ var import_node_fs4 = require("fs");
285632
+ var import_node_crypto7 = require("crypto");
285433
285633
  var import_node_child_process2 = require("child_process");
285434
- var import_node_path2 = require("path");
285634
+ var import_node_path3 = require("path");
285435
285635
  init_controlPlane();
285436
285636
  init_config();
285437
285637
 
@@ -286490,7 +286690,7 @@ function tryGit(cwd, args) {
286490
286690
  }
286491
286691
  }
286492
286692
  function resolveRepositoryRoot(cwd = process.cwd()) {
286493
- return (0, import_node_path2.resolve)(tryGit(cwd, ["rev-parse", "--show-toplevel"]) || cwd);
286693
+ return (0, import_node_path3.resolve)(tryGit(cwd, ["rev-parse", "--show-toplevel"]) || cwd);
286494
286694
  }
286495
286695
  function walkFiles(root, maxDepth = 5) {
286496
286696
  const files = [];
@@ -286499,13 +286699,13 @@ function walkFiles(root, maxDepth = 5) {
286499
286699
  const current = stack.pop();
286500
286700
  let entries;
286501
286701
  try {
286502
- entries = (0, import_node_fs3.readdirSync)(current.path, { withFileTypes: true });
286702
+ entries = (0, import_node_fs4.readdirSync)(current.path, { withFileTypes: true });
286503
286703
  } catch {
286504
286704
  continue;
286505
286705
  }
286506
286706
  for (const entry of entries.slice(0, 1e4)) {
286507
286707
  if (files.length >= MAX_DISCOVERY_FILES) break;
286508
- const path = (0, import_node_path2.join)(current.path, entry.name);
286708
+ const path = (0, import_node_path3.join)(current.path, entry.name);
286509
286709
  if (entry.isDirectory()) {
286510
286710
  if (current.depth < maxDepth && !IGNORED_DIRECTORIES.has(entry.name)) {
286511
286711
  stack.push({ path, depth: current.depth + 1 });
@@ -286519,9 +286719,9 @@ function walkFiles(root, maxDepth = 5) {
286519
286719
  }
286520
286720
  function readManifest(path) {
286521
286721
  try {
286522
- const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
286722
+ const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path, "utf8"));
286523
286723
  return {
286524
- root: (0, import_node_path2.resolve)(path, ".."),
286724
+ root: (0, import_node_path3.resolve)(path, ".."),
286525
286725
  name: typeof parsed.name === "string" ? parsed.name : null,
286526
286726
  dependencies: { ...parsed.dependencies, ...parsed.devDependencies },
286527
286727
  scripts: { ...parsed.scripts }
@@ -286531,14 +286731,14 @@ function readManifest(path) {
286531
286731
  }
286532
286732
  }
286533
286733
  function packageManifests(root, files) {
286534
- return files.filter((path) => (0, import_node_path2.basename)(path) === "package.json").flatMap((path) => {
286734
+ return files.filter((path) => (0, import_node_path3.basename)(path) === "package.json").flatMap((path) => {
286535
286735
  const manifest = readManifest(path);
286536
286736
  return manifest ? [manifest] : [];
286537
286737
  }).sort((a, b4) => a.root.localeCompare(b4.root));
286538
286738
  }
286539
286739
  function pathInside(root, target) {
286540
- const fromRoot = (0, import_node_path2.relative)(root, target);
286541
- return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${import_node_path2.sep}`);
286740
+ const fromRoot = (0, import_node_path3.relative)(root, target);
286741
+ return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${import_node_path3.sep}`);
286542
286742
  }
286543
286743
  function packageOwnedFiles(manifest, manifests, files) {
286544
286744
  const nestedPackageRoots = manifests.filter(({ root }) => root !== manifest.root && pathInside(manifest.root, root));
@@ -286596,8 +286796,8 @@ function detectedPersistence(manifest, files) {
286596
286796
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286597
286797
  let source;
286598
286798
  try {
286599
- if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286600
- source = (0, import_node_fs3.readFileSync)(path, "utf8");
286799
+ if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286800
+ source = (0, import_node_fs4.readFileSync)(path, "utf8");
286601
286801
  } catch {
286602
286802
  continue;
286603
286803
  }
@@ -286625,17 +286825,17 @@ function coordinationAdoptionReason(disposition, persistence) {
286625
286825
  }
286626
286826
  }
286627
286827
  function packageManager(root) {
286628
- if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "pnpm-lock.yaml"))) return "pnpm";
286629
- if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "yarn.lock"))) return "yarn";
286630
- if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "bun.lockb")) || (0, import_node_fs3.existsSync)((0, import_node_path2.join)(root, "bun.lock"))) return "bun";
286828
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "pnpm-lock.yaml"))) return "pnpm";
286829
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "yarn.lock"))) return "yarn";
286830
+ if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "bun.lockb")) || (0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "bun.lock"))) return "bun";
286631
286831
  return "npm";
286632
286832
  }
286633
286833
  function environmentKeyNames(root) {
286634
286834
  const names = [".env.local", ".env.development.local", ".env.development", ".env"];
286635
286835
  return names.flatMap((name) => {
286636
- const path = (0, import_node_path2.join)(root, name);
286637
- if (!(0, import_node_fs3.existsSync)(path)) return [];
286638
- const keys = (0, import_node_fs3.readFileSync)(path, "utf8").split(/\r?\n/).flatMap((line) => {
286836
+ const path = (0, import_node_path3.join)(root, name);
286837
+ if (!(0, import_node_fs4.existsSync)(path)) return [];
286838
+ const keys = (0, import_node_fs4.readFileSync)(path, "utf8").split(/\r?\n/).flatMap((line) => {
286639
286839
  const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
286640
286840
  return match ? [match[1]] : [];
286641
286841
  });
@@ -286650,8 +286850,8 @@ function abloSourceFiles(root, files) {
286650
286850
  return files.flatMap((path) => {
286651
286851
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) return [];
286652
286852
  try {
286653
- if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) return [];
286654
- return (0, import_node_fs3.readFileSync)(path, "utf8").includes("@abloatai/") ? [(0, import_node_path2.relative)(root, path) || "."] : [];
286853
+ if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) return [];
286854
+ return (0, import_node_fs4.readFileSync)(path, "utf8").includes("@abloatai/") ? [(0, import_node_path3.relative)(root, path) || "."] : [];
286655
286855
  } catch {
286656
286856
  return [];
286657
286857
  }
@@ -286678,12 +286878,12 @@ function discoverMutationSites(root, files) {
286678
286878
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286679
286879
  let source;
286680
286880
  try {
286681
- if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286682
- source = (0, import_node_fs3.readFileSync)(path, "utf8");
286881
+ if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286882
+ source = (0, import_node_fs4.readFileSync)(path, "utf8");
286683
286883
  } catch {
286684
286884
  continue;
286685
286885
  }
286686
- const locator = (0, import_node_path2.relative)(root, path) || ".";
286886
+ const locator = (0, import_node_path3.relative)(root, path) || ".";
286687
286887
  for (const match of source.matchAll(/\b(?:(?:[A-Za-z_$][\w$]*)\.query|query|q)\s*\(\s*(?:`|['"])\s*(INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+([A-Za-z_$][\w$.[\]"`]*|"[^"]+"|`[^`]+`)/gi)) {
286688
286888
  const rawTable = match[2] ?? "";
286689
286889
  const modelHint = rawTable.replace(/["`\[\]]/g, "").split(".").at(-1)?.toLowerCase() || null;
@@ -286715,13 +286915,13 @@ function discoverMutationSites(root, files) {
286715
286915
  return sites.sort((a, b4) => a.path.localeCompare(b4.path) || a.line - b4.line);
286716
286916
  }
286717
286917
  function isProductionMutationFile(root, path) {
286718
- const locator = (0, import_node_path2.relative)(root, path).replaceAll("\\", "/");
286918
+ const locator = (0, import_node_path3.relative)(root, path).replaceAll("\\", "/");
286719
286919
  return !/(?:^|\/)(?:test|tests|__tests__|scripts)(?:\/|$)/.test(locator) && !/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(locator);
286720
286920
  }
286721
286921
  function digestFile(path) {
286722
- if (!(0, import_node_fs3.existsSync)(path)) return null;
286922
+ if (!(0, import_node_fs4.existsSync)(path)) return null;
286723
286923
  try {
286724
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs3.readFileSync)(path)).digest("hex");
286924
+ return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs4.readFileSync)(path)).digest("hex");
286725
286925
  } catch {
286726
286926
  return null;
286727
286927
  }
@@ -286752,7 +286952,7 @@ function localDiscoveryStep(state) {
286752
286952
  const appFiles = selected ? packageOwnedFiles(selected, state.packageManifests, files) : files.filter((path) => pathInside(envRoot, path));
286753
286953
  const persistence = selected ? detectedPersistence(selected, appFiles) : [];
286754
286954
  const coordinationAdoption = coordinationAdoptionDisposition(persistence);
286755
- const excludedNestedPackages = selected ? state.packageManifests.filter(({ root: packageRoot2 }) => packageRoot2 !== selected.root && pathInside(selected.root, packageRoot2)).map(({ root: packageRoot2, name }) => ({ root: (0, import_node_path2.relative)(root, packageRoot2), name })) : [];
286955
+ const excludedNestedPackages = selected ? state.packageManifests.filter(({ root: packageRoot2 }) => packageRoot2 !== selected.root && pathInside(selected.root, packageRoot2)).map(({ root: packageRoot2, name }) => ({ root: (0, import_node_path3.relative)(root, packageRoot2), name })) : [];
286756
286956
  const mutationSites = discoverMutationSites(
286757
286957
  envRoot,
286758
286958
  appFiles.filter((path) => isProductionMutationFile(envRoot, path))
@@ -286765,17 +286965,17 @@ function localDiscoveryStep(state) {
286765
286965
  if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
286766
286966
  let source;
286767
286967
  try {
286768
- if ((0, import_node_fs3.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286769
- source = (0, import_node_fs3.readFileSync)(path, "utf8");
286968
+ if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
286969
+ source = (0, import_node_fs4.readFileSync)(path, "utf8");
286770
286970
  } catch {
286771
286971
  continue;
286772
286972
  }
286773
286973
  databaseColumns.push(...discoverDatabaseColumnsFromSqlSource({
286774
- path: (0, import_node_path2.relative)(envRoot, path),
286974
+ path: (0, import_node_path3.relative)(envRoot, path),
286775
286975
  source
286776
286976
  }));
286777
286977
  transactionalRequirements.push(...discoverTransactionalRequirementsFromSqlSource({
286778
- path: (0, import_node_path2.relative)(envRoot, path),
286978
+ path: (0, import_node_path3.relative)(envRoot, path),
286779
286979
  source
286780
286980
  }));
286781
286981
  }
@@ -286807,8 +287007,8 @@ function localDiscoveryStep(state) {
286807
287007
  "src/app/providers.tsx",
286808
287008
  "app/api/ablo-session/route.ts",
286809
287009
  "src/app/api/ablo-session/route.ts"
286810
- ].filter((path) => (0, import_node_fs3.existsSync)((0, import_node_path2.join)(envRoot, path)));
286811
- const localSchemaPath = [(0, import_node_path2.join)(envRoot, "ablo", "schema.ts"), (0, import_node_path2.join)(envRoot, "src", "ablo", "schema.ts")].find((path) => (0, import_node_fs3.existsSync)(path)) ?? (0, import_node_path2.join)(envRoot, "ablo", "schema.ts");
287010
+ ].filter((path) => (0, import_node_fs4.existsSync)((0, import_node_path3.join)(envRoot, path)));
287011
+ const localSchemaPath = [(0, import_node_path3.join)(envRoot, "ablo", "schema.ts"), (0, import_node_path3.join)(envRoot, "src", "ablo", "schema.ts")].find((path) => (0, import_node_fs4.existsSync)(path)) ?? (0, import_node_path3.join)(envRoot, "ablo", "schema.ts");
286812
287012
  state.localSchemaDigest = digestFile(localSchemaPath);
286813
287013
  const facts = [
286814
287014
  fact("repository.root", root, "git", tryGit(root, ["rev-parse", "--show-toplevel"]) ? "Resolved from Git." : "No Git root was available; using the requested directory.", root),
@@ -286817,9 +287017,9 @@ function localDiscoveryStep(state) {
286817
287017
  fact("repository.dirtyPathCount", dirtyEntries.length, "git", "Count from porcelain status; path names are intentionally omitted.", root),
286818
287018
  fact("repository.scanTruncated", files.length >= MAX_DISCOVERY_FILES, "filesystem", `Scanned at most ${MAX_DISCOVERY_FILES} files to depth 5.`, root),
286819
287019
  fact("package.manager", packageManager(root), "filesystem", "Detected from the repository lockfile.", root),
286820
- fact("application.candidates", candidates.map(({ manifest, frameworks, dataAccess, runtimeEntrypoint }) => ({ root: (0, import_node_path2.relative)(root, manifest.root) || ".", name: manifest.name, frameworks, dataAccess, runtimeEntrypoint })), "package_manifest", `${candidates.length} runnable application candidate(s) found.`, root),
286821
- fact("application.selectedRoot", state.applicationRoot ? (0, import_node_path2.relative)(root, state.applicationRoot) || "." : null, "inference", state.applicationRoot ? "Exactly one usable application root was selected." : "Application selection is ambiguous.", root, state.applicationRoot ? "high" : "low"),
286822
- fact("application.packageName", state.packageName, "package_manifest", "Read from the selected package manifest.", state.applicationRoot ? (0, import_node_path2.join)((0, import_node_path2.relative)(root, state.applicationRoot), "package.json") : "package.json"),
287020
+ fact("application.candidates", candidates.map(({ manifest, frameworks, dataAccess, runtimeEntrypoint }) => ({ root: (0, import_node_path3.relative)(root, manifest.root) || ".", name: manifest.name, frameworks, dataAccess, runtimeEntrypoint })), "package_manifest", `${candidates.length} runnable application candidate(s) found.`, root),
287021
+ fact("application.selectedRoot", state.applicationRoot ? (0, import_node_path3.relative)(root, state.applicationRoot) || "." : null, "inference", state.applicationRoot ? "Exactly one usable application root was selected." : "Application selection is ambiguous.", root, state.applicationRoot ? "high" : "low"),
287022
+ fact("application.packageName", state.packageName, "package_manifest", "Read from the selected package manifest.", state.applicationRoot ? (0, import_node_path3.join)((0, import_node_path3.relative)(root, state.applicationRoot), "package.json") : "package.json"),
286823
287023
  fact("application.frameworks", selected ? selectedFrameworks : candidates.flatMap(({ frameworks }) => frameworks), "package_manifest", "Detected only from declared package dependencies.", root),
286824
287024
  fact("application.kinds", selectedApplicationKinds, "package_manifest", "Detected from runtime scripts and declared framework or database dependencies.", root),
286825
287025
  fact("application.excludedNestedPackages", excludedNestedPackages, "package_manifest", "Independently manifested nested packages are excluded from the selected package's lexical mutation inventory; an agent may still follow application imports across that boundary.", root),
@@ -286840,16 +287040,16 @@ function localDiscoveryStep(state) {
286840
287040
  fact("application.databaseSchemaEvidence", uniqueDatabaseColumns, "filesystem", "Conservative database-column evidence derived from application-owned CREATE TABLE statements. Database catalogs remain authoritative.", envRoot, "medium"),
286841
287041
  fact("application.transactionalRequirements", uniqueRequirements, "filesystem", "Transaction shapes whose atomic predicates or exact RETURNING rows must be preserved.", envRoot, "medium"),
286842
287042
  fact("application.compatibilityDisposition", state.compatibility, "inference", "Compared database and transaction evidence with the current canonical Ablo contracts.", envRoot, uniqueDatabaseColumns.length > 0 ? "medium" : "low"),
286843
- fact("application.localSchemaDigest", state.localSchemaDigest, "filesystem", state.localSchemaDigest ? "SHA-256 of the local schema source file." : "No local ablo/schema.ts was found.", (0, import_node_path2.relative)(root, localSchemaPath))
287043
+ fact("application.localSchemaDigest", state.localSchemaDigest, "filesystem", state.localSchemaDigest ? "SHA-256 of the local schema source file." : "No local ablo/schema.ts was found.", (0, import_node_path3.relative)(root, localSchemaPath))
286844
287044
  ];
286845
287045
  const applicationChoices = candidates.map(({ manifest, frameworks, dataAccess }) => ({
286846
- value: (0, import_node_path2.relative)(root, manifest.root) || ".",
286847
- label: manifest.name ?? ((0, import_node_path2.relative)(root, manifest.root) || "."),
287046
+ value: (0, import_node_path3.relative)(root, manifest.root) || ".",
287047
+ label: manifest.name ?? ((0, import_node_path3.relative)(root, manifest.root) || "."),
286848
287048
  consequence: `Setup will modify only this ${[...frameworks, ...dataAccess].join("/")} application.`
286849
287049
  }));
286850
- if (state.applicationRoot && !applicationChoices.some(({ value }) => value === ((0, import_node_path2.relative)(root, state.applicationRoot) || "."))) {
287050
+ if (state.applicationRoot && !applicationChoices.some(({ value }) => value === ((0, import_node_path3.relative)(root, state.applicationRoot) || "."))) {
286851
287051
  applicationChoices.push({
286852
- value: (0, import_node_path2.relative)(root, state.applicationRoot) || ".",
287052
+ value: (0, import_node_path3.relative)(root, state.applicationRoot) || ".",
286853
287053
  label: state.packageName ?? ".",
286854
287054
  consequence: "Setup will treat this package as the application root; framework support remains unconfirmed."
286855
287055
  });
@@ -286860,7 +287060,7 @@ function localDiscoveryStep(state) {
286860
287060
  question: "Which application should Ablo set up?",
286861
287061
  status: state.applicationRoot ? "resolved" : "unresolved",
286862
287062
  choices: applicationChoices,
286863
- ...state.applicationRoot ? { selected: (0, import_node_path2.relative)(root, state.applicationRoot) || "." } : {},
287063
+ ...state.applicationRoot ? { selected: (0, import_node_path3.relative)(root, state.applicationRoot) || "." } : {},
286864
287064
  reason: state.applicationRoot ? dataApplications.length === 1 ? "Exactly one runnable package owns database access, so it is the coordination boundary." : runtimeOwners.length === 1 ? "Exactly one package owns a concrete runtime entrypoint, so it is the application boundary." : "The repository has one unambiguous application target." : "More than one or no runnable application was identified."
286865
287065
  },
286866
287066
  {
@@ -287210,7 +287410,7 @@ function parseSetupArgs(args) {
287210
287410
  if (arg === "--root") {
287211
287411
  const next = args[index + 1];
287212
287412
  if (!next || next.startsWith("-")) {
287213
- throw new import_errors16.AbloValidationError("`--root` requires a directory.", {
287413
+ throw new import_errors17.AbloValidationError("`--root` requires a directory.", {
287214
287414
  code: "cli_invalid_arguments"
287215
287415
  });
287216
287416
  }
@@ -287219,7 +287419,7 @@ function parseSetupArgs(args) {
287219
287419
  continue;
287220
287420
  }
287221
287421
  if (!allowedFlags.has(arg)) {
287222
- throw new import_errors16.AbloValidationError(`Unknown setup option: ${arg}`, {
287422
+ throw new import_errors17.AbloValidationError(`Unknown setup option: ${arg}`, {
287223
287423
  code: "cli_invalid_arguments"
287224
287424
  });
287225
287425
  }
@@ -287305,7 +287505,7 @@ function renderHumanPlan(plan) {
287305
287505
  async function runSetup(args) {
287306
287506
  const options = parseSetupArgs(args);
287307
287507
  if (options.json && !options.plan) {
287308
- throw new import_errors16.AbloValidationError(
287508
+ throw new import_errors17.AbloValidationError(
287309
287509
  "`--json` is a plan renderer. Use `ablo setup --plan --json`.",
287310
287510
  { code: "cli_invalid_arguments" }
287311
287511
  );
@@ -287319,11 +287519,13 @@ async function runSetup(args) {
287319
287519
  }
287320
287520
 
287321
287521
  // src/commands.ts
287522
+ init_theme();
287322
287523
  var CORE_GROUPS = ["Start", "Every day", "More"];
287323
287524
  var FULL_GROUPS = [
287324
287525
  "Set up",
287325
287526
  "Your database",
287326
287527
  "Your schema",
287528
+ "Your writes",
287327
287529
  "Read the docs",
287328
287530
  "See what's happening",
287329
287531
  "Workspace"
@@ -287362,8 +287564,8 @@ var COMMANDS = [
287362
287564
  full: {
287363
287565
  group: "Set up",
287364
287566
  rows: [
287365
- { run: "login", does: "Authorize in your browser \u2014 stores one mk_ management credential" },
287366
- { run: "login --project <slug>", does: "Same, for one project \u2014 it becomes active" }
287567
+ { run: "login", does: "Authorize in your browser, pick a project \u2014 stores its mk_ management credential" },
287568
+ { run: "login --project <slug>", does: "Same, without the picker \u2014 the named project becomes active" }
287367
287569
  ]
287368
287570
  }
287369
287571
  },
@@ -287454,6 +287656,28 @@ var COMMANDS = [
287454
287656
  ]
287455
287657
  }
287456
287658
  },
287659
+ {
287660
+ name: "claims",
287661
+ core: {
287662
+ group: "Every day",
287663
+ does: "Say what you are editing, so another writer waits instead of clobbering it"
287664
+ },
287665
+ full: {
287666
+ group: "Your writes",
287667
+ rows: [
287668
+ { run: "claims acquire <model> <id>", does: "Take the lease on one row" },
287669
+ { run: "claims acquire <model> <id> -- <cmd>", does: "Hold it only while <cmd> runs, then release" },
287670
+ { run: "claims acquire <model> <id> --queue", does: "Wait in line when it is held, instead of failing" },
287671
+ { run: "claims acquire <model> <id> --ttl 5m", does: "Lease length: 30s, 5m, 2h (default 60s)" },
287672
+ { run: "claims acquire <model> <id> --description <t>", does: "What you are doing, shown to whoever waits" },
287673
+ { run: "claims release <model> <id>", does: "Give the lease back" },
287674
+ { run: "claims heartbeat <model> <id>", does: "Extend a lease you already hold" },
287675
+ { run: "claims list [<model> [<id>]]", does: "Who holds what, and who waits" },
287676
+ { run: "claims list --actor <id>", does: "Narrow a listing to one holder" },
287677
+ { run: "claims list --json", does: "Same, machine-readable" }
287678
+ ]
287679
+ }
287680
+ },
287457
287681
  {
287458
287682
  name: "generate",
287459
287683
  full: {
@@ -287599,7 +287823,9 @@ var REDIRECTS = /* @__PURE__ */ new Map([
287599
287823
  ["disconnect", "connect deregister"],
287600
287824
  ["deregister", "connect deregister"],
287601
287825
  ["register", "connect register"],
287602
- ["rotate", "connect rotate"]
287826
+ ["rotate", "connect rotate"],
287827
+ ["claim", "claims acquire"],
287828
+ ["release", "claims release"]
287603
287829
  ]);
287604
287830
  function editDistance(a, b4) {
287605
287831
  const cols = b4.length + 1;
@@ -287636,7 +287862,22 @@ function suggestCommand(raw) {
287636
287862
  return REDIRECTS.get(best.name) ?? best.name;
287637
287863
  }
287638
287864
  function usageFor(name) {
287639
- return BY_NAME.get(name)?.usage;
287865
+ const command = BY_NAME.get(name);
287866
+ if (command === void 0) return void 0;
287867
+ if (command.usage !== void 0) return command.usage;
287868
+ const rows = command.full?.rows ?? [];
287869
+ const described = rows.filter((row) => row.does !== void 0);
287870
+ if (described.length === 0) return void 0;
287871
+ const width = Math.max(...described.map((row) => row.run.length)) + 2;
287872
+ const headline = command.core?.does;
287873
+ return [
287874
+ ` ${brand(`ablo ${name}`)}${headline !== void 0 ? ` \u2014 ${headline}` : ""}`,
287875
+ "",
287876
+ ...rows.map(
287877
+ (row) => row.does === void 0 ? ` ${row.run}` : ` ablo ${row.run.padEnd(width)}${row.does}`
287878
+ ),
287879
+ ""
287880
+ ].join("\n");
287640
287881
  }
287641
287882
  function coreRows(group) {
287642
287883
  return ALL.filter((c) => c.core?.group === group).map((c) => ({
@@ -287649,16 +287890,16 @@ function fullRows(group) {
287649
287890
  }
287650
287891
 
287651
287892
  // src/index.ts
287652
- var import_errors25 = require("@abloatai/transaction/errors");
287893
+ var import_errors26 = require("@abloatai/transaction/errors");
287653
287894
  init_push();
287654
287895
 
287655
287896
  // src/generate.ts
287656
287897
  init_cjs_shims();
287657
- var import_errors17 = require("@abloatai/transaction/errors");
287898
+ var import_errors18 = require("@abloatai/transaction/errors");
287658
287899
  var import_fs8 = require("fs");
287659
287900
  var import_path6 = require("path");
287660
287901
  var import_picocolors20 = __toESM(require_picocolors(), 1);
287661
- var import_schema7 = require("@abloatai/transaction/schema");
287902
+ var import_schema6 = require("@abloatai/transaction/schema");
287662
287903
  init_push();
287663
287904
  var DEFAULT_SCHEMA_PATH4 = "ablo/schema.ts";
287664
287905
  var DEFAULT_EXPORT3 = "schema";
@@ -287680,7 +287921,7 @@ function parseGenerateArgs(argv) {
287680
287921
  out = argv[++i] ?? out;
287681
287922
  break;
287682
287923
  default:
287683
- throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287924
+ throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287684
287925
  }
287685
287926
  }
287686
287927
  return { schemaPath, exportName, out };
@@ -287696,8 +287937,8 @@ async function generate(argv) {
287696
287937
  let source;
287697
287938
  try {
287698
287939
  const schema = await loadSchema(args.schemaPath, args.exportName);
287699
- const schemaJson = JSON.parse((0, import_schema7.serializeSchema)(schema));
287700
- source = (0, import_schema7.generateTypes)(schemaJson);
287940
+ const schemaJson = JSON.parse((0, import_schema6.serializeSchema)(schema));
287941
+ source = (0, import_schema6.generateTypes)(schemaJson);
287701
287942
  } catch (err) {
287702
287943
  console.error(import_picocolors20.default.red(` ${err instanceof Error ? err.message : String(err)}`));
287703
287944
  process.exit(1);
@@ -287713,9 +287954,10 @@ init_cjs_shims();
287713
287954
  var import_child_process2 = require("child_process");
287714
287955
  var import_picocolors21 = __toESM(require_picocolors(), 1);
287715
287956
  init_dist2();
287716
- var import_errors18 = require("@abloatai/transaction/errors");
287717
- var import_wire8 = require("@abloatai/transaction/wire");
287957
+ var import_errors19 = require("@abloatai/transaction/errors");
287958
+ var import_wire9 = require("@abloatai/transaction/wire");
287718
287959
  init_config();
287960
+ init_projects();
287719
287961
  init_theme();
287720
287962
  var CLIENT_ID = "ablo-cli";
287721
287963
  var stripSlash = (u2) => u2.replace(/\/+$/, "");
@@ -287741,11 +287983,52 @@ function parseSlugFlag(argv, flag2) {
287741
287983
  const eq = argv.find((a) => a.startsWith(`${flag2}=`));
287742
287984
  return eq ? eq.slice(flag2.length + 1) || void 0 : void 0;
287743
287985
  }
287986
+ function projectSlugOrDefault(slug) {
287987
+ return slug === DEFAULT_PROFILE ? void 0 : slug;
287988
+ }
287989
+ async function listProjectsForSession(accessToken) {
287990
+ const res = await fetch(`${DASHBOARD_URL}/api/cli/projects`, {
287991
+ headers: { authorization: `Bearer ${accessToken}`, accept: "application/json" }
287992
+ }).catch(() => null);
287993
+ if (!res) return { ok: false, reason: `${DASHBOARD_URL} could not be reached` };
287994
+ return projectListResult(res.status, await res.json().catch(() => null));
287995
+ }
287996
+ async function pickProject(accessToken) {
287997
+ const active = getActiveProject();
287998
+ const s = Y2();
287999
+ s.start("Listing projects\u2026");
288000
+ const listed = await listProjectsForSession(accessToken);
288001
+ if (!listed.ok) {
288002
+ const fallback = projectSlugOrDefault(active?.slug);
288003
+ s.stop(
288004
+ `Couldn't list projects (${listed.reason}); continuing with ${fallback ? `project ${import_picocolors21.default.bold(fallback)}` : "the organization default"}.`
288005
+ );
288006
+ return fallback;
288007
+ }
288008
+ if (listed.projects.every((p2) => p2.default)) {
288009
+ s.stop("One project, the organization default.");
288010
+ return void 0;
288011
+ }
288012
+ s.stop(`${listed.projects.length} projects`);
288013
+ const current = active ? listed.projects.find((p2) => p2.id === active.id) : void 0;
288014
+ const choice = await ve({
288015
+ message: "Project",
288016
+ options: listed.projects.map((p2) => {
288017
+ const hint = projectDisplayName(p2) ?? (p2.default ? "organization default" : void 0);
288018
+ return { value: p2, label: p2.slug, ...hint ? { hint } : {} };
288019
+ }),
288020
+ ...current ? { initialValue: current } : {}
288021
+ });
288022
+ if (pD(choice)) {
288023
+ xe("Cancelled.");
288024
+ process.exit(0);
288025
+ }
288026
+ return choice.default ? void 0 : choice.slug;
288027
+ }
287744
288028
  async function deviceLogin(argv, deps = {}) {
287745
288029
  const openUrl = deps.openUrl ?? openBrowser;
287746
288030
  Ie(`${brand("ablo")} login`);
287747
- const requested = parseSlugFlag(argv, "--project") ?? getActiveProject()?.slug;
287748
- const targetProject = requested === DEFAULT_PROFILE ? void 0 : requested;
288031
+ const flagged = parseSlugFlag(argv, "--project");
287749
288032
  const targetOrg = parseSlugFlag(argv, "--org");
287750
288033
  const interactive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
287751
288034
  let account = "login";
@@ -287824,30 +288107,33 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
287824
288107
  s.stop("Timed out waiting for approval.");
287825
288108
  process.exit(1);
287826
288109
  }
287827
- s.message(
288110
+ s.stop("Approved.");
288111
+ const targetProject = flagged !== void 0 ? projectSlugOrDefault(flagged) : interactive ? await pickProject(accessToken) : projectSlugOrDefault(getActiveProject()?.slug);
288112
+ const mint = Y2();
288113
+ mint.start(
287828
288114
  targetProject ? `Provisioning project access for ${targetProject}\u2026` : "Provisioning project access\u2026"
287829
288115
  );
287830
288116
  const provRes = await fetch(`${DASHBOARD_URL}/api/cli/provision-key`, {
287831
288117
  method: "POST",
287832
288118
  headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
287833
- // Scope the minted keys to the chosen project (`--project`/active), with
287834
- // the device_code as a legacy fallback for the /cli picker. Both harmless
287835
- // if absent → org-default keys.
288119
+ // Scope the minted keys to the chosen project, with the device_code as a
288120
+ // legacy fallback for the /cli picker. Both harmless if absent →
288121
+ // org-default keys.
287836
288122
  body: JSON.stringify({
287837
288123
  device_code: code.device_code,
287838
288124
  ...targetProject ? { project_slug: targetProject } : {}
287839
288125
  })
287840
288126
  }).catch(() => null);
287841
288127
  if (!provRes) {
287842
- s.stop("Could not provision a key.");
288128
+ mint.stop("Could not provision a key.");
287843
288129
  M2.error(
287844
288130
  `Could not reach ${DASHBOARD_URL} to finish the handoff. Check your connection and run \`ablo login\` again.`
287845
288131
  );
287846
288132
  process.exit(1);
287847
288133
  }
287848
288134
  if (!provRes.ok) {
287849
- s.stop("Could not provision a key.");
287850
- const err = (0, import_errors18.translateHttpError)(
288135
+ mint.stop("Could not provision a key.");
288136
+ const err = (0, import_errors19.translateHttpError)(
287851
288137
  provRes.status,
287852
288138
  await provRes.json().catch(() => null),
287853
288139
  provRes.headers.get("x-request-id") ?? void 0
@@ -287864,11 +288150,11 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
287864
288150
  }
287865
288151
  process.exit(1);
287866
288152
  }
287867
- const parsedProv = import_wire8.provisionKeyResponseSchema.safeParse(
288153
+ const parsedProv = import_wire9.provisionKeyResponseSchema.safeParse(
287868
288154
  await provRes.json().catch(() => null)
287869
288155
  );
287870
288156
  if (!parsedProv.success) {
287871
- s.stop("Could not provision a key.");
288157
+ mint.stop("Could not provision a key.");
287872
288158
  M2.error("The key handoff returned something this version does not recognize.");
287873
288159
  M2.error(`Try again, or upgrade with ${import_picocolors21.default.bold("npm i -g @abloatai/ablo")}.`);
287874
288160
  process.exit(1);
@@ -287893,7 +288179,7 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
287893
288179
  },
287894
288180
  { mode: "sandbox", activeProject: prov.project ?? void 0 }
287895
288181
  );
287896
- s.stop(`Saved project credential to ${path}`);
288182
+ mint.stop(`Saved project credential to ${path}`);
287897
288183
  const orgLabel = prov.organizationSlug ? ` to ${import_picocolors21.default.bold(prov.organizationSlug)}` : "";
287898
288184
  const where = prov.project ? ` ${import_picocolors21.default.dim(`(project ${prov.project.slug})`)}` : "";
287899
288185
  Se(
@@ -287910,10 +288196,10 @@ function logout() {
287910
288196
  } else {
287911
288197
  console.log(` ${import_picocolors21.default.dim("\u25CB")} Not logged in \u2014 nothing to remove.`);
287912
288198
  }
287913
- if (process.env.ABLO_MANAGEMENT_KEY) {
288199
+ if (process.env.ABLO_API_KEY?.startsWith("mk_")) {
287914
288200
  console.log(
287915
288201
  import_picocolors21.default.dim(
287916
- ` Note: ${import_picocolors21.default.bold("ABLO_MANAGEMENT_KEY")} is still set in this shell and takes precedence.`
288202
+ ` Note: ${import_picocolors21.default.bold("ABLO_API_KEY")} still contains an ${import_picocolors21.default.bold("mk_")} credential in this shell and takes precedence.`
287917
288203
  )
287918
288204
  );
287919
288205
  }
@@ -287929,7 +288215,6 @@ init_config();
287929
288215
  init_target();
287930
288216
  init_theme();
287931
288217
  init_controlPlane();
287932
- var import_schema8 = require("@abloatai/transaction/coordination/schema");
287933
288218
  init_readiness();
287934
288219
  function expiryLabel(iso) {
287935
288220
  const ms = Date.parse(iso) - Date.now();
@@ -287952,13 +288237,6 @@ async function ping2(apiUrl3) {
287952
288237
  clearTimeout(t);
287953
288238
  }
287954
288239
  }
287955
- function formatConflict(conflict) {
287956
- if (!conflict) return "";
287957
- const parts = import_schema8.participantKindSchema.options.flatMap(
287958
- (k3) => conflict[k3] ? [`${k3}:${conflict[k3]}`] : []
287959
- );
287960
- return parts.length ? `{${parts.join(",")}}` : "";
287961
- }
287962
288240
  function printTargetLines(target, localProject, storedOrganizationId, storedOrganizationSlug) {
287963
288241
  const confirmed = target?.confirmed ?? null;
287964
288242
  const org = confirmed?.organizationId ?? storedOrganizationId;
@@ -288179,9 +288457,7 @@ async function status(args = []) {
288179
288457
  );
288180
288458
  for (const m2 of pushed.models) {
288181
288459
  const tn = m2.typename === m2.key ? import_picocolors22.default.dim(`typename=${m2.typename}`) : import_picocolors22.default.yellow(`typename=${m2.typename}`);
288182
- const conflict = formatConflict(m2.conflict);
288183
- const conflictStr2 = conflict ? ` ${import_picocolors22.default.dim(`conflict=${conflict}`)}` : "";
288184
- console.log(` ${import_picocolors22.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}${conflictStr2}`);
288460
+ console.log(` ${import_picocolors22.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}`);
288185
288461
  }
288186
288462
  } else if (pushed && !pushed.active) {
288187
288463
  console.log(
@@ -288223,8 +288499,8 @@ async function status(args = []) {
288223
288499
 
288224
288500
  // src/logs.ts
288225
288501
  init_cjs_shims();
288226
- var import_errors19 = require("@abloatai/transaction/errors");
288227
- var import_wire9 = require("@abloatai/transaction/wire");
288502
+ var import_errors20 = require("@abloatai/transaction/errors");
288503
+ var import_wire10 = require("@abloatai/transaction/wire");
288228
288504
  var import_picocolors23 = __toESM(require_picocolors(), 1);
288229
288505
  init_config();
288230
288506
  init_theme();
@@ -288265,12 +288541,12 @@ function parseLogsArgs(argv) {
288265
288541
  args.json = true;
288266
288542
  break;
288267
288543
  case "--mode":
288268
- throw new import_errors19.AbloValidationError(
288544
+ throw new import_errors20.AbloValidationError(
288269
288545
  "--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
288270
288546
  { code: "cli_invalid_arguments" }
288271
288547
  );
288272
288548
  default:
288273
- throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288549
+ throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288274
288550
  }
288275
288551
  }
288276
288552
  return args;
@@ -288335,7 +288611,7 @@ async function logs(argv) {
288335
288611
  const json = await res.json();
288336
288612
  return {
288337
288613
  events: json.data ?? json.events ?? [],
288338
- cursor: json.next_cursor ?? (json.cursor != null ? (0, import_wire9.formatFeedCursor)({ log: json.cursor, claims: 0 }) : (0, import_wire9.formatFeedCursor)(import_wire9.FEED_CURSOR_START))
288614
+ cursor: json.next_cursor ?? (json.cursor != null ? (0, import_wire10.formatFeedCursor)({ log: json.cursor, claims: 0 }) : (0, import_wire10.formatFeedCursor)(import_wire10.FEED_CURSOR_START))
288339
288615
  };
288340
288616
  }
288341
288617
  if (!args.json) {
@@ -288367,9 +288643,9 @@ async function logs(argv) {
288367
288643
  });
288368
288644
  if (!page) continue;
288369
288645
  for (const e2 of page.events) render2(e2, args.json);
288370
- const prev = (0, import_wire9.parseFeedCursor)(cursor);
288371
- const next = (0, import_wire9.parseFeedCursor)(page.cursor);
288372
- if (prev && next && (0, import_wire9.feedCursorAdvanced)(prev, next)) cursor = page.cursor;
288646
+ const prev = (0, import_wire10.parseFeedCursor)(cursor);
288647
+ const next = (0, import_wire10.parseFeedCursor)(page.cursor);
288648
+ if (prev && next && (0, import_wire10.feedCursorAdvanced)(prev, next)) cursor = page.cursor;
288373
288649
  }
288374
288650
  }
288375
288651
 
@@ -288549,10 +288825,10 @@ async function webhooks(argv) {
288549
288825
 
288550
288826
  // src/check.ts
288551
288827
  init_cjs_shims();
288552
- var import_errors20 = require("@abloatai/transaction/errors");
288828
+ var import_errors21 = require("@abloatai/transaction/errors");
288553
288829
  var import_picocolors25 = __toESM(require_picocolors(), 1);
288554
288830
  init_src();
288555
- var import_schema9 = require("@abloatai/transaction/schema");
288831
+ var import_schema8 = require("@abloatai/transaction/schema");
288556
288832
  init_push();
288557
288833
 
288558
288834
  // src/schemaIr.ts
@@ -288627,14 +288903,15 @@ function emitSchemaSource(schema, importPath) {
288627
288903
 
288628
288904
  // src/schemaSource.ts
288629
288905
  init_cjs_shims();
288906
+ var import_schema7 = require("@abloatai/transaction/schema");
288630
288907
  var TENANCY_COLUMN = "organization_id";
288631
- var BASE_FIELDS = /* @__PURE__ */ new Set(["id", "organizationId", "createdBy", "createdAt", "updatedAt"]);
288908
+ var BASE_FIELDS = /* @__PURE__ */ new Set([
288909
+ ...import_schema7.BASE_FIELDS,
288910
+ "organizationId"
288911
+ ]);
288632
288912
  var BASE_COLUMNS = /* @__PURE__ */ new Set([
288633
- "id",
288634
- "organization_id",
288635
- "created_by",
288636
- "created_at",
288637
- "updated_at"
288913
+ ...import_schema7.BASE_FIELDS.map(camelToSnake),
288914
+ TENANCY_COLUMN
288638
288915
  ]);
288639
288916
  function fieldNameForColumn(column) {
288640
288917
  const camel2 = column.replace(/_([a-z0-9])/g, (_3, c) => c.toUpperCase());
@@ -288697,7 +288974,7 @@ function parseCheckArgs(argv) {
288697
288974
  appSchema = argv[++i] ?? appSchema;
288698
288975
  break;
288699
288976
  default:
288700
- throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288977
+ throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
288701
288978
  }
288702
288979
  }
288703
288980
  return { schemaPath, exportName, appSchema };
@@ -288779,9 +289056,9 @@ async function check(argv) {
288779
289056
  process.exit(1);
288780
289057
  }
288781
289058
  const schema = await loadSchema(args.schemaPath, args.exportName);
288782
- const schemaJson = JSON.parse((0, import_schema9.serializeSchema)(schema));
289059
+ const schemaJson = JSON.parse((0, import_schema8.serializeSchema)(schema));
288783
289060
  const accessFindings = new Map(
288784
- (0, import_schema9.auditSchemaAccessPolicies)(schemaJson).map((finding) => [finding.model, finding])
289061
+ (0, import_schema8.auditSchemaAccessPolicies)(schemaJson).map((finding) => [finding.model, finding])
288785
289062
  );
288786
289063
  console.log(`
288787
289064
  ${brand("ablo")} ${import_picocolors25.default.dim("check")} ${import_picocolors25.default.dim(`schema "${args.appSchema}"`)}
@@ -288830,7 +289107,7 @@ async function check(argv) {
288830
289107
  );
288831
289108
  }
288832
289109
  if (!present.has("id")) problems.push('missing primary key "id"');
288833
- const orgCol = (0, import_schema9.tenancyColumn)((0, import_schema9.resolveTenancy)(model));
289110
+ const orgCol = (0, import_schema8.tenancyColumn)((0, import_schema8.resolveTenancy)(model));
288834
289111
  if (orgCol && !present.has(orgCol)) {
288835
289112
  problems.push(
288836
289113
  `missing "${orgCol}" \u2014 Ablo isolates tenants (RLS) and routes realtime by it, so a table without it has no safe boundary. Add the column, or use a Data Source endpoint.`
@@ -288880,9 +289157,244 @@ async function check(argv) {
288880
289157
  process.exit(errors > 0 ? 1 : 0);
288881
289158
  }
288882
289159
 
288883
- // src/upgrade.ts
289160
+ // src/claims.ts
288884
289161
  init_cjs_shims();
289162
+ var import_node_child_process3 = require("child_process");
288885
289163
  var import_picocolors26 = __toESM(require_picocolors(), 1);
289164
+ var import_contract = require("@abloatai/transaction/claims/contract");
289165
+ var import_routes = require("@abloatai/transaction/claims/routes");
289166
+ init_controlPlane();
289167
+ init_config();
289168
+ function requireRuntimeKey() {
289169
+ const { key } = resolveRuntimeApiKey();
289170
+ if (!key) {
289171
+ console.error(
289172
+ import_picocolors26.default.red(" No runtime credential.") + import_picocolors26.default.dim(
289173
+ ` Run ${import_picocolors26.default.bold("npx ablo login")}, or set ${import_picocolors26.default.bold("ABLO_API_KEY")} to a runtime key.`
289174
+ )
289175
+ );
289176
+ process.exit(1);
289177
+ }
289178
+ return key;
289179
+ }
289180
+ var VALUE_FLAGS = /* @__PURE__ */ new Set(["--ttl", "--description", "--actor"]);
289181
+ function flagValue(argv, name) {
289182
+ const at = argv.indexOf(`--${name}`);
289183
+ return at === -1 ? void 0 : argv[at + 1];
289184
+ }
289185
+ function parseFlags(argv) {
289186
+ return {
289187
+ json: argv.includes("--json") || process.env.ABLO_JSON === "1",
289188
+ queue: argv.includes("--queue"),
289189
+ ttl: flagValue(argv, "ttl"),
289190
+ description: flagValue(argv, "description"),
289191
+ actor: flagValue(argv, "actor")
289192
+ };
289193
+ }
289194
+ function splitAtCommand(argv) {
289195
+ const at = argv.indexOf("--");
289196
+ return at === -1 ? { args: argv, command: [] } : { args: argv.slice(0, at), command: argv.slice(at + 1) };
289197
+ }
289198
+ function positionals(args) {
289199
+ const out = [];
289200
+ for (let i = 0; i < args.length; i += 1) {
289201
+ const arg = args[i];
289202
+ if (arg === void 0) continue;
289203
+ if (VALUE_FLAGS.has(arg)) {
289204
+ i += 1;
289205
+ continue;
289206
+ }
289207
+ if (arg.startsWith("-")) continue;
289208
+ out.push(arg);
289209
+ }
289210
+ return out;
289211
+ }
289212
+ async function acquireClaim(model, id, flags, apiKey) {
289213
+ return requestControlPlane({
289214
+ path: (0, import_routes.claimOnModelPath)({ model, id }),
289215
+ method: "POST",
289216
+ apiKey,
289217
+ body: {
289218
+ ...flags.ttl !== void 0 ? { ttl: flags.ttl } : {},
289219
+ ...flags.description !== void 0 ? { description: flags.description } : {},
289220
+ ...flags.queue ? { queue: true } : {}
289221
+ },
289222
+ responseSchema: import_contract.claimAcquireResponseSchema
289223
+ });
289224
+ }
289225
+ async function releaseClaim(model, id, apiKey) {
289226
+ const reply = await requestControlPlane({
289227
+ path: (0, import_routes.claimOnModelPath)({ model, id }),
289228
+ method: "DELETE",
289229
+ apiKey,
289230
+ responseSchema: import_contract.claimReleaseReplySchema
289231
+ });
289232
+ return reply.released;
289233
+ }
289234
+ async function beat(model, id, ttl, apiKey) {
289235
+ await requestControlPlane({
289236
+ path: (0, import_routes.claimHeartbeatOnModelPath)({ model, id }),
289237
+ method: "POST",
289238
+ apiKey,
289239
+ body: ttl !== void 0 ? { ttl } : {},
289240
+ responseSchema: import_contract.claimHeartbeatReplySchema
289241
+ });
289242
+ }
289243
+ async function pollClaim(claimId, apiKey) {
289244
+ return requestControlPlane({
289245
+ path: (0, import_routes.claimByIdPath)(claimId),
289246
+ apiKey,
289247
+ responseSchema: import_contract.claimStateSchema
289248
+ });
289249
+ }
289250
+ async function waitForGrant(claimId, ttl, apiKey) {
289251
+ const everyMs = Math.max(1e3, Math.floor((0, import_contract.claimTtlMs)(ttl) / 4));
289252
+ for (; ; ) {
289253
+ await new Promise((resolve11) => setTimeout(resolve11, everyMs));
289254
+ const state = await pollClaim(claimId, apiKey);
289255
+ if (state.status === "active") return;
289256
+ if (state.status !== "queued") {
289257
+ throw new Error(`the wait ended without the lease (${state.status})`);
289258
+ }
289259
+ }
289260
+ }
289261
+ function describeAcquired(model, id, granted) {
289262
+ if (granted.status === "queued") {
289263
+ const ahead = granted.position;
289264
+ return ` ${import_picocolors26.default.yellow("\xB7")} Waiting for ${import_picocolors26.default.bold(`${model} ${id}`)}. ` + import_picocolors26.default.dim(ahead === 0 ? "Next in line." : `${ahead} ahead of you.`);
289265
+ }
289266
+ return ` ${import_picocolors26.default.green("\u2713")} Holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`;
289267
+ }
289268
+ async function holdWhile(model, id, flags, apiKey, command) {
289269
+ const granted = await acquireClaim(model, id, flags, apiKey);
289270
+ if (granted.status === "queued") {
289271
+ if (!flags.json) console.error(describeAcquired(model, id, granted));
289272
+ await waitForGrant(granted.id, flags.ttl, apiKey);
289273
+ }
289274
+ if (!flags.json) console.error(` ${import_picocolors26.default.green("\u2713")} Holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
289275
+ const everyMs = Math.max(1e3, Math.floor((0, import_contract.claimTtlMs)(flags.ttl) / 3));
289276
+ const timer2 = setInterval(() => {
289277
+ void beat(model, id, flags.ttl, apiKey).catch(() => {
289278
+ });
289279
+ }, everyMs);
289280
+ let released = false;
289281
+ const giveBack = async () => {
289282
+ if (released) return;
289283
+ released = true;
289284
+ clearInterval(timer2);
289285
+ try {
289286
+ await releaseClaim(model, id, apiKey);
289287
+ } catch {
289288
+ }
289289
+ };
289290
+ const [head, ...rest] = command;
289291
+ if (head === void 0) {
289292
+ await giveBack();
289293
+ throw new Error("no command was given after `--`");
289294
+ }
289295
+ const code = await new Promise((resolve11) => {
289296
+ const child = (0, import_node_child_process3.spawn)(head, rest, { stdio: "inherit" });
289297
+ const forward = (signal) => {
289298
+ child.kill(signal);
289299
+ };
289300
+ process.on("SIGINT", forward);
289301
+ process.on("SIGTERM", forward);
289302
+ child.on("error", () => {
289303
+ process.off("SIGINT", forward);
289304
+ process.off("SIGTERM", forward);
289305
+ resolve11(127);
289306
+ });
289307
+ child.on("close", (status2) => {
289308
+ process.off("SIGINT", forward);
289309
+ process.off("SIGTERM", forward);
289310
+ resolve11(status2 ?? 1);
289311
+ });
289312
+ });
289313
+ await giveBack();
289314
+ if (!flags.json) console.error(` ${import_picocolors26.default.dim("\xB7")} ${import_picocolors26.default.dim(`Released ${model} ${id}.`)}`);
289315
+ return code;
289316
+ }
289317
+ function renderList(rows) {
289318
+ if (rows.length === 0) {
289319
+ console.log(` ${import_picocolors26.default.dim("Nothing is held right now.")}`);
289320
+ return;
289321
+ }
289322
+ const held = rows.filter((row) => row.status !== "queued").length;
289323
+ const waiting = rows.length - held;
289324
+ console.log();
289325
+ for (const row of rows) {
289326
+ const where = `${row.target.model} ${row.target.id}`;
289327
+ const state = row.status === "queued" ? import_picocolors26.default.yellow(row.position === void 0 ? "waiting" : `waiting (${row.position} ahead)`) : import_picocolors26.default.green("held");
289328
+ console.log(
289329
+ ` ${import_picocolors26.default.bold(where.padEnd(28))} ${state.padEnd(28)} ${import_picocolors26.default.dim(row.description ?? row.actor)}`
289330
+ );
289331
+ }
289332
+ console.log();
289333
+ console.log(import_picocolors26.default.dim(` ${held} held, ${waiting} waiting.`));
289334
+ console.log();
289335
+ }
289336
+ async function claims(argv = []) {
289337
+ const { args, command } = splitAtCommand(argv);
289338
+ const flags = parseFlags(args);
289339
+ const [verb, ...rest] = positionals(args);
289340
+ if (verb === void 0 || verb === "help" || args.includes("--help")) {
289341
+ console.log(usageFor("claims"));
289342
+ return;
289343
+ }
289344
+ const apiKey = requireRuntimeKey();
289345
+ if (verb === "list") {
289346
+ const [model2, id2] = rest;
289347
+ const query = new URLSearchParams();
289348
+ if (model2 !== void 0) query.set("model", model2);
289349
+ if (id2 !== void 0) query.set("id", id2);
289350
+ if (flags.actor !== void 0) query.set("actorId", flags.actor);
289351
+ const suffix = query.toString();
289352
+ const page = await requestControlPlane({
289353
+ path: `${import_routes.CLAIM_ROUTES.collection}${suffix ? `?${suffix}` : ""}`,
289354
+ apiKey,
289355
+ responseSchema: import_contract.claimListResponseSchema
289356
+ });
289357
+ if (flags.json) console.log(JSON.stringify(page, null, 2));
289358
+ else renderList(page.data);
289359
+ return;
289360
+ }
289361
+ const [model, id] = rest;
289362
+ if (model === void 0 || id === void 0) {
289363
+ console.error(` ${import_picocolors26.default.red("\u2717")} Name the row: ${import_picocolors26.default.bold(`ablo claims ${verb} <model> <id>`)}.`);
289364
+ process.exitCode = 1;
289365
+ return;
289366
+ }
289367
+ if (verb === "acquire") {
289368
+ if (command.length > 0) {
289369
+ process.exitCode = await holdWhile(model, id, flags, apiKey, command);
289370
+ return;
289371
+ }
289372
+ const granted = await acquireClaim(model, id, flags, apiKey);
289373
+ if (flags.json) console.log(JSON.stringify(granted, null, 2));
289374
+ else console.log(describeAcquired(model, id, granted));
289375
+ return;
289376
+ }
289377
+ if (verb === "release") {
289378
+ const released = await releaseClaim(model, id, apiKey);
289379
+ if (flags.json) console.log(JSON.stringify({ object: "claim_release", released }, null, 2));
289380
+ else if (released) console.log(` ${import_picocolors26.default.green("\u2713")} Released ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
289381
+ else console.log(` ${import_picocolors26.default.dim("\xB7")} ${import_picocolors26.default.dim(`You were not holding ${model} ${id}.`)}`);
289382
+ return;
289383
+ }
289384
+ if (verb === "heartbeat") {
289385
+ await beat(model, id, flags.ttl, apiKey);
289386
+ if (flags.json) console.log(JSON.stringify({ object: "claim_heartbeat", ok: true }, null, 2));
289387
+ else console.log(` ${import_picocolors26.default.green("\u2713")} Still holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
289388
+ return;
289389
+ }
289390
+ console.error(` ${import_picocolors26.default.red("\u2717")} Unknown: ${import_picocolors26.default.bold(`ablo claims ${verb}`)}.`);
289391
+ console.error(usageFor("claims"));
289392
+ process.exitCode = 1;
289393
+ }
289394
+
289395
+ // src/upgrade.ts
289396
+ init_cjs_shims();
289397
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
288886
289398
  var import_ts_morph = __toESM(require_ts_morph(), 1);
288887
289399
  var DEFAULT_GLOBS = ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}", "ablo/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}"];
288888
289400
  var VERB_ARGS = {
@@ -288924,12 +289436,14 @@ function verbRewrite(call, verb) {
288924
289436
  const args = call.getArguments();
288925
289437
  const first = args[0];
288926
289438
  if (first === void 0) return null;
288927
- const calleeText = call.getExpression().getText();
289439
+ const calleeText = verb === "retrieve" ? `${call.getExpression().getText().slice(0, -"retrieve".length)}get` : call.getExpression().getText();
288928
289440
  if (verb === "create") {
288929
289441
  if (import_ts_morph.Node.isObjectLiteralExpression(first) && hasKey2(first, "data")) return null;
288930
289442
  return `${calleeText}({ data: ${first.getText()}${spreadOpts(args[1])} })`;
288931
289443
  }
288932
- if (import_ts_morph.Node.isObjectLiteralExpression(first)) return null;
289444
+ if (import_ts_morph.Node.isObjectLiteralExpression(first)) {
289445
+ return verb === "retrieve" ? `${calleeText}(${first.getText()})` : null;
289446
+ }
288933
289447
  const keyed = params.map((key, i) => args[i] ? `${key}: ${args[i].getText()}` : null).filter(Boolean);
288934
289448
  return `${calleeText}({ ${keyed.join(", ")}${spreadOpts(args[params.length])} })`;
288935
289449
  }
@@ -288945,7 +289459,7 @@ function loadRewrite(call) {
288945
289459
  if (import_ts_morph.Node.isObjectLiteralExpression(whereVal)) {
288946
289460
  const idProp = whereVal.getProperty("id");
288947
289461
  if (idProp && whereVal.getProperties().length === 1 && import_ts_morph.Node.isPropertyAssignment(idProp)) {
288948
- return `${base}.retrieve({ id: ${idProp.getInitializerOrThrow().getText()} })`;
289462
+ return `${base}.get({ id: ${idProp.getInitializerOrThrow().getText()} })`;
288949
289463
  }
288950
289464
  }
288951
289465
  return `${base}.list({ where: ${whereVal.getText()} })`;
@@ -288960,7 +289474,7 @@ async function upgrade(argv) {
288960
289474
  project.addSourceFilesAtPaths(globs.length > 0 ? globs : DEFAULT_GLOBS);
288961
289475
  const files = project.getSourceFiles();
288962
289476
  if (files.length === 0) {
288963
- console.log(import_picocolors26.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
289477
+ console.log(import_picocolors27.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
288964
289478
  return;
288965
289479
  }
288966
289480
  const edits = [];
@@ -289008,7 +289522,7 @@ async function upgrade(argv) {
289008
289522
  } else if (method === "load") {
289009
289523
  const next = loadRewrite(call);
289010
289524
  if (next) {
289011
- record(call, "load\u2192retrieve/list", (call.getText().split("\n")[0] ?? "").slice(0, 80), next.slice(0, 80));
289525
+ record(call, "load\u2192get/list", (call.getText().split("\n")[0] ?? "").slice(0, 80), next.slice(0, 80));
289012
289526
  call.replaceWithText(next);
289013
289527
  }
289014
289528
  }
@@ -289034,39 +289548,39 @@ async function upgrade(argv) {
289034
289548
  const rel = (f) => f.replace(cwd + "/", "");
289035
289549
  console.log();
289036
289550
  if (edits.length === 0 && manual.length === 0) {
289037
- console.log(import_picocolors26.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
289551
+ console.log(import_picocolors27.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
289038
289552
  return;
289039
289553
  }
289040
289554
  if (edits.length > 0) {
289041
- console.log(import_picocolors26.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
289555
+ console.log(import_picocolors27.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
289042
289556
  for (const e2 of edits) {
289043
- console.log(` ${import_picocolors26.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors26.default.cyan(e2.rule)}`);
289044
- console.log(` ${import_picocolors26.default.red("-")} ${e2.before}`);
289045
- console.log(` ${import_picocolors26.default.green("+")} ${e2.after}`);
289557
+ console.log(` ${import_picocolors27.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors27.default.cyan(e2.rule)}`);
289558
+ console.log(` ${import_picocolors27.default.red("-")} ${e2.before}`);
289559
+ console.log(` ${import_picocolors27.default.green("+")} ${e2.after}`);
289046
289560
  }
289047
289561
  }
289048
289562
  if (manual.length > 0) {
289049
289563
  console.log();
289050
- console.log(import_picocolors26.default.bold(import_picocolors26.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
289564
+ console.log(import_picocolors27.default.bold(import_picocolors27.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
289051
289565
  for (const m2 of manual) {
289052
- console.log(` ${import_picocolors26.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors26.default.yellow(m2.rule)}`);
289053
- console.log(` ${import_picocolors26.default.dim(m2.snippet)}`);
289566
+ console.log(` ${import_picocolors27.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors27.default.yellow(m2.rule)}`);
289567
+ console.log(` ${import_picocolors27.default.dim(m2.snippet)}`);
289054
289568
  console.log(` \u2192 ${m2.hint}`);
289055
289569
  }
289056
289570
  }
289057
289571
  console.log();
289058
289572
  if (write) {
289059
289573
  await project.save();
289060
- console.log(import_picocolors26.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
289574
+ console.log(import_picocolors27.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
289061
289575
  } else {
289062
- console.log(import_picocolors26.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
289576
+ console.log(import_picocolors27.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
289063
289577
  }
289064
289578
  }
289065
289579
 
289066
289580
  // src/pull.ts
289067
289581
  init_cjs_shims();
289068
- var import_errors21 = require("@abloatai/transaction/errors");
289069
- var import_picocolors27 = __toESM(require_picocolors(), 1);
289582
+ var import_errors22 = require("@abloatai/transaction/errors");
289583
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
289070
289584
  init_src();
289071
289585
  var import_fs10 = require("fs");
289072
289586
  init_theme();
@@ -289094,7 +289608,7 @@ function parsePullArgs(argv) {
289094
289608
  force = true;
289095
289609
  break;
289096
289610
  default:
289097
- throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289611
+ throw new import_errors22.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289098
289612
  }
289099
289613
  }
289100
289614
  return { out, appSchema, importPath, force };
@@ -289164,56 +289678,56 @@ async function pull(argv) {
289164
289678
  try {
289165
289679
  args = parsePullArgs(argv);
289166
289680
  } catch (err) {
289167
- console.error(import_picocolors27.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289681
+ console.error(import_picocolors28.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289168
289682
  process.exit(1);
289169
289683
  }
289170
289684
  const dbUrl = readProjectAdminDatabaseUrl();
289171
289685
  if (!dbUrl) {
289172
289686
  console.error(
289173
- import_picocolors27.default.red(` No database.`) + import_picocolors27.default.dim(` Set ${import_picocolors27.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
289687
+ import_picocolors28.default.red(` No database.`) + import_picocolors28.default.dim(` Set ${import_picocolors28.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
289174
289688
  );
289175
289689
  process.exit(1);
289176
289690
  }
289177
289691
  if ((0, import_fs10.existsSync)(args.out) && !args.force) {
289178
289692
  console.error(
289179
- import_picocolors27.default.red(` ${args.out} already exists.`) + import_picocolors27.default.dim(` Re-run with ${import_picocolors27.default.bold("--force")} to overwrite.`)
289693
+ import_picocolors28.default.red(` ${args.out} already exists.`) + import_picocolors28.default.dim(` Re-run with ${import_picocolors28.default.bold("--force")} to overwrite.`)
289180
289694
  );
289181
289695
  process.exit(1);
289182
289696
  }
289183
289697
  console.log(`
289184
- ${brand("ablo")} ${import_picocolors27.default.dim("pull")} ${import_picocolors27.default.dim(`schema "${args.appSchema}"`)}
289698
+ ${brand("ablo")} ${import_picocolors28.default.dim("pull")} ${import_picocolors28.default.dim(`schema "${args.appSchema}"`)}
289185
289699
  `);
289186
289700
  let result;
289187
289701
  try {
289188
289702
  result = await buildSchemaSourceFromDb({ dbUrl, appSchema: args.appSchema, importPath: args.importPath });
289189
289703
  } catch (err) {
289190
- console.error(import_picocolors27.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
289704
+ console.error(import_picocolors28.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
289191
289705
  process.exit(1);
289192
289706
  }
289193
289707
  if (result.models.length === 0) {
289194
289708
  console.error(
289195
- import_picocolors27.default.yellow(` No adoptable tables found`) + import_picocolors27.default.dim(` (a model needs an ${import_picocolors27.default.bold("id")} + ${import_picocolors27.default.bold("organization_id")} column).`)
289709
+ import_picocolors28.default.yellow(` No adoptable tables found`) + import_picocolors28.default.dim(` (a model needs an ${import_picocolors28.default.bold("id")} + ${import_picocolors28.default.bold("organization_id")} column).`)
289196
289710
  );
289197
289711
  process.exit(1);
289198
289712
  }
289199
289713
  (0, import_fs10.writeFileSync)(args.out, result.source);
289200
- console.log(` ${import_picocolors27.default.green("\u2713")} wrote ${import_picocolors27.default.bold(args.out)} ${import_picocolors27.default.dim(`(${result.models.length} models)`)}`);
289201
- console.log(` ${import_picocolors27.default.dim(`models: ${result.models.join(", ")}`)}`);
289714
+ console.log(` ${import_picocolors28.default.green("\u2713")} wrote ${import_picocolors28.default.bold(args.out)} ${import_picocolors28.default.dim(`(${result.models.length} models)`)}`);
289715
+ console.log(` ${import_picocolors28.default.dim(`models: ${result.models.join(", ")}`)}`);
289202
289716
  if (result.skipped.length > 0) {
289203
- console.log(` ${import_picocolors27.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289204
- for (const s of result.skipped) console.log(` ${import_picocolors27.default.dim(`- ${s.name}: ${s.reason}`)}`);
289717
+ console.log(` ${import_picocolors28.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289718
+ for (const s of result.skipped) console.log(` ${import_picocolors28.default.dim(`- ${s.name}: ${s.reason}`)}`);
289205
289719
  }
289206
289720
  console.log(
289207
289721
  `
289208
- ${import_picocolors27.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors27.default.bold("ablo check")}.
289722
+ ${import_picocolors28.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors28.default.bold("ablo check")}.
289209
289723
  `
289210
289724
  );
289211
289725
  }
289212
289726
 
289213
289727
  // src/prismaPull.ts
289214
289728
  init_cjs_shims();
289215
- var import_errors22 = require("@abloatai/transaction/errors");
289216
- var import_picocolors28 = __toESM(require_picocolors(), 1);
289729
+ var import_errors23 = require("@abloatai/transaction/errors");
289730
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
289217
289731
  var import_fs11 = require("fs");
289218
289732
  init_theme();
289219
289733
  var DEFAULT_SCHEMA = "prisma/schema.prisma";
@@ -289410,7 +289924,7 @@ function parsePrismaPullArgs(argv) {
289410
289924
  force = true;
289411
289925
  break;
289412
289926
  default:
289413
- if (arg.startsWith("--")) throw new import_errors22.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289927
+ if (arg.startsWith("--")) throw new import_errors23.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289414
289928
  schema = arg;
289415
289929
  }
289416
289930
  }
@@ -289421,56 +289935,56 @@ async function prismaPull(argv) {
289421
289935
  try {
289422
289936
  args = parsePrismaPullArgs(argv);
289423
289937
  } catch (err) {
289424
- console.error(import_picocolors28.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289938
+ console.error(import_picocolors29.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289425
289939
  process.exit(1);
289426
289940
  }
289427
289941
  if (!(0, import_fs11.existsSync)(args.schema)) {
289428
289942
  console.error(
289429
- import_picocolors28.default.red(` No Prisma schema at ${import_picocolors28.default.bold(args.schema)}.`) + import_picocolors28.default.dim(` Pass a path: ${import_picocolors28.default.bold("ablo pull prisma <path>")}.`)
289943
+ import_picocolors29.default.red(` No Prisma schema at ${import_picocolors29.default.bold(args.schema)}.`) + import_picocolors29.default.dim(` Pass a path: ${import_picocolors29.default.bold("ablo pull prisma <path>")}.`)
289430
289944
  );
289431
289945
  process.exit(1);
289432
289946
  }
289433
289947
  if ((0, import_fs11.existsSync)(args.out) && !args.force) {
289434
289948
  console.error(
289435
- import_picocolors28.default.red(` ${args.out} already exists.`) + import_picocolors28.default.dim(` Re-run with ${import_picocolors28.default.bold("--force")} to overwrite.`)
289949
+ import_picocolors29.default.red(` ${args.out} already exists.`) + import_picocolors29.default.dim(` Re-run with ${import_picocolors29.default.bold("--force")} to overwrite.`)
289436
289950
  );
289437
289951
  process.exit(1);
289438
289952
  }
289439
289953
  console.log(`
289440
- ${brand("ablo")} ${import_picocolors28.default.dim("pull prisma")} ${import_picocolors28.default.dim(args.schema)}
289954
+ ${brand("ablo")} ${import_picocolors29.default.dim("pull prisma")} ${import_picocolors29.default.dim(args.schema)}
289441
289955
  `);
289442
289956
  let result;
289443
289957
  try {
289444
289958
  const src = (0, import_fs11.readFileSync)(args.schema, "utf8");
289445
289959
  result = buildSchemaSourceFromPrisma({ src, importPath: args.importPath });
289446
289960
  } catch (err) {
289447
- console.error(import_picocolors28.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
289961
+ console.error(import_picocolors29.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
289448
289962
  process.exit(1);
289449
289963
  }
289450
289964
  if (result.models.length === 0) {
289451
289965
  console.error(
289452
- import_picocolors28.default.yellow(` No adoptable models found`) + import_picocolors28.default.dim(` (a model needs an ${import_picocolors28.default.bold("id")} + ${import_picocolors28.default.bold("organizationId")} / ${import_picocolors28.default.bold("organization_id")}).`)
289966
+ import_picocolors29.default.yellow(` No adoptable models found`) + import_picocolors29.default.dim(` (a model needs an ${import_picocolors29.default.bold("id")} + ${import_picocolors29.default.bold("organizationId")} / ${import_picocolors29.default.bold("organization_id")}).`)
289453
289967
  );
289454
289968
  process.exit(1);
289455
289969
  }
289456
289970
  (0, import_fs11.writeFileSync)(args.out, result.source);
289457
- console.log(` ${import_picocolors28.default.green("\u2713")} wrote ${import_picocolors28.default.bold(args.out)} ${import_picocolors28.default.dim(`(${result.models.length} models)`)}`);
289458
- console.log(` ${import_picocolors28.default.dim(`models: ${result.models.join(", ")}`)}`);
289971
+ console.log(` ${import_picocolors29.default.green("\u2713")} wrote ${import_picocolors29.default.bold(args.out)} ${import_picocolors29.default.dim(`(${result.models.length} models)`)}`);
289972
+ console.log(` ${import_picocolors29.default.dim(`models: ${result.models.join(", ")}`)}`);
289459
289973
  if (result.skipped.length > 0) {
289460
- console.log(` ${import_picocolors28.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
289461
- for (const s of result.skipped) console.log(` ${import_picocolors28.default.dim(`- ${s.name}: ${s.reason}`)}`);
289974
+ console.log(` ${import_picocolors29.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
289975
+ for (const s of result.skipped) console.log(` ${import_picocolors29.default.dim(`- ${s.name}: ${s.reason}`)}`);
289462
289976
  }
289463
289977
  console.log(
289464
289978
  `
289465
- ${import_picocolors28.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors28.default.bold("ablo check")}.
289979
+ ${import_picocolors29.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors29.default.bold("ablo check")}.
289466
289980
  `
289467
289981
  );
289468
289982
  }
289469
289983
 
289470
289984
  // src/drizzlePull.ts
289471
289985
  init_cjs_shims();
289472
- var import_picocolors29 = __toESM(require_picocolors(), 1);
289473
- var import_errors23 = require("@abloatai/transaction/errors");
289986
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
289987
+ var import_errors24 = require("@abloatai/transaction/errors");
289474
289988
  var import_fs12 = require("fs");
289475
289989
  var import_path7 = require("path");
289476
289990
  init_theme();
@@ -289577,7 +290091,7 @@ function parseDrizzlePullArgs(argv) {
289577
290091
  force = true;
289578
290092
  break;
289579
290093
  default:
289580
- if (arg.startsWith("--")) throw new import_errors23.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
290094
+ if (arg.startsWith("--")) throw new import_errors24.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
289581
290095
  schema = arg;
289582
290096
  }
289583
290097
  }
@@ -289594,27 +290108,27 @@ async function drizzlePull(argv) {
289594
290108
  try {
289595
290109
  args = parseDrizzlePullArgs(argv);
289596
290110
  } catch (err) {
289597
- console.error(import_picocolors29.default.red(` ${err instanceof Error ? err.message : String(err)}`));
290111
+ console.error(import_picocolors30.default.red(` ${err instanceof Error ? err.message : String(err)}`));
289598
290112
  process.exit(1);
289599
290113
  }
289600
290114
  if (!args.schema) {
289601
290115
  console.error(
289602
- import_picocolors29.default.red(` No Drizzle schema given.`) + import_picocolors29.default.dim(` Pass the module: ${import_picocolors29.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
290116
+ import_picocolors30.default.red(` No Drizzle schema given.`) + import_picocolors30.default.dim(` Pass the module: ${import_picocolors30.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
289603
290117
  );
289604
290118
  process.exit(1);
289605
290119
  }
289606
290120
  if (!(0, import_fs12.existsSync)(args.schema)) {
289607
- console.error(import_picocolors29.default.red(` No file at ${import_picocolors29.default.bold(args.schema)}.`));
290121
+ console.error(import_picocolors30.default.red(` No file at ${import_picocolors30.default.bold(args.schema)}.`));
289608
290122
  process.exit(1);
289609
290123
  }
289610
290124
  if ((0, import_fs12.existsSync)(args.out) && !args.force) {
289611
290125
  console.error(
289612
- import_picocolors29.default.red(` ${args.out} already exists.`) + import_picocolors29.default.dim(` Re-run with ${import_picocolors29.default.bold("--force")} to overwrite.`)
290126
+ import_picocolors30.default.red(` ${args.out} already exists.`) + import_picocolors30.default.dim(` Re-run with ${import_picocolors30.default.bold("--force")} to overwrite.`)
289613
290127
  );
289614
290128
  process.exit(1);
289615
290129
  }
289616
290130
  console.log(`
289617
- ${brand("ablo")} ${import_picocolors29.default.dim("pull drizzle")} ${import_picocolors29.default.dim(args.schema)}
290131
+ ${brand("ablo")} ${import_picocolors30.default.dim("pull drizzle")} ${import_picocolors30.default.dim(args.schema)}
289618
290132
  `);
289619
290133
  let result;
289620
290134
  try {
@@ -289622,26 +290136,26 @@ async function drizzlePull(argv) {
289622
290136
  result = await buildSchemaSourceFromDrizzle({ mod, importPath: args.importPath });
289623
290137
  } catch (err) {
289624
290138
  const msg = err instanceof Error ? err.message : String(err);
289625
- const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors29.default.dim(` (install ${import_picocolors29.default.bold("drizzle-orm")} in this project)`) : "";
289626
- console.error(import_picocolors29.default.red(` Couldn't load the schema: ${msg}`) + hint);
290139
+ const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors30.default.dim(` (install ${import_picocolors30.default.bold("drizzle-orm")} in this project)`) : "";
290140
+ console.error(import_picocolors30.default.red(` Couldn't load the schema: ${msg}`) + hint);
289627
290141
  process.exit(1);
289628
290142
  }
289629
290143
  if (result.models.length === 0) {
289630
290144
  console.error(
289631
- import_picocolors29.default.yellow(` No adoptable tables found`) + import_picocolors29.default.dim(` (a table needs an ${import_picocolors29.default.bold("id")} + ${import_picocolors29.default.bold("organization_id")} column).`)
290145
+ import_picocolors30.default.yellow(` No adoptable tables found`) + import_picocolors30.default.dim(` (a table needs an ${import_picocolors30.default.bold("id")} + ${import_picocolors30.default.bold("organization_id")} column).`)
289632
290146
  );
289633
290147
  process.exit(1);
289634
290148
  }
289635
290149
  (0, import_fs12.writeFileSync)(args.out, result.source);
289636
- console.log(` ${import_picocolors29.default.green("\u2713")} wrote ${import_picocolors29.default.bold(args.out)} ${import_picocolors29.default.dim(`(${result.models.length} models)`)}`);
289637
- console.log(` ${import_picocolors29.default.dim(`models: ${result.models.join(", ")}`)}`);
290150
+ console.log(` ${import_picocolors30.default.green("\u2713")} wrote ${import_picocolors30.default.bold(args.out)} ${import_picocolors30.default.dim(`(${result.models.length} models)`)}`);
290151
+ console.log(` ${import_picocolors30.default.dim(`models: ${result.models.join(", ")}`)}`);
289638
290152
  if (result.skipped.length > 0) {
289639
- console.log(` ${import_picocolors29.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
289640
- for (const s of result.skipped) console.log(` ${import_picocolors29.default.dim(`- ${s.name}: ${s.reason}`)}`);
290153
+ console.log(` ${import_picocolors30.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
290154
+ for (const s of result.skipped) console.log(` ${import_picocolors30.default.dim(`- ${s.name}: ${s.reason}`)}`);
289641
290155
  }
289642
290156
  console.log(
289643
290157
  `
289644
- ${import_picocolors29.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors29.default.bold("ablo check")}.
290158
+ ${import_picocolors30.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors30.default.bold("ablo check")}.
289645
290159
  `
289646
290160
  );
289647
290161
  }
@@ -289654,8 +290168,8 @@ init_telemetry();
289654
290168
 
289655
290169
  // src/init/options.ts
289656
290170
  init_cjs_shims();
289657
- var import_node_fs4 = require("fs");
289658
- var import_node_path3 = require("path");
290171
+ var import_node_fs5 = require("fs");
290172
+ var import_node_path4 = require("path");
289659
290173
  var INIT_FRAMEWORKS = ["nextjs", "vite", "remix", "vanilla"];
289660
290174
  var INIT_AUTHS = [
289661
290175
  "apikey",
@@ -289694,7 +290208,7 @@ function parseInitArgs(args) {
289694
290208
  function detectOrm(override, root = process.cwd()) {
289695
290209
  if (override === "prisma" || override === "drizzle" || override === "none") return override;
289696
290210
  try {
289697
- const pkg = JSON.parse((0, import_node_fs4.readFileSync)((0, import_node_path3.resolve)(root, "package.json"), "utf8"));
290211
+ const pkg = JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path4.resolve)(root, "package.json"), "utf8"));
289698
290212
  const dependencies = { ...pkg.dependencies, ...pkg.devDependencies };
289699
290213
  if (dependencies["@prisma/client"] || dependencies.prisma) return "prisma";
289700
290214
  if (dependencies["drizzle-orm"]) return "drizzle";
@@ -289703,24 +290217,24 @@ function detectOrm(override, root = process.cwd()) {
289703
290217
  return "none";
289704
290218
  }
289705
290219
  function detectNextLayout(root = process.cwd()) {
289706
- const useSrc = (0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "src", "app")) || !(0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "app")) && (0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "src"));
289707
- return useSrc ? { appBase: (0, import_node_path3.join)("src", "app"), aliasBase: "src" } : { appBase: "app", aliasBase: "." };
290220
+ const useSrc = (0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "src", "app")) || !(0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "app")) && (0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "src"));
290221
+ return useSrc ? { appBase: (0, import_node_path4.join)("src", "app"), aliasBase: "src" } : { appBase: "app", aliasBase: "." };
289708
290222
  }
289709
290223
  function detectPackageManager(root = process.cwd()) {
289710
- if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "pnpm-lock.yaml"))) return "pnpm";
289711
- if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "yarn.lock"))) return "yarn";
289712
- if ((0, import_node_fs4.existsSync)((0, import_node_path3.resolve)(root, "bun.lockb"))) return "bun";
290224
+ if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "pnpm-lock.yaml"))) return "pnpm";
290225
+ if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "yarn.lock"))) return "yarn";
290226
+ if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "bun.lockb"))) return "bun";
289713
290227
  return "npm";
289714
290228
  }
289715
290229
 
289716
290230
  // src/init/run.ts
289717
290231
  init_cjs_shims();
289718
- var import_node_child_process3 = require("child_process");
289719
- var import_node_fs6 = require("fs");
289720
- var import_node_path5 = require("path");
290232
+ var import_node_child_process4 = require("child_process");
290233
+ var import_node_fs7 = require("fs");
290234
+ var import_node_path6 = require("path");
289721
290235
  init_dist2();
289722
- var import_picocolors30 = __toESM(require_picocolors(), 1);
289723
- var import_errors24 = require("@abloatai/transaction/errors");
290236
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
290237
+ var import_errors25 = require("@abloatai/transaction/errors");
289724
290238
  init_dbRole();
289725
290239
  init_config();
289726
290240
  init_projects();
@@ -290105,12 +290619,12 @@ async function main() {
290105
290619
  // Triage the urgent one to the top. We write based on the version we just
290106
290620
  // read (\`readAt\`), so if a human edits the same row at the same moment the
290107
290621
  // write is rejected instead of silently clobbering them.
290108
- const snap = ablo.snapshot({ records: urgent.id });
290622
+ const current = await ablo.records.read({ id: urgent.id });
290623
+ if (!current) throw new Error('urgent record was not found');
290109
290624
  await ablo.records.update({
290110
290625
  id: urgent.id,
290111
290626
  data: { priority: 10 },
290112
- readAt: snap.stamp,
290113
- onStale: 'reject',
290627
+ reads: [current],
290114
290628
  });
290115
290629
  console.log('prioritized:', urgent.title);
290116
290630
 
@@ -290180,9 +290694,9 @@ export function RecordList() {
290180
290694
 
290181
290695
  // src/init/writer.ts
290182
290696
  init_cjs_shims();
290183
- var import_node_fs5 = require("fs");
290184
- var import_node_path4 = require("path");
290185
- var import_node_crypto7 = require("crypto");
290697
+ var import_node_fs6 = require("fs");
290698
+ var import_node_path5 = require("path");
290699
+ var import_node_crypto8 = require("crypto");
290186
290700
  function projectInitWritePlan(plan) {
290187
290701
  return setupInitPlanProjectionSchema.parse({
290188
290702
  root: plan.root,
@@ -290196,18 +290710,18 @@ function projectInitWritePlan(plan) {
290196
290710
  });
290197
290711
  }
290198
290712
  function absolute(root, path) {
290199
- const target = (0, import_node_path4.resolve)(root, path);
290200
- const fromRoot = (0, import_node_path4.relative)(root, target);
290201
- if (fromRoot === "" || fromRoot === ".." || fromRoot.startsWith(`..${import_node_path4.sep}`) || (0, import_node_path4.isAbsolute)(fromRoot)) {
290713
+ const target = (0, import_node_path5.resolve)(root, path);
290714
+ const fromRoot = (0, import_node_path5.relative)(root, target);
290715
+ if (fromRoot === "" || fromRoot === ".." || fromRoot.startsWith(`..${import_node_path5.sep}`) || (0, import_node_path5.isAbsolute)(fromRoot)) {
290202
290716
  throw new Error(`Init target must stay inside the project root: ${path}`);
290203
290717
  }
290204
290718
  return target;
290205
290719
  }
290206
290720
  function sha2562(content) {
290207
- return (0, import_node_crypto7.createHash)("sha256").update(content).digest("hex");
290721
+ return (0, import_node_crypto8.createHash)("sha256").update(content).digest("hex");
290208
290722
  }
290209
290723
  function readIfPresent(path) {
290210
- return (0, import_node_fs5.existsSync)(path) ? (0, import_node_fs5.readFileSync)(path, "utf8") : void 0;
290724
+ return (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path, "utf8") : void 0;
290211
290725
  }
290212
290726
  function mergeEnvironmentTemplate(existing, template) {
290213
290727
  const assignments = template.split(/\r?\n/).map((line) => {
@@ -290231,7 +290745,7 @@ function mergeEnvironmentTemplate(existing, template) {
290231
290745
  };
290232
290746
  }
290233
290747
  function planInitWrites(input) {
290234
- const root = (0, import_node_path4.resolve)(input.root ?? process.cwd());
290748
+ const root = (0, import_node_path5.resolve)(input.root ?? process.cwd());
290235
290749
  const actions = [];
290236
290750
  const conflicts = [];
290237
290751
  for (const file of input.files) {
@@ -290276,18 +290790,18 @@ function planInitWrites(input) {
290276
290790
  return { root, actions, conflicts };
290277
290791
  }
290278
290792
  function writeAtomic(path, content, kind) {
290279
- (0, import_node_fs5.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
290280
- const temporary = (0, import_node_path4.join)((0, import_node_path4.dirname)(path), `.${(0, import_node_crypto7.randomUUID)()}.ablo-init.tmp`);
290281
- (0, import_node_fs5.writeFileSync)(temporary, content, { flag: "wx" });
290793
+ (0, import_node_fs6.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
290794
+ const temporary = (0, import_node_path5.join)((0, import_node_path5.dirname)(path), `.${(0, import_node_crypto8.randomUUID)()}.ablo-init.tmp`);
290795
+ (0, import_node_fs6.writeFileSync)(temporary, content, { flag: "wx" });
290282
290796
  try {
290283
290797
  if (kind === "create") {
290284
- (0, import_node_fs5.linkSync)(temporary, path);
290285
- (0, import_node_fs5.unlinkSync)(temporary);
290798
+ (0, import_node_fs6.linkSync)(temporary, path);
290799
+ (0, import_node_fs6.unlinkSync)(temporary);
290286
290800
  } else {
290287
- (0, import_node_fs5.renameSync)(temporary, path);
290801
+ (0, import_node_fs6.renameSync)(temporary, path);
290288
290802
  }
290289
290803
  } catch (error) {
290290
- if ((0, import_node_fs5.existsSync)(temporary)) (0, import_node_fs5.unlinkSync)(temporary);
290804
+ if ((0, import_node_fs6.existsSync)(temporary)) (0, import_node_fs6.unlinkSync)(temporary);
290291
290805
  throw error;
290292
290806
  }
290293
290807
  }
@@ -290318,23 +290832,23 @@ function bailIfCancelled(value) {
290318
290832
  process.exit(0);
290319
290833
  }
290320
290834
  }
290321
- async function chooseOption(name, flagValue, fallback, allowed, interactive, prompt) {
290322
- if (flagValue !== void 0) {
290323
- if (!allowed.includes(flagValue)) {
290324
- throw new import_errors24.AbloValidationError(
290325
- `Invalid --${name} "${flagValue}". Allowed: ${allowed.join(", ")}`,
290835
+ async function chooseOption(name, flagValue2, fallback, allowed, interactive, prompt) {
290836
+ if (flagValue2 !== void 0) {
290837
+ if (!allowed.includes(flagValue2)) {
290838
+ throw new import_errors25.AbloValidationError(
290839
+ `Invalid --${name} "${flagValue2}". Allowed: ${allowed.join(", ")}`,
290326
290840
  { code: "cli_invalid_arguments" }
290327
290841
  );
290328
290842
  }
290329
- return flagValue;
290843
+ return flagValue2;
290330
290844
  }
290331
290845
  if (!interactive) return fallback;
290332
290846
  const value = await prompt();
290333
290847
  bailIfCancelled(value);
290334
290848
  return value;
290335
290849
  }
290336
- async function chooseBool(flagValue, fallback, interactive, prompt) {
290337
- if (flagValue !== void 0) return flagValue;
290850
+ async function chooseBool(flagValue2, fallback, interactive, prompt) {
290851
+ if (flagValue2 !== void 0) return flagValue2;
290338
290852
  if (!interactive) return fallback;
290339
290853
  const value = await prompt();
290340
290854
  bailIfCancelled(value);
@@ -290345,7 +290859,7 @@ async function ensureInitProject(opts) {
290345
290859
  const slug = opts.project ?? projectSlugFromPackageName(
290346
290860
  (() => {
290347
290861
  try {
290348
- return JSON.parse((0, import_node_fs6.readFileSync)("package.json", "utf8")).name;
290862
+ return JSON.parse((0, import_node_fs7.readFileSync)("package.json", "utf8")).name;
290349
290863
  } catch {
290350
290864
  return void 0;
290351
290865
  }
@@ -290355,7 +290869,7 @@ async function ensureInitProject(opts) {
290355
290869
  const ensured = await ensureProject(slug);
290356
290870
  if (ensured) {
290357
290871
  console.log(
290358
- ` ${import_picocolors30.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors30.default.bold(ensured.slug)} ${import_picocolors30.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
290872
+ ` ${import_picocolors31.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors31.default.bold(ensured.slug)} ${import_picocolors31.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
290359
290873
  );
290360
290874
  }
290361
290875
  }
@@ -290367,16 +290881,16 @@ function renderWritePlan(actions) {
290367
290881
  }
290368
290882
  function renderAppliedWrites(actions) {
290369
290883
  return actions.map((action) => {
290370
- const status2 = action.kind === "create" ? import_picocolors30.default.green("created") : action.kind === "update" ? import_picocolors30.default.yellow("updated") : import_picocolors30.default.dim("unchanged");
290371
- return `${import_picocolors30.default.green("\u2713")} ${action.path}${action.note ?? ""} ${import_picocolors30.default.dim(`(${status2})`)}`;
290884
+ const status2 = action.kind === "create" ? import_picocolors31.default.green("created") : action.kind === "update" ? import_picocolors31.default.yellow("updated") : import_picocolors31.default.dim("unchanged");
290885
+ return `${import_picocolors31.default.green("\u2713")} ${action.path}${action.note ?? ""} ${import_picocolors31.default.dim(`(${status2})`)}`;
290372
290886
  }).join("\n");
290373
290887
  }
290374
290888
  async function runInit(args = []) {
290375
290889
  const opts = parseInitArgs(args);
290376
290890
  const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
290377
- Ie(`${brand("ablo")} ${import_picocolors30.default.dim("sync engine")}`);
290378
- if (!(0, import_node_fs6.existsSync)("package.json")) {
290379
- throw new import_errors24.AbloValidationError("No package.json found. Run this from your project root.", {
290891
+ Ie(`${brand("ablo")} ${import_picocolors31.default.dim("sync engine")}`);
290892
+ if (!(0, import_node_fs7.existsSync)("package.json")) {
290893
+ throw new import_errors25.AbloValidationError("No package.json found. Run this from your project root.", {
290380
290894
  code: "cli_invalid_arguments"
290381
290895
  });
290382
290896
  }
@@ -290445,14 +290959,14 @@ async function runInit(args = []) {
290445
290959
  );
290446
290960
  }
290447
290961
  const layout = framework === "nextjs" ? detectNextLayout() : { appBase: "app", aliasBase: "." };
290448
- const abloDir = (0, import_node_path5.join)(layout.aliasBase, "ablo");
290962
+ const abloDir = (0, import_node_path6.join)(layout.aliasBase, "ablo");
290449
290963
  const files = [];
290450
290964
  let schemaSource = generateSchema();
290451
290965
  let schemaNote = "";
290452
290966
  if (pullExisting) {
290453
290967
  const dbUrl = readProjectAdminDatabaseUrl();
290454
290968
  if (!dbUrl) {
290455
- schemaNote = import_picocolors30.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
290969
+ schemaNote = import_picocolors31.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
290456
290970
  } else {
290457
290971
  try {
290458
290972
  const pulled = await buildSchemaSourceFromDb({
@@ -290462,59 +290976,59 @@ async function runInit(args = []) {
290462
290976
  });
290463
290977
  if (pulled.models.length > 0) {
290464
290978
  schemaSource = pulled.source;
290465
- schemaNote = import_picocolors30.default.dim(` (pulled ${pulled.models.length} models)`);
290979
+ schemaNote = import_picocolors31.default.dim(` (pulled ${pulled.models.length} models)`);
290466
290980
  } else {
290467
- schemaNote = import_picocolors30.default.dim(" (no adoptable tables \u2014 wrote starter)");
290981
+ schemaNote = import_picocolors31.default.dim(" (no adoptable tables \u2014 wrote starter)");
290468
290982
  }
290469
290983
  } catch {
290470
- schemaNote = import_picocolors30.default.dim(" (pull failed \u2014 wrote starter)");
290984
+ schemaNote = import_picocolors31.default.dim(" (pull failed \u2014 wrote starter)");
290471
290985
  }
290472
290986
  }
290473
290987
  }
290474
- files.push({ path: (0, import_node_path5.join)(abloDir, "schema.ts"), content: schemaSource, note: schemaNote });
290988
+ files.push({ path: (0, import_node_path6.join)(abloDir, "schema.ts"), content: schemaSource, note: schemaNote });
290475
290989
  files.push({
290476
- path: (0, import_node_path5.join)(abloDir, "index.ts"),
290990
+ path: (0, import_node_path6.join)(abloDir, "index.ts"),
290477
290991
  content: generateSyncConfig(auth, { serverOnly: framework === "nextjs" })
290478
290992
  });
290479
- files.push({ path: (0, import_node_path5.join)(abloDir, "register.ts"), content: generateRegister() });
290993
+ files.push({ path: (0, import_node_path6.join)(abloDir, "register.ts"), content: generateRegister() });
290480
290994
  const orm = detectOrm(opts.orm);
290481
290995
  if (storage === "endpoint") {
290482
290996
  files.push({
290483
- path: (0, import_node_path5.join)(abloDir, "data-source.ts"),
290997
+ path: (0, import_node_path6.join)(abloDir, "data-source.ts"),
290484
290998
  content: generateDataSource(orm),
290485
290999
  note: orm === "drizzle" ? " (Drizzle)" : " (Prisma)"
290486
291000
  });
290487
291001
  }
290488
291002
  const envFile = framework === "nextjs" ? ".env.local" : ".env";
290489
291003
  const envBody = generateEnv(storage);
290490
- if (agent) files.push({ path: (0, import_node_path5.join)(abloDir, "agent.ts"), content: generateAgent() });
291004
+ if (agent) files.push({ path: (0, import_node_path6.join)(abloDir, "agent.ts"), content: generateAgent() });
290491
291005
  if (framework === "nextjs") {
290492
291006
  if (storage === "endpoint") {
290493
- const webhookDir = (0, import_node_path5.join)(layout.appBase, "api", "ablo", "webhooks");
291007
+ const webhookDir = (0, import_node_path6.join)(layout.appBase, "api", "ablo", "webhooks");
290494
291008
  files.push({
290495
- path: (0, import_node_path5.join)(webhookDir, "route.ts"),
291009
+ path: (0, import_node_path6.join)(webhookDir, "route.ts"),
290496
291010
  content: generateWebhookRoute(orm),
290497
291011
  note: orm === "prisma" ? " (Prisma mirror)" : " (add your database write)"
290498
291012
  });
290499
291013
  }
290500
291014
  files.push({
290501
- path: (0, import_node_path5.join)(layout.appBase, "providers.tsx"),
291015
+ path: (0, import_node_path6.join)(layout.appBase, "providers.tsx"),
290502
291016
  content: generateProviders(),
290503
- note: ` (wrap ${(0, import_node_path5.join)(layout.appBase, "layout.tsx")} in <Providers>)`
291017
+ note: ` (wrap ${(0, import_node_path6.join)(layout.appBase, "layout.tsx")} in <Providers>)`
290504
291018
  });
290505
291019
  files.push({
290506
- path: (0, import_node_path5.join)(layout.appBase, "api", "ablo-session", "route.ts"),
291020
+ path: (0, import_node_path6.join)(layout.appBase, "api", "ablo-session", "route.ts"),
290507
291021
  content: generateSessionRoute(),
290508
291022
  note: " (wire your auth)"
290509
291023
  });
290510
291024
  }
290511
291025
  if (framework !== "vanilla") {
290512
- files.push({ path: (0, import_node_path5.join)(abloDir, "RecordList.tsx"), content: generateComponent() });
291026
+ files.push({ path: (0, import_node_path6.join)(abloDir, "RecordList.tsx"), content: generateComponent() });
290513
291027
  }
290514
291028
  const writePlan = planInitWrites({ files, environment: { path: envFile, template: envBody } });
290515
291029
  if (writePlan.conflicts.length > 0) {
290516
291030
  const occupied = writePlan.conflicts.map(({ path }) => ` - ${path}`).join("\n");
290517
- throw new import_errors24.AbloValidationError(
291031
+ throw new import_errors25.AbloValidationError(
290518
291032
  `Ablo init did not change any files because these application-owned paths already contain different contents:
290519
291033
  ${occupied}
290520
291034
 
@@ -290524,7 +291038,7 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290524
291038
  }
290525
291039
  if (opts.plan) {
290526
291040
  Me(renderWritePlan(writePlan.actions), "Plan (no files changed)");
290527
- Se(`Dry run complete. Re-run without ${import_picocolors30.default.bold("--plan")} to apply it.`);
291041
+ Se(`Dry run complete. Re-run without ${import_picocolors31.default.bold("--plan")} to apply it.`);
290528
291042
  return setupInitResultSchema.parse({
290529
291043
  status: "planned",
290530
291044
  plan: projectInitWritePlan(writePlan)
@@ -290541,32 +291055,32 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290541
291055
  const progress = Y2();
290542
291056
  progress.start("Installing @abloatai/ablo");
290543
291057
  try {
290544
- (0, import_node_child_process3.execFileSync)(packageManager2, ["add", "@abloatai/ablo"], { stdio: "ignore" });
291058
+ (0, import_node_child_process4.execFileSync)(packageManager2, ["add", "@abloatai/ablo"], { stdio: "ignore" });
290545
291059
  progress.stop("Installed @abloatai/ablo");
290546
291060
  } catch {
290547
291061
  progress.stop(
290548
- `${import_picocolors30.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors30.default.bold(`${packageManager2} install @abloatai/ablo`)}`
291062
+ `${import_picocolors31.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors31.default.bold(`${packageManager2} install @abloatai/ablo`)}`
290549
291063
  );
290550
291064
  }
290551
291065
  }
290552
291066
  const steps = [
290553
- `Run ${import_picocolors30.default.bold("npx ablo login")} to authorize branch management`,
290554
- `Set ${import_picocolors30.default.bold("DATABASE_URL")} in ${import_picocolors30.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
290555
- `Run ${import_picocolors30.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
291067
+ `Run ${import_picocolors31.default.bold("npx ablo login")} to authorize branch management`,
291068
+ `Set ${import_picocolors31.default.bold("DATABASE_URL")} in ${import_picocolors31.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
291069
+ `Run ${import_picocolors31.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
290556
291070
  ...storage === "replication" ? [
290557
- `Connect your database \u2014 ${import_picocolors30.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
290558
- `Verify it \u2014 ${import_picocolors30.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
290559
- `Register it \u2014 ${import_picocolors30.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
291071
+ `Connect your database \u2014 ${import_picocolors31.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
291072
+ `Verify it \u2014 ${import_picocolors31.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
291073
+ `Register it \u2014 ${import_picocolors31.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
290560
291074
  ] : [
290561
- `Provision your DB: ${import_picocolors30.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors30.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors30.default.bold("/api/ablo/source")}`
291075
+ `Provision your DB: ${import_picocolors31.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors31.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors31.default.bold("/api/ablo/source")}`
290562
291076
  ],
290563
291077
  ...framework === "nextjs" ? [
290564
- `Wrap ${import_picocolors30.default.bold((0, import_node_path5.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors30.default.bold("<Providers>")} (${(0, import_node_path5.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors30.default.bold((0, import_node_path5.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
291078
+ `Wrap ${import_picocolors31.default.bold((0, import_node_path6.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors31.default.bold("<Providers>")} (${(0, import_node_path6.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors31.default.bold((0, import_node_path6.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
290565
291079
  ] : [],
290566
- `Run ${import_picocolors30.default.bold(`${packageManager2} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
291080
+ `Run ${import_picocolors31.default.bold(`${packageManager2} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
290567
291081
  ...agent ? [
290568
- `Run ${import_picocolors30.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same records`,
290569
- `Run ${import_picocolors30.default.bold("npx ablo logs")} to watch human + agent commits stream by`
291082
+ `Run ${import_picocolors31.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same records`,
291083
+ `Run ${import_picocolors31.default.bold("npx ablo logs")} to watch human + agent commits stream by`
290570
291084
  ] : []
290571
291085
  ];
290572
291086
  Me(steps.map((step, index) => `${index + 1}. ${step}`).join("\n"), "Next steps");
@@ -290574,26 +291088,26 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
290574
291088
  if (existingKey) {
290575
291089
  await ensureInitProject(opts);
290576
291090
  Se(
290577
- `Already authorized ${import_picocolors30.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors30.default.bold("npx ablo dev")} next. ${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`
291091
+ `Already authorized ${import_picocolors31.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors31.default.bold("npx ablo dev")} next. ${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`
290578
291092
  );
290579
291093
  return initResult;
290580
291094
  }
290581
291095
  if (interactive && opts.login) {
290582
291096
  const loginNow = await ye({ message: "Log in now? (opens your browser)", initialValue: true });
290583
291097
  if (!pD(loginNow) && loginNow) {
290584
- Se(`${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`);
291098
+ Se(`${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`);
290585
291099
  await login();
290586
291100
  await ensureInitProject(opts);
290587
291101
  return initResult;
290588
291102
  }
290589
291103
  }
290590
- Se(`Run ${import_picocolors30.default.bold("npx ablo login")} when ready. ${import_picocolors30.default.dim("Docs:")} https://abloatai.com/docs`);
291104
+ Se(`Run ${import_picocolors31.default.bold("npx ablo login")} when ready. ${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`);
290591
291105
  return initResult;
290592
291106
  }
290593
291107
 
290594
291108
  // src/index.ts
290595
291109
  var LOGO = `
290596
- ${brand("ablo")} ${import_picocolors31.default.dim("sync engine")}
291110
+ ${brand("ablo")} ${import_picocolors32.default.dim("sync engine")}
290597
291111
  `;
290598
291112
  var HANDLERS = {
290599
291113
  setup: (argv) => runSetup(argv),
@@ -290609,6 +291123,7 @@ var HANDLERS = {
290609
291123
  whoami: (argv) => whoami([...argv]),
290610
291124
  doctor: (argv) => doctor([...argv]),
290611
291125
  logs: (argv) => logs([...argv]),
291126
+ claims: (argv) => claims([...argv]),
290612
291127
  webhooks: (argv) => webhooks([...argv]),
290613
291128
  check: (argv) => check([...argv]),
290614
291129
  docs: (argv) => docs([...argv]),
@@ -290626,7 +291141,7 @@ async function runDev(argv) {
290626
291141
  const devArgs = [...argv];
290627
291142
  const oneShot = devArgs.includes("--no-watch");
290628
291143
  console.log(
290629
- import_picocolors31.default.dim(
291144
+ import_picocolors32.default.dim(
290630
291145
  oneShot ? " `ablo dev --no-watch` prepares this Git branch and pushes once." : " `ablo dev` prepares this Git branch and watches the schema."
290631
291146
  )
290632
291147
  );
@@ -290644,7 +291159,7 @@ async function runPush2(argv) {
290644
291159
  }
290645
291160
  function runRenamedSchema(argv) {
290646
291161
  const forwarded = argv.slice(1).join(" ");
290647
- console.error(` ${import_picocolors31.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
291162
+ console.error(` ${import_picocolors32.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
290648
291163
  console.error(` Run \`ablo push${forwarded ? " " + forwarded : ""}\` instead.`);
290649
291164
  process.exitCode = 1;
290650
291165
  }
@@ -290654,7 +291169,7 @@ async function main() {
290654
291169
  const argv = process.argv.slice(3);
290655
291170
  if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
290656
291171
  const suggestion = suggestCommand(raw);
290657
- throw new import_errors25.AbloValidationError(
291172
+ throw new import_errors26.AbloValidationError(
290658
291173
  `\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
290659
291174
  { code: "cli_invalid_arguments" }
290660
291175
  );
@@ -290695,7 +291210,7 @@ function printCoreHelp() {
290695
291210
  const width = Math.max(...rows.map((r2) => r2.run.length)) + 4;
290696
291211
  console.log(LOGO);
290697
291212
  for (const group of CORE_GROUPS) {
290698
- console.log(` ${import_picocolors31.default.bold(group)}`);
291213
+ console.log(` ${import_picocolors32.default.bold(group)}`);
290699
291214
  const printed = group === "More" ? [...coreRows(group), ...extra] : coreRows(group);
290700
291215
  for (const row of printed) console.log(` npx ablo ${row.run.padEnd(width)}${row.does}`);
290701
291216
  console.log();
@@ -290704,7 +291219,7 @@ function printCoreHelp() {
290704
291219
  }
290705
291220
  function printSchemaReminder() {
290706
291221
  console.log(
290707
- import_picocolors31.default.dim(` Edit ${import_picocolors31.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors31.default.yellow("server_execute_unknown_model") + import_picocolors31.default.dim(".")
291222
+ import_picocolors32.default.dim(` Edit ${import_picocolors32.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors32.default.yellow("server_execute_unknown_model") + import_picocolors32.default.dim(".")
290708
291223
  );
290709
291224
  console.log();
290710
291225
  }
@@ -290714,7 +291229,7 @@ function printFullHelp() {
290714
291229
  ) + 2;
290715
291230
  console.log(LOGO);
290716
291231
  for (const group of FULL_GROUPS) {
290717
- console.log(` ${import_picocolors31.default.bold(group)}`);
291232
+ console.log(` ${import_picocolors32.default.bold(group)}`);
290718
291233
  for (const row of fullRows(group)) {
290719
291234
  console.log(row.does === void 0 ? ` ${" ".repeat(9)}${row.run}` : ` npx ablo ${row.run.padEnd(width)}${row.does}`);
290720
291235
  }