@abloatai/cli 0.48.0 → 0.50.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 +374 -197
  2. package/package.json +5 -3
package/dist/cli.cjs CHANGED
@@ -2318,7 +2318,7 @@ function Subscribe(postgres2, options) {
2318
2318
  return;
2319
2319
  stream = null;
2320
2320
  state.pid = state.secret = void 0;
2321
- connected(await init2(sql, slot, options.publications));
2321
+ connected(await init4(sql, slot, options.publications));
2322
2322
  subscribers.forEach((event) => event.forEach(({ onsubscribe }) => onsubscribe()));
2323
2323
  },
2324
2324
  no_subscribe: true
@@ -2337,7 +2337,7 @@ function Subscribe(postgres2, options) {
2337
2337
  async function subscribe(event, fn, onsubscribe = noop2, onerror = noop2) {
2338
2338
  event = parseEvent(event);
2339
2339
  if (!connection2)
2340
- connection2 = init2(sql, slot, options.publications);
2340
+ connection2 = init4(sql, slot, options.publications);
2341
2341
  const subscriber = { fn, onsubscribe };
2342
2342
  const fns = subscribers.has(event) ? subscribers.get(event).add(subscriber) : subscribers.set(event, /* @__PURE__ */ new Set([subscriber])).get(event);
2343
2343
  const unsubscribe = () => {
@@ -2356,7 +2356,7 @@ function Subscribe(postgres2, options) {
2356
2356
  state.pid = x2.state.pid;
2357
2357
  state.secret = x2.state.secret;
2358
2358
  }
2359
- async function init2(sql2, slot2, publications) {
2359
+ async function init4(sql2, slot2, publications) {
2360
2360
  if (!publications)
2361
2361
  throw new Error("Missing publication names");
2362
2362
  const xs = await sql2.unsafe(
@@ -3455,14 +3455,14 @@ function requireKey() {
3455
3455
  }
3456
3456
  return apiKey;
3457
3457
  }
3458
- async function request(path, apiKey, init2 = {}, baseUrl2) {
3458
+ async function request(path, apiKey, init4 = {}, baseUrl2) {
3459
3459
  const res = await fetch(`${baseUrl2 ?? apiUrl()}${path}`, {
3460
- method: init2.method ?? "GET",
3460
+ method: init4.method ?? "GET",
3461
3461
  headers: {
3462
3462
  "content-type": "application/json",
3463
3463
  authorization: `Bearer ${apiKey}`
3464
3464
  },
3465
- ...init2.body !== void 0 ? { body: JSON.stringify(init2.body) } : {}
3465
+ ...init4.body !== void 0 ? { body: JSON.stringify(init4.body) } : {}
3466
3466
  });
3467
3467
  let body = {};
3468
3468
  try {
@@ -3825,6 +3825,153 @@ var init_terminalWidth = __esm({
3825
3825
  }
3826
3826
  });
3827
3827
 
3828
+ // src/observeCliError.ts
3829
+ function installCliExitObservationBoundary() {
3830
+ if (exitBoundaryInstalled) return;
3831
+ exitBoundaryInstalled = true;
3832
+ process.exit = ((code) => {
3833
+ const numericCode = code == null ? 0 : Number(code);
3834
+ if (numericCode === 0) return nativeProcessExit(code);
3835
+ throw new CliFailureExit(Number.isFinite(numericCode) ? numericCode : 1);
3836
+ });
3837
+ }
3838
+ function restoreCliExitObservationBoundary() {
3839
+ if (!exitBoundaryInstalled) return;
3840
+ process.exit = nativeProcessExit;
3841
+ exitBoundaryInstalled = false;
3842
+ }
3843
+ function init2() {
3844
+ if (!dsn) return false;
3845
+ if (!initialized) {
3846
+ Sentry.init({
3847
+ dsn,
3848
+ environment: process.env.ABLO_STAGE ?? "local",
3849
+ release,
3850
+ sendDefaultPii: false,
3851
+ enableLogs: true,
3852
+ beforeSend(event) {
3853
+ return (0, import_errorObservation.sanitizeObservationValue)(event);
3854
+ },
3855
+ beforeBreadcrumb(breadcrumb) {
3856
+ return (0, import_errorObservation.sanitizeObservationValue)(breadcrumb);
3857
+ }
3858
+ });
3859
+ initialized = true;
3860
+ }
3861
+ return true;
3862
+ }
3863
+ function commandOperation() {
3864
+ const command = process.argv[2];
3865
+ const subcommand = process.argv[3];
3866
+ const safe = (value) => value && /^[a-z][a-z0-9-]*$/i.test(value) ? value : void 0;
3867
+ return ["ablo", safe(command), safe(subcommand)].filter(Boolean).join(" ");
3868
+ }
3869
+ function detailString(details, ...keys) {
3870
+ for (const key of keys) {
3871
+ const value = details?.[key];
3872
+ if (typeof value === "string" && value.length > 0) return value;
3873
+ }
3874
+ return void 0;
3875
+ }
3876
+ function observeCliError(err) {
3877
+ const normalized = (0, import_errors5.toAbloError)(err);
3878
+ const eventId = normalized.eventId ?? (dsn ? (0, import_node_crypto.randomUUID)().replaceAll("-", "") : void 0);
3879
+ if (!eventId || !init2()) return normalized.eventId;
3880
+ try {
3881
+ const spec = normalized.code ? (0, import_errorCodes.errorCodeSpec)(normalized.code) : void 0;
3882
+ const policy = spec?.observability ?? {
3883
+ severity: "error",
3884
+ sentry: "issue",
3885
+ pagingEligible: false,
3886
+ expectedVolume: "low",
3887
+ owner: "product"
3888
+ };
3889
+ const details = normalized.details;
3890
+ const organizationId = detailString(details, "organizationId", "organization_id");
3891
+ const projectId = detailString(details, "projectId", "project_id");
3892
+ const branchId = detailString(details, "branchId", "branch_id");
3893
+ const dataSourceId = detailString(details, "dataSourceId", "data_source_id");
3894
+ const model = detailString(details, "model", "modelName", "model_name");
3895
+ const candidate = (0, import_errorObservation.sanitizeObservationValue)({
3896
+ eventId,
3897
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
3898
+ service: "ablo-cli",
3899
+ stage: process.env.ABLO_STAGE ?? "local",
3900
+ ...release ? { release } : {},
3901
+ severity: normalized.eventId ? "warning" : policy.severity,
3902
+ channel: "cli",
3903
+ scope: "command",
3904
+ operation: commandOperation(),
3905
+ errorCode: normalized.code ?? "internal_error",
3906
+ errorType: normalized.type,
3907
+ category: spec?.category ?? "client",
3908
+ retryable: spec?.retryable ?? false,
3909
+ handled: normalized.eventId !== void 0 || policy.sentry === "log",
3910
+ publicMessage: normalized.message,
3911
+ internalMessage: normalized.message,
3912
+ ...normalized.stack ? { stack: normalized.stack } : {},
3913
+ ...normalized.requestId ? { requestId: normalized.requestId } : {},
3914
+ ...organizationId ? { organizationId } : {},
3915
+ ...projectId ? { projectId } : {},
3916
+ ...branchId ? { branchId } : {},
3917
+ ...dataSourceId ? { dataSourceId } : {},
3918
+ ...model ? { model } : {},
3919
+ ...err instanceof CliFailureExit ? { diagnosticContext: { exitCode: err.exitCode } } : {}
3920
+ });
3921
+ const observation = import_errorObservation.errorObservationSchema.parse(candidate);
3922
+ if (normalized.eventId || policy.sentry === "log") {
3923
+ Sentry.logger.warn(observation.publicMessage, { ...observation });
3924
+ } else {
3925
+ Sentry.captureException(err, {
3926
+ event_id: observation.eventId,
3927
+ captureContext: {
3928
+ level: observation.severity,
3929
+ fingerprint: [observation.service, observation.operation, observation.errorCode],
3930
+ tags: {
3931
+ service: observation.service,
3932
+ channel: observation.channel,
3933
+ scope: observation.scope,
3934
+ error_code: observation.errorCode
3935
+ },
3936
+ contexts: { ablo: { ...observation } }
3937
+ }
3938
+ });
3939
+ }
3940
+ return eventId;
3941
+ } catch {
3942
+ return normalized.eventId;
3943
+ }
3944
+ }
3945
+ async function flushCliErrors(timeoutMs = 2e3) {
3946
+ if (!initialized) return true;
3947
+ return Sentry.flush(timeoutMs);
3948
+ }
3949
+ var import_node_crypto, Sentry, import_errorCodes, import_errorObservation, import_errors5, dsn, release, initialized, nativeProcessExit, exitBoundaryInstalled, CliFailureExit;
3950
+ var init_observeCliError = __esm({
3951
+ "src/observeCliError.ts"() {
3952
+ "use strict";
3953
+ init_cjs_shims();
3954
+ import_node_crypto = require("crypto");
3955
+ Sentry = __toESM(require("@sentry/node"), 1);
3956
+ import_errorCodes = require("@abloatai/transaction/errorCodes");
3957
+ import_errorObservation = require("@abloatai/transaction/errorObservation");
3958
+ import_errors5 = require("@abloatai/transaction/errors");
3959
+ dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
3960
+ release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.50.0";
3961
+ initialized = false;
3962
+ nativeProcessExit = process.exit.bind(process);
3963
+ exitBoundaryInstalled = false;
3964
+ CliFailureExit = class extends Error {
3965
+ exitCode;
3966
+ constructor(exitCode) {
3967
+ super(`CLI command exited with status ${exitCode}`);
3968
+ this.name = "CliFailureExit";
3969
+ this.exitCode = exitCode;
3970
+ }
3971
+ };
3972
+ }
3973
+ });
3974
+
3828
3975
  // src/renderError.ts
3829
3976
  function titleForType(type) {
3830
3977
  const core = type.replace(/^Ablo/, "").replace(/Error$/, "");
@@ -3853,6 +4000,17 @@ function wrapParagraph(text, indent) {
3853
4000
  function renderKnownDetails(details, line) {
3854
4001
  if (!details) return;
3855
4002
  const { retryAfterSeconds, missingIds, requiredCapability, unexecutable, errors, target } = details;
4003
+ if (details.topology === "localhost") {
4004
+ const commands = isStringArray(details.recommended_commands) ? details.recommended_commands : ["ablo migrate", "ablo dev --local"];
4005
+ line(` ${import_picocolors4.default.dim("setup")} ${commands.join(" \u2192 ")}`);
4006
+ if (typeof details.mode === "string") line(` ${import_picocolors4.default.dim("mode")} ${details.mode}`);
4007
+ if (typeof details.limitation === "string") {
4008
+ line(` ${import_picocolors4.default.dim("note")} ${details.limitation}`);
4009
+ }
4010
+ if (isStringArray(details.alternatives)) {
4011
+ line(` ${import_picocolors4.default.dim("other")} ${details.alternatives.join(" \xB7 ")}`);
4012
+ }
4013
+ }
3856
4014
  if (typeof target === "string") line(` ${import_picocolors4.default.dim("tried")} ${target}`);
3857
4015
  if (typeof retryAfterSeconds === "number") line(` ${import_picocolors4.default.dim("retry")} after ${retryAfterSeconds}s`);
3858
4016
  if (isStringArray(missingIds) && missingIds.length > 0) {
@@ -3876,17 +4034,18 @@ function renderKnownDetails(details, line) {
3876
4034
  }
3877
4035
  }
3878
4036
  function renderCliError(err, opts = {}) {
4037
+ const observedEventId = observeCliError(err);
3879
4038
  const line = opts.write ?? ((l2) => {
3880
4039
  console.error(l2);
3881
4040
  });
3882
4041
  const verbose = opts.verbose ?? (process.argv.includes("--verbose") || process.env.ABLO_VERBOSE === "1");
3883
4042
  const json = opts.json ?? (process.argv.includes("--json") || process.env.ABLO_JSON === "1");
3884
4043
  if (json) {
3885
- line(JSON.stringify((0, import_errors5.toAbloError)(err).toJSON()));
4044
+ line(JSON.stringify((0, import_errors6.toAbloError)(err).toJSON()));
3886
4045
  process.exitCode = 1;
3887
4046
  return;
3888
4047
  }
3889
- if (err instanceof import_errors5.AbloError) {
4048
+ if (err instanceof import_errors6.AbloError) {
3890
4049
  const codeTag = err.code ? ` ${import_picocolors4.default.dim(`[${err.code}]`)}` : "";
3891
4050
  line("");
3892
4051
  line(` ${brand("ablo")} ${import_picocolors4.default.red("\u2717")} ${import_picocolors4.default.bold(titleForType(err.type))}${codeTag}`);
@@ -3899,10 +4058,13 @@ function renderCliError(err, opts = {}) {
3899
4058
  const field = (s) => fields.push(s);
3900
4059
  if (err.param) field(` ${import_picocolors4.default.dim("field")} ${err.param}`);
3901
4060
  renderKnownDetails(err.details, field);
3902
- const hint = err.code ? RECOVERY_HINT[(0, import_errors5.classifyRecovery)(err.code)] : void 0;
4061
+ const hint = err.code ? RECOVERY_HINT[(0, import_errors6.classifyRecovery)(err.code)] : void 0;
3903
4062
  if (hint) field(` ${import_picocolors4.default.dim(hint)}`);
3904
4063
  if (err.docUrl) field(` ${import_picocolors4.default.dim("docs")} ${err.docUrl}`);
3905
4064
  if (err.requestId) field(` ${import_picocolors4.default.dim("ref")} ${err.requestId}`);
4065
+ if (err.eventId ?? observedEventId) {
4066
+ field(` ${import_picocolors4.default.dim("event")} ${err.eventId ?? observedEventId}`);
4067
+ }
3906
4068
  if (fields.length > 0) {
3907
4069
  line("");
3908
4070
  for (const f of fields) line(f);
@@ -3925,15 +4087,16 @@ function renderCliError(err, opts = {}) {
3925
4087
  line("");
3926
4088
  process.exitCode = 1;
3927
4089
  }
3928
- var import_picocolors4, import_errors5, RECOVERY_HINT;
4090
+ var import_picocolors4, import_errors6, RECOVERY_HINT;
3929
4091
  var init_renderError = __esm({
3930
4092
  "src/renderError.ts"() {
3931
4093
  "use strict";
3932
4094
  init_cjs_shims();
3933
4095
  import_picocolors4 = __toESM(require_picocolors(), 1);
3934
- import_errors5 = require("@abloatai/transaction/errors");
4096
+ import_errors6 = require("@abloatai/transaction/errors");
3935
4097
  init_terminalWidth();
3936
4098
  init_theme();
4099
+ init_observeCliError();
3937
4100
  RECOVERY_HINT = {
3938
4101
  transient: "This looks transient \u2014 retry in a moment.",
3939
4102
  permission: "Your key isn't allowed to do this \u2014 check its scopes or role.",
@@ -4030,7 +4193,7 @@ function parsePushArgs(argv) {
4030
4193
  const spec = argv[++i] ?? "";
4031
4194
  const [from, to] = spec.split(":");
4032
4195
  if (!from || !to) {
4033
- throw new import_errors6.AbloValidationError(`--rename expects "old:new", got "${spec}"`, { code: "cli_invalid_arguments" });
4196
+ throw new import_errors7.AbloValidationError(`--rename expects "old:new", got "${spec}"`, { code: "cli_invalid_arguments" });
4034
4197
  }
4035
4198
  renames.push({ from, to });
4036
4199
  break;
@@ -4044,13 +4207,13 @@ function parsePushArgs(argv) {
4044
4207
  const modelName = dot === -1 ? "" : path.slice(0, dot);
4045
4208
  const fieldName = dot === -1 ? "" : path.slice(dot + 1);
4046
4209
  if (!modelName || !fieldName || eq === -1) {
4047
- throw new import_errors6.AbloValidationError(`--backfill expects "model.field=value", got "${spec}"`, { code: "cli_invalid_arguments" });
4210
+ throw new import_errors7.AbloValidationError(`--backfill expects "model.field=value", got "${spec}"`, { code: "cli_invalid_arguments" });
4048
4211
  }
4049
4212
  backfills.push({ model: modelName, field: fieldName, value: coerceBackfill(rawValue) });
4050
4213
  break;
4051
4214
  }
4052
4215
  default:
4053
- throw new import_errors6.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
4216
+ throw new import_errors7.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
4054
4217
  }
4055
4218
  }
4056
4219
  url = url.replace(/\/+$/, "");
@@ -4078,7 +4241,7 @@ function publicationGap(value) {
4078
4241
  async function loadSchema(schemaPath, exportName) {
4079
4242
  const abs = (0, import_path3.resolve)(process.cwd(), schemaPath);
4080
4243
  if (!(0, import_fs4.existsSync)(abs)) {
4081
- throw new import_errors6.AbloValidationError(
4244
+ throw new import_errors7.AbloValidationError(
4082
4245
  `schema not found at ${import_picocolors5.default.bold(schemaPath)}. Run ${import_picocolors5.default.bold("npx ablo init")} or pass ${import_picocolors5.default.bold("--schema <path>")}.`,
4083
4246
  { code: "cli_invalid_arguments" }
4084
4247
  );
@@ -4089,7 +4252,7 @@ async function loadSchema(schemaPath, exportName) {
4089
4252
  const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
4090
4253
  const schema = mod[exportName] ?? nested?.[exportName];
4091
4254
  if (!schema || typeof schema !== "object" || !("models" in schema)) {
4092
- throw new import_errors6.AbloValidationError(
4255
+ throw new import_errors7.AbloValidationError(
4093
4256
  `${import_picocolors5.default.bold(schemaPath)} has no \`${exportName}\` export that looks like a Schema. Did you \`export const ${exportName} = defineSchema({ ... })\`?`,
4094
4257
  { code: "cli_invalid_arguments" }
4095
4258
  );
@@ -4279,7 +4442,7 @@ async function push(argv) {
4279
4442
  try {
4280
4443
  process.loadEnvFile(args.envFile);
4281
4444
  } catch (error) {
4282
- throw new import_errors6.AbloValidationError(
4445
+ throw new import_errors7.AbloValidationError(
4283
4446
  `could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
4284
4447
  { code: "cli_invalid_arguments" }
4285
4448
  );
@@ -4454,17 +4617,17 @@ async function push(argv) {
4454
4617
  );
4455
4618
  }
4456
4619
  } else {
4457
- renderCliError((0, import_errors6.translateHttpError)(status2, Object.keys(body).length > 0 ? body : bodyText));
4620
+ renderCliError((0, import_errors7.translateHttpError)(status2, Object.keys(body).length > 0 ? body : bodyText));
4458
4621
  }
4459
4622
  process.exit(1);
4460
4623
  }
4461
- var import_picocolors5, import_errors6, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, import_schema2, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT, PUSH_USAGE;
4624
+ 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;
4462
4625
  var init_push = __esm({
4463
4626
  "src/push.ts"() {
4464
4627
  "use strict";
4465
4628
  init_cjs_shims();
4466
4629
  import_picocolors5 = __toESM(require_picocolors(), 1);
4467
- import_errors6 = require("@abloatai/transaction/errors");
4630
+ import_errors7 = require("@abloatai/transaction/errors");
4468
4631
  import_credentialPolicy = require("@abloatai/transaction/auth/credentialPolicy");
4469
4632
  import_fs4 = require("fs");
4470
4633
  import_path3 = require("path");
@@ -4910,25 +5073,16 @@ Logical replication already exposes every published row; this lets the ordinary
4910
5073
  JOIN pg_class c ON c.relname = pt.tablename
4911
5074
  JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = pt.schemaname
4912
5075
  WHERE pt.pubname = $1 AND pt.schemaname = $2
4913
- AND (
4914
- c.relreplident = 'n'
4915
- OR (
4916
- c.relreplident = 'd'
4917
- AND NOT EXISTS (
4918
- SELECT 1 FROM pg_index i
4919
- WHERE i.indrelid = c.oid AND i.indisprimary
4920
- )
4921
- )
4922
- )`,
5076
+ AND c.relreplident <> 'f'`,
4923
5077
  [publication, schema]
4924
5078
  );
4925
5079
  const relevant = coordinated ? badRows.filter((row) => coordinated.has(row.table_name)) : badRows;
4926
5080
  items.push(
4927
- relevant.length === 0 ? { ok: true, label: `all published tables have a usable REPLICA IDENTITY` } : {
5081
+ relevant.length === 0 ? { ok: true, label: `all published tables use REPLICA IDENTITY FULL` } : {
4928
5082
  ok: false,
4929
5083
  label: `${relevant.length} published table${relevant.length === 1 ? "" : "s"} cannot replicate UPDATE/DELETE`,
4930
5084
  fix: relevant.map(
4931
- (r2) => `${r2.table_name}: add a PRIMARY KEY, or ALTER TABLE ${quoteIdent(schema)}.${quoteIdent(r2.table_name)} REPLICA IDENTITY FULL;`
5085
+ (r2) => `${r2.table_name}: ALTER TABLE ${quoteIdent(schema)}.${quoteIdent(r2.table_name)} REPLICA IDENTITY FULL;`
4932
5086
  ).join("\n")
4933
5087
  }
4934
5088
  );
@@ -4983,6 +5137,18 @@ async function registerDirectDataSource(opts) {
4983
5137
  ` This deployment can\u2019t accept connection strings \u2014 use a self-hosted/hosted engine, or the signed endpoint fallback.`
4984
5138
  )
4985
5139
  );
5140
+ } else if (err.code === "database_loopback_requires_connector") {
5141
+ console.error(`
5142
+ ${import_picocolors7.default.cyan("Recommended for this localhost-first project")}
5143
+ 1. ${import_picocolors7.default.bold("npx ablo migrate")} ${import_picocolors7.default.dim("(once: models + idempotency + outbox)")}
5144
+ 2. ${import_picocolors7.default.bold("npx ablo dev --local")} ${import_picocolors7.default.dim("(keep running beside the app)")}
5145
+
5146
+ ${import_picocolors7.default.dim("This keeps Postgres private and supports reads, coordinated writes, claims,")}
5147
+ ${import_picocolors7.default.dim("subscriptions, and confirmations through the signed Data Source connector.")}
5148
+ ${import_picocolors7.default.yellow("Note:")} ${import_picocolors7.default.dim("raw SQL or unrelated ORM writes are not automatically observed without WAL.")}
5149
+
5150
+ ${import_picocolors7.default.dim("If every arbitrary database write must be observed, use a secure database-capable")}
5151
+ ${import_picocolors7.default.dim("tunnel, hosted direct Postgres, PrivateLink, peering, or VPN\u2014not a transaction pooler.")}`);
4986
5152
  } else if (err.code === "database_not_replication_ready" || err.code === "data_source_blocked") {
4987
5153
  for (const f of failures) {
4988
5154
  const { label, fix } = describeRemoteFailure(f);
@@ -5013,9 +5179,9 @@ async function registerDirectDataSource(opts) {
5013
5179
  }
5014
5180
  console.error(
5015
5181
  import_picocolors7.default.dim(
5016
- ` Ablo's servers must be able to reach this database \u2014 a localhost or private-network
5017
- Postgres can't use the direct path. Establish an allowlist, PrivateLink, peering, or VPN.
5018
- Only when no inbound route is possible, register the signed ${import_picocolors7.default.bold("dataSource()")} endpoint fallback.`
5182
+ ` Ablo's servers must be able to reach this database for the direct WAL path.
5183
+ For localhost development, run ${import_picocolors7.default.bold("ablo dev --local")}. For private deployments,
5184
+ establish an allowlist, PrivateLink, peering, or VPN.`
5019
5185
  )
5020
5186
  );
5021
5187
  }
@@ -5077,9 +5243,9 @@ async function deregisterDataSource(opts) {
5077
5243
  });
5078
5244
  return { removed: true, response };
5079
5245
  } catch (err) {
5080
- if (err instanceof import_errors8.AbloError && err.code === "entity_not_found") return { removed: false };
5081
- if (err instanceof import_errors8.AbloError && err.code === "forbidden") {
5082
- throw new import_errors8.AbloPermissionError(
5246
+ if (err instanceof import_errors9.AbloError && err.code === "entity_not_found") return { removed: false };
5247
+ if (err instanceof import_errors9.AbloError && err.code === "forbidden") {
5248
+ throw new import_errors9.AbloPermissionError(
5083
5249
  `${err.message}. Disconnecting needs a branch-bound secret key (sk_\u2026).`,
5084
5250
  {
5085
5251
  code: "forbidden",
@@ -5135,7 +5301,7 @@ async function disconnect(argv) {
5135
5301
  console.log(DISCONNECT_USAGE);
5136
5302
  return;
5137
5303
  } else {
5138
- throw new import_errors8.AbloValidationError(
5304
+ throw new import_errors9.AbloValidationError(
5139
5305
  `unknown flag: ${arg} \u2014 see \`ablo connect deregister --help\``,
5140
5306
  { code: "cli_invalid_arguments" }
5141
5307
  );
@@ -5150,7 +5316,7 @@ async function disconnect(argv) {
5150
5316
  try {
5151
5317
  process.loadEnvFile(envFile);
5152
5318
  } catch (error) {
5153
- throw new import_errors8.AbloValidationError(
5319
+ throw new import_errors9.AbloValidationError(
5154
5320
  `could not load --env-file ${envFile}: ${error instanceof Error ? error.message : String(error)}`,
5155
5321
  { code: "cli_invalid_arguments" }
5156
5322
  );
@@ -5158,7 +5324,7 @@ async function disconnect(argv) {
5158
5324
  }
5159
5325
  const selected = keyEnv ? readProjectEnvVariable(keyEnv) : null;
5160
5326
  if (keyEnv && !selected) {
5161
- throw new import_errors8.AbloAuthenticationError(
5327
+ throw new import_errors9.AbloAuthenticationError(
5162
5328
  `No value named ${keyEnv} was found in the process environment, .env.local, or .env.`,
5163
5329
  { code: "cli_api_key_missing" }
5164
5330
  );
@@ -5170,7 +5336,7 @@ async function disconnect(argv) {
5170
5336
  const apiKey = resolved.key;
5171
5337
  const keySource = resolved.source ?? "stored";
5172
5338
  if (!apiKey) {
5173
- throw new import_errors8.AbloAuthenticationError(
5339
+ throw new import_errors9.AbloAuthenticationError(
5174
5340
  "Disconnecting needs a branch-bound sk_ key. Set ABLO_API_KEY, pass `--env-file .env.local`, or select a named recovery key with `--key-env <NAME>`.",
5175
5341
  { code: "cli_api_key_missing" }
5176
5342
  );
@@ -5184,7 +5350,7 @@ async function disconnect(argv) {
5184
5350
  `);
5185
5351
  if (!skipConfirm) {
5186
5352
  if (!process.stdout.isTTY) {
5187
- throw new import_errors8.AbloValidationError(
5353
+ throw new import_errors9.AbloValidationError(
5188
5354
  "This session has no terminal to confirm in. Re-run with --yes to disconnect non-interactively.",
5189
5355
  { code: "cli_invalid_arguments" }
5190
5356
  );
@@ -5207,14 +5373,14 @@ async function disconnect(argv) {
5207
5373
  }
5208
5374
  renderDisconnected(outcome.response, project, branchLabel);
5209
5375
  }
5210
- var import_picocolors8, import_errors8, import_wire4, DISCONNECT_USAGE;
5376
+ var import_picocolors8, import_errors9, import_wire4, DISCONNECT_USAGE;
5211
5377
  var init_disconnect = __esm({
5212
5378
  "src/disconnect.ts"() {
5213
5379
  "use strict";
5214
5380
  init_cjs_shims();
5215
5381
  import_picocolors8 = __toESM(require_picocolors(), 1);
5216
5382
  init_dist2();
5217
- import_errors8 = require("@abloatai/transaction/errors");
5383
+ import_errors9 = require("@abloatai/transaction/errors");
5218
5384
  import_wire4 = require("@abloatai/transaction/wire");
5219
5385
  init_config();
5220
5386
  init_dbRole();
@@ -5467,7 +5633,7 @@ function blockers(input) {
5467
5633
  }
5468
5634
  if (input.dataSource.kind === "none") {
5469
5635
  found.push({
5470
- problem: "this branch is not connected to a database, so writes are held",
5636
+ problem: "no database is connected to this branch, so writes are held",
5471
5637
  fix: "connect one with `ablo connect apply`"
5472
5638
  });
5473
5639
  }
@@ -5822,7 +5988,7 @@ async function runConnectApply(args) {
5822
5988
  const verb = rotating ? "connect rotate" : "connect apply";
5823
5989
  let adminUrl = args.url ?? readProjectAdminDatabaseUrl();
5824
5990
  if (!adminUrl) {
5825
- throw new import_errors9.AbloValidationError(
5991
+ throw new import_errors10.AbloValidationError(
5826
5992
  "No admin connection string. Pass --url <admin-conn> (or set DATABASE_URL) and re-run.",
5827
5993
  { code: "cli_database_url_missing" }
5828
5994
  );
@@ -5839,7 +6005,7 @@ async function runConnectApply(args) {
5839
6005
  const loggedIn = resolveManagementKey() !== void 0;
5840
6006
  const ambient = ambientEnvKeyNote();
5841
6007
  const retry = `npx ablo connect ${rotating ? "rotate" : "apply"} --env-file .env.local --yes`;
5842
- throw new import_errors9.AbloAuthenticationError(
6008
+ throw new import_errors10.AbloAuthenticationError(
5843
6009
  loggedIn ? `You are logged in, but connect needs a branch-bound runtime key.
5844
6010
 
5845
6011
  Logging in stores an mk_ management credential; it can manage branches but cannot read, write, or register a database. Set ABLO_API_KEY to the sk_ key for the exact branch this database should join. The server confirms whether that branch is the production root or a development child; the CLI does not infer it from the key spelling.${ambient ? `
@@ -5904,22 +6070,6 @@ ${ambient}` : ""}`,
5904
6070
  ` + import_picocolors11.default.dim(
5905
6071
  ` Replication cannot run over a pooler, so if that is what this is, point ${import_picocolors11.default.bold("--url")}
5906
6072
  at the database itself. Carrying on, since a database can use this port too.
5907
- `
5908
- )
5909
- );
5910
- }
5911
- const coordinatedTables = await schemaDeclaredTables() ?? [];
5912
- const tables = args.tables.length > 0 ? args.tables : coordinatedTables;
5913
- if (tables.length === 0) {
5914
- throw new import_errors9.AbloValidationError(
5915
- `No mapped tables were found for schema ${args.schema}. Push the Ablo schema first, or pass --tables a,b,c. A project binding must enumerate its own schema-qualified tables; it cannot publish every table in a shared database.`,
5916
- { code: "cli_invalid_arguments" }
5917
- );
5918
- }
5919
- if (args.tables.length === 0) {
5920
- console.log(
5921
- import_picocolors11.default.dim(
5922
- ` publishing the ${tables.length} table${tables.length === 1 ? "" : "s"} declared by your Ablo schema in ${import_picocolors11.default.bold(args.schema)} (${import_picocolors11.default.bold("--tables")} to override)
5923
6073
  `
5924
6074
  )
5925
6075
  );
@@ -5936,7 +6086,7 @@ ${ambient}` : ""}`,
5936
6086
  }
5937
6087
  const confirmed = connectTarget?.confirmed;
5938
6088
  if (!confirmed?.branchId) {
5939
- throw new import_errors9.AbloConnectionError(
6089
+ throw new import_errors10.AbloConnectionError(
5940
6090
  "Ablo could not confirm the branch this key targets, so it cannot derive an isolated database footprint safely. Check the API URL/key and re-run.",
5941
6091
  { code: "cli_database_unreachable" }
5942
6092
  );
@@ -5967,6 +6117,22 @@ ${ambient}` : ""}`,
5967
6117
  );
5968
6118
  process.exit(1);
5969
6119
  }
6120
+ const coordinatedTables = await schemaDeclaredTables() ?? [];
6121
+ const tables = args.tables.length > 0 ? args.tables : coordinatedTables;
6122
+ if (tables.length === 0) {
6123
+ throw new import_errors10.AbloValidationError(
6124
+ `No mapped tables were found for schema ${args.schema}. Push the Ablo schema first, or pass --tables a,b,c. A project binding must enumerate its own schema-qualified tables; it cannot publish every table in a shared database.`,
6125
+ { code: "cli_invalid_arguments" }
6126
+ );
6127
+ }
6128
+ if (args.tables.length === 0) {
6129
+ console.log(
6130
+ import_picocolors11.default.dim(
6131
+ ` publishing the ${tables.length} table${tables.length === 1 ? "" : "s"} declared by your Ablo schema in ${import_picocolors11.default.bold(args.schema)} (${import_picocolors11.default.bold("--tables")} to override)
6132
+ `
6133
+ )
6134
+ );
6135
+ }
5970
6136
  let rotatePlane = null;
5971
6137
  if (rotating) {
5972
6138
  const state = await fetchDataSourceState(apiBaseUrl(), apiKey).catch(
@@ -6002,7 +6168,7 @@ ${ambient}` : ""}`,
6002
6168
  } catch (err) {
6003
6169
  await admin.end({ timeout: 2 }).catch(() => void 0);
6004
6170
  const pg = err ?? {};
6005
- throw new import_errors9.AbloConnectionError(`Couldn't connect: ${pg.message ?? String(err)}`, {
6171
+ throw new import_errors10.AbloConnectionError(`Couldn't connect: ${pg.message ?? String(err)}`, {
6006
6172
  code: "cli_database_unreachable",
6007
6173
  details: { target },
6008
6174
  cause: err
@@ -6259,7 +6425,7 @@ ${ambient}` : ""}`,
6259
6425
  }
6260
6426
  process.exit(outcome.exitCode);
6261
6427
  }
6262
- var import_picocolors11, import_errors9, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
6428
+ var import_picocolors11, import_errors10, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
6263
6429
  var init_connectApply = __esm({
6264
6430
  "src/connectApply.ts"() {
6265
6431
  "use strict";
@@ -6267,7 +6433,7 @@ var init_connectApply = __esm({
6267
6433
  import_picocolors11 = __toESM(require_picocolors(), 1);
6268
6434
  init_src();
6269
6435
  init_dist2();
6270
- import_errors9 = require("@abloatai/transaction/errors");
6436
+ import_errors10 = require("@abloatai/transaction/errors");
6271
6437
  import_footprint2 = require("@abloatai/transaction/footprint");
6272
6438
  init_connectSetup();
6273
6439
  init_connectOwnership();
@@ -6331,7 +6497,7 @@ function parseConnectArgs(argv) {
6331
6497
  locate = true;
6332
6498
  break;
6333
6499
  default:
6334
- throw new import_errors10.AbloValidationError(
6500
+ throw new import_errors11.AbloValidationError(
6335
6501
  `unknown connect subcommand: ${lead} (expected register, deregister, check, apply, rotate, resnapshot, scan, locate)`,
6336
6502
  { code: "cli_invalid_arguments" }
6337
6503
  );
@@ -6374,7 +6540,7 @@ function parseConnectArgs(argv) {
6374
6540
  case "--route": {
6375
6541
  const value = argv[++i] ?? "";
6376
6542
  if (!DIRECT_DATA_SOURCE_ROUTES.includes(value)) {
6377
- throw new import_errors10.AbloValidationError(
6543
+ throw new import_errors11.AbloValidationError(
6378
6544
  `invalid direct route: ${value || "(missing)"} (expected ${DIRECT_DATA_SOURCE_ROUTES.join(", ")})`,
6379
6545
  { code: "cli_invalid_arguments" }
6380
6546
  );
@@ -6383,11 +6549,11 @@ function parseConnectArgs(argv) {
6383
6549
  break;
6384
6550
  }
6385
6551
  default:
6386
- throw new import_errors10.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
6552
+ throw new import_errors11.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
6387
6553
  }
6388
6554
  }
6389
6555
  if (role === writeRole) {
6390
- throw new import_errors10.AbloValidationError("replication and write roles must be different", {
6556
+ throw new import_errors11.AbloValidationError("replication and write roles must be different", {
6391
6557
  code: "cli_invalid_arguments"
6392
6558
  });
6393
6559
  }
@@ -6694,7 +6860,7 @@ async function probeAndReport(dbUrl, kind, opts) {
6694
6860
  const dial = dialFailureReason(err);
6695
6861
  if (dial) return { kind: "no-dial", reason: dial };
6696
6862
  const pg = err ?? {};
6697
- throw new import_errors10.AbloConnectionError(`Couldn't read the database: ${pg.message ?? String(err)}`, {
6863
+ throw new import_errors11.AbloConnectionError(`Couldn't read the database: ${pg.message ?? String(err)}`, {
6698
6864
  code: "cli_database_unreachable",
6699
6865
  cause: err
6700
6866
  });
@@ -6712,7 +6878,7 @@ async function runCheck() {
6712
6878
  const apiKey = resolveRuntimeApiKey().key;
6713
6879
  if (!apiKey) {
6714
6880
  const ambient = ambientEnvKeyNote();
6715
- throw new import_errors10.AbloAuthenticationError(
6881
+ throw new import_errors11.AbloAuthenticationError(
6716
6882
  `No branch-bound runtime key found. Set ABLO_API_KEY to the sk_ key for the branch to check, or pass \`--env-file .env.local\` explicitly.${ambient ? `
6717
6883
 
6718
6884
  ${ambient}` : ""}`,
@@ -6749,8 +6915,9 @@ ${ambient}` : ""}`,
6749
6915
  );
6750
6916
  console.error(
6751
6917
  import_picocolors12.default.dim(
6752
- ` Direct needs a route Ablo's servers can dial \u2014 public allowlist, PrivateLink, peering,
6753
- or VPN. Only when no inbound route can exist, use the signed ${import_picocolors12.default.bold("dataSource()")} endpoint fallback.
6918
+ ` For localhost-first development, run ${import_picocolors12.default.bold("ablo dev --local")} and keep it beside the app.
6919
+ The direct WAL path needs a route Ablo's servers can dial \u2014 public allowlist,
6920
+ PrivateLink, peering, VPN, or a database-capable secure tunnel.
6754
6921
  `
6755
6922
  )
6756
6923
  );
@@ -6804,7 +6971,7 @@ async function runRegister(args) {
6804
6971
  const apiKey = resolveMutationApiKey();
6805
6972
  if (!apiKey) {
6806
6973
  const ambient = ambientEnvKeyNote();
6807
- throw new import_errors10.AbloAuthenticationError(
6974
+ throw new import_errors11.AbloAuthenticationError(
6808
6975
  `No branch-bound runtime key found. Set ABLO_API_KEY to the sk_ key for the branch to register, or pass \`--env-file .env.local\` explicitly.${ambient ? `
6809
6976
 
6810
6977
  ${ambient}` : ""}`,
@@ -6819,7 +6986,7 @@ ${ambient}` : ""}`,
6819
6986
  const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
6820
6987
  const confirmed = target.confirmed;
6821
6988
  if (!confirmed?.branchId) {
6822
- throw new import_errors10.AbloValidationError(
6989
+ throw new import_errors11.AbloValidationError(
6823
6990
  "This key is not bound to a branch, so Ablo cannot validate isolated database objects safely.",
6824
6991
  { code: "cli_database_unreachable" }
6825
6992
  );
@@ -6901,7 +7068,7 @@ async function runScan(args) {
6901
7068
  } catch (err) {
6902
7069
  const pg = err ?? {};
6903
7070
  await sql.end({ timeout: 2 });
6904
- throw new import_errors10.AbloConnectionError(`Couldn't audit the database: ${pg.message ?? String(err)}`, {
7071
+ throw new import_errors11.AbloConnectionError(`Couldn't audit the database: ${pg.message ?? String(err)}`, {
6905
7072
  code: "cli_database_unreachable",
6906
7073
  cause: err
6907
7074
  });
@@ -6953,7 +7120,7 @@ async function runLocate(args) {
6953
7120
  );
6954
7121
  const url = args.url ?? readProjectAdminDatabaseUrl();
6955
7122
  if (!url) {
6956
- throw new import_errors10.AbloValidationError(
7123
+ throw new import_errors11.AbloValidationError(
6957
7124
  "Locating needs a connection string to identify the database. Pass --url <conn> (or set DATABASE_URL) and re-run.",
6958
7125
  { code: "cli_database_url_missing" }
6959
7126
  );
@@ -6961,7 +7128,7 @@ async function runLocate(args) {
6961
7128
  const apiKey = resolveRuntimeApiKey().key;
6962
7129
  if (!apiKey) {
6963
7130
  const ambient = ambientEnvKeyNote();
6964
- throw new import_errors10.AbloAuthenticationError(
7131
+ throw new import_errors11.AbloAuthenticationError(
6965
7132
  `No branch-bound runtime key found. Set ABLO_API_KEY to a key that can inspect this project, or pass \`--env-file .env.local\` explicitly.${ambient ? `
6966
7133
 
6967
7134
  ${ambient}` : ""}`,
@@ -7012,7 +7179,7 @@ ${ambient}` : ""}`,
7012
7179
  async function runResnapshot() {
7013
7180
  const apiKey = resolveMutationApiKey();
7014
7181
  if (!apiKey) {
7015
- throw new import_errors10.AbloAuthenticationError(
7182
+ throw new import_errors11.AbloAuthenticationError(
7016
7183
  "No branch-bound secret key found. Set ABLO_API_KEY to the sk_ key for the branch to resnapshot.",
7017
7184
  { code: "cli_api_key_missing" }
7018
7185
  );
@@ -7057,7 +7224,7 @@ async function connect(argv) {
7057
7224
  try {
7058
7225
  process.loadEnvFile(args.envFile);
7059
7226
  } catch (error) {
7060
- throw new import_errors10.AbloValidationError(
7227
+ throw new import_errors11.AbloValidationError(
7061
7228
  `could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
7062
7229
  { code: "cli_invalid_arguments" }
7063
7230
  );
@@ -7097,7 +7264,7 @@ async function connect(argv) {
7097
7264
  }
7098
7265
  const apiKey = resolveRuntimeApiKey().key;
7099
7266
  if (!apiKey) {
7100
- throw new import_errors10.AbloAuthenticationError(
7267
+ throw new import_errors11.AbloAuthenticationError(
7101
7268
  "Ablo needs the branch key to derive isolated database object names. Set ABLO_API_KEY for this branch, then re-run `ablo connect --manual`.",
7102
7269
  { code: "cli_api_key_missing" }
7103
7270
  );
@@ -7105,7 +7272,7 @@ async function connect(argv) {
7105
7272
  const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
7106
7273
  const confirmed = target.confirmed;
7107
7274
  if (!confirmed?.branchId) {
7108
- throw new import_errors10.AbloValidationError(
7275
+ throw new import_errors11.AbloValidationError(
7109
7276
  "This key is not bound to a branch, so Ablo cannot derive isolated database object names safely.",
7110
7277
  { code: "cli_database_unreachable" }
7111
7278
  );
@@ -7119,12 +7286,12 @@ async function connect(argv) {
7119
7286
  })
7120
7287
  );
7121
7288
  }
7122
- var import_errors10, import_picocolors12, import_footprint3, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
7289
+ var import_errors11, import_picocolors12, import_footprint3, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
7123
7290
  var init_connect = __esm({
7124
7291
  "src/connect.ts"() {
7125
7292
  "use strict";
7126
7293
  init_cjs_shims();
7127
- import_errors10 = require("@abloatai/transaction/errors");
7294
+ import_errors11 = require("@abloatai/transaction/errors");
7128
7295
  import_picocolors12 = __toESM(require_picocolors(), 1);
7129
7296
  init_src();
7130
7297
  import_footprint3 = require("@abloatai/transaction/footprint");
@@ -12852,11 +13019,11 @@ var require_typescript = __commonJS({
12852
13019
  function compareTextSpans(a, b4) {
12853
13020
  return compareValues(a == null ? void 0 : a.start, b4 == null ? void 0 : b4.start) || compareValues(a == null ? void 0 : a.length, b4 == null ? void 0 : b4.length);
12854
13021
  }
12855
- function maxBy(arr, init2, mapper) {
13022
+ function maxBy(arr, init4, mapper) {
12856
13023
  for (let i = 0; i < arr.length; i++) {
12857
- init2 = Math.max(init2, mapper(arr[i]));
13024
+ init4 = Math.max(init4, mapper(arr[i]));
12858
13025
  }
12859
- return init2;
13026
+ return init4;
12860
13027
  }
12861
13028
  function min(items, compare) {
12862
13029
  return reduceLeft(items, (x2, y3) => compare(x2, y3) === -1 ? x2 : y3);
@@ -17355,8 +17522,8 @@ ${lanes.join("\n")}
17355
17522
  function sysLog(s) {
17356
17523
  return curSysLog(s);
17357
17524
  }
17358
- function setSysLog(logger) {
17359
- curSysLog = logger;
17525
+ function setSysLog(logger2) {
17526
+ curSysLog = logger2;
17360
17527
  }
17361
17528
  function createDirectoryWatcherSupportingRecursive({
17362
17529
  watchDirectory,
@@ -28455,8 +28622,8 @@ ${lanes.join("\n")}
28455
28622
  return node.initializer;
28456
28623
  }
28457
28624
  function getDeclaredExpandoInitializer(node) {
28458
- const init2 = getEffectiveInitializer(node);
28459
- return init2 && getExpandoInitializer(init2, isPrototypeAccess(node.name));
28625
+ const init4 = getEffectiveInitializer(node);
28626
+ return init4 && getExpandoInitializer(init4, isPrototypeAccess(node.name));
28460
28627
  }
28461
28628
  function hasExpandoValueProperty(node, isPrototypeAssignment) {
28462
28629
  return forEach(node.properties, (p2) => isPropertyAssignment(p2) && isIdentifier2(p2.name) && p2.name.escapedText === "value" && p2.initializer && getExpandoInitializer(p2.initializer, isPrototypeAssignment));
@@ -62043,11 +62210,11 @@ ${lanes.join("\n")}
62043
62210
  if (node && isCallExpression(node)) {
62044
62211
  return !!getAssignedExpandoInitializer(node);
62045
62212
  }
62046
- let init2 = !node ? void 0 : isVariableDeclaration(node) ? node.initializer : isBinaryExpression(node) ? node.right : isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right : void 0;
62047
- init2 = init2 && getRightMostAssignedExpression(init2);
62048
- if (init2) {
62213
+ let init4 = !node ? void 0 : isVariableDeclaration(node) ? node.initializer : isBinaryExpression(node) ? node.right : isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right : void 0;
62214
+ init4 = init4 && getRightMostAssignedExpression(init4);
62215
+ if (init4) {
62049
62216
  const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node) ? node.name : isBinaryExpression(node) ? node.left : node);
62050
- return !!getExpandoInitializer(isBinaryExpression(init2) && (init2.operatorToken.kind === 57 || init2.operatorToken.kind === 61) ? init2.right : init2, isPrototypeAssignment);
62217
+ return !!getExpandoInitializer(isBinaryExpression(init4) && (init4.operatorToken.kind === 57 || init4.operatorToken.kind === 61) ? init4.right : init4, isPrototypeAssignment);
62051
62218
  }
62052
62219
  return false;
62053
62220
  }
@@ -62366,15 +62533,15 @@ ${lanes.join("\n")}
62366
62533
  } else if (isIdentifier2(node)) {
62367
62534
  const symbol = lookupSymbolForName(sourceFile, node.escapedText);
62368
62535
  if (!!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) {
62369
- const init2 = symbol.valueDeclaration.initializer;
62370
- q2.enqueue(init2);
62536
+ const init4 = symbol.valueDeclaration.initializer;
62537
+ q2.enqueue(init4);
62371
62538
  if (isAssignmentExpression(
62372
- init2,
62539
+ init4,
62373
62540
  /*excludeCompoundAssignment*/
62374
62541
  true
62375
62542
  )) {
62376
- q2.enqueue(init2.left);
62377
- q2.enqueue(init2.right);
62543
+ q2.enqueue(init4.left);
62544
+ q2.enqueue(init4.right);
62378
62545
  }
62379
62546
  }
62380
62547
  }
@@ -66962,9 +67129,9 @@ ${lanes.join("\n")}
66962
67129
  )) {
66963
67130
  return void 0;
66964
67131
  }
66965
- const init2 = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
66966
- if (init2) {
66967
- const initSymbol = getSymbolOfNode(init2);
67132
+ const init4 = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
67133
+ if (init4) {
67134
+ const initSymbol = getSymbolOfNode(init4);
66968
67135
  if (initSymbol) {
66969
67136
  return mergeJSSymbols(initSymbol, symbol);
66970
67137
  }
@@ -73744,9 +73911,9 @@ ${lanes.join("\n")}
73744
73911
  }
73745
73912
  return widened;
73746
73913
  }
73747
- function getJSContainerObjectType(decl, symbol, init2) {
73914
+ function getJSContainerObjectType(decl, symbol, init4) {
73748
73915
  var _a, _b;
73749
- if (!isInJSFile(decl) || !init2 || !isObjectLiteralExpression(init2) || init2.properties.length) {
73916
+ if (!isInJSFile(decl) || !init4 || !isObjectLiteralExpression(init4) || init4.properties.length) {
73750
73917
  return void 0;
73751
73918
  }
73752
73919
  const exports22 = createSymbolTable();
@@ -88720,8 +88887,8 @@ ${lanes.join("\n")}
88720
88887
  return unreachableNeverType;
88721
88888
  }
88722
88889
  if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConstLike2(node))) {
88723
- const init2 = getDeclaredExpandoInitializer(node);
88724
- if (init2 && (init2.kind === 218 || init2.kind === 219)) {
88890
+ const init4 = getDeclaredExpandoInitializer(node);
88891
+ if (init4 && (init4.kind === 218 || init4.kind === 219)) {
88725
88892
  return getTypeAtFlowNode(flow.antecedent);
88726
88893
  }
88727
88894
  }
@@ -96342,8 +96509,8 @@ ${lanes.join("\n")}
96342
96509
  true
96343
96510
  );
96344
96511
  const prototype = (_a = assignmentSymbol == null ? void 0 : assignmentSymbol.exports) == null ? void 0 : _a.get("prototype");
96345
- const init2 = (prototype == null ? void 0 : prototype.valueDeclaration) && getAssignedJSPrototype(prototype.valueDeclaration);
96346
- return init2 ? getSymbolOfDeclaration(init2) : void 0;
96512
+ const init4 = (prototype == null ? void 0 : prototype.valueDeclaration) && getAssignedJSPrototype(prototype.valueDeclaration);
96513
+ return init4 ? getSymbolOfDeclaration(init4) : void 0;
96347
96514
  }
96348
96515
  function getSymbolOfExpando(node, allowDeclaration) {
96349
96516
  if (!node.parent) {
@@ -99359,8 +99526,8 @@ ${lanes.join("\n")}
99359
99526
  case 3:
99360
99527
  case 4:
99361
99528
  const symbol = getSymbolOfNode(left);
99362
- const init2 = getAssignedExpandoInitializer(right);
99363
- return !!init2 && isObjectLiteralExpression(init2) && !!((_a = symbol == null ? void 0 : symbol.exports) == null ? void 0 : _a.size);
99529
+ const init4 = getAssignedExpandoInitializer(right);
99530
+ return !!init4 && isObjectLiteralExpression(init4) && !!((_a = symbol == null ? void 0 : symbol.exports) == null ? void 0 : _a.size);
99364
99531
  default:
99365
99532
  return false;
99366
99533
  }
@@ -163359,13 +163526,13 @@ ${lanes.join("\n")}
163359
163526
  }
163360
163527
  } else {
163361
163528
  if (isVariableStatement(node) && node.parent === sourceFile && node.declarationList.flags & 2 && node.declarationList.declarations.length === 1) {
163362
- const init2 = node.declarationList.declarations[0].initializer;
163363
- if (init2 && isRequireCall(
163364
- init2,
163529
+ const init4 = node.declarationList.declarations[0].initializer;
163530
+ if (init4 && isRequireCall(
163531
+ init4,
163365
163532
  /*requireStringLiteralLikeArgument*/
163366
163533
  true
163367
163534
  )) {
163368
- diags.push(createDiagnosticForNode(init2, Diagnostics.require_call_may_be_converted_to_an_import));
163535
+ diags.push(createDiagnosticForNode(init4, Diagnostics.require_call_may_be_converted_to_an_import));
163369
163536
  }
163370
163537
  }
163371
163538
  const jsdocTypedefNodes = ts_codefix_exports.getJSDocTypedefNodes(node);
@@ -176256,7 +176423,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
176256
176423
  factory.createIdentifier(name)
176257
176424
  );
176258
176425
  }
176259
- function makeConst(modifiers, name, init2) {
176426
+ function makeConst(modifiers, name, init4) {
176260
176427
  return factory.createVariableStatement(
176261
176428
  modifiers,
176262
176429
  factory.createVariableDeclarationList(
@@ -176266,7 +176433,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
176266
176433
  void 0,
176267
176434
  /*type*/
176268
176435
  void 0,
176269
- init2
176436
+ init4
176270
176437
  )],
176271
176438
  2
176272
176439
  /* Const */
@@ -195240,9 +195407,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
195240
195407
  return isFunctionLike(be.right) ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner };
195241
195408
  }
195242
195409
  case 172:
195243
- const init2 = commentOwner.initializer;
195244
- if (init2 && (isFunctionExpression(init2) || isArrowFunction(init2))) {
195245
- return { commentOwner, parameters: init2.parameters, hasReturn: hasReturn(init2, options) };
195410
+ const init4 = commentOwner.initializer;
195411
+ if (init4 && (isFunctionExpression(init4) || isArrowFunction(init4))) {
195412
+ return { commentOwner, parameters: init4.parameters, hasReturn: hasReturn(init4, options) };
195246
195413
  }
195247
195414
  }
195248
195415
  }
@@ -206735,13 +206902,13 @@ ${options.prefix}` : "\n" : options.prefix
206735
206902
  return [];
206736
206903
  }
206737
206904
  var ThrottledOperations = class _ThrottledOperations {
206738
- constructor(host, logger) {
206905
+ constructor(host, logger2) {
206739
206906
  this.host = host;
206740
206907
  this.pendingTimeouts = /* @__PURE__ */ new Map();
206741
- this.logger = logger.hasLevel(
206908
+ this.logger = logger2.hasLevel(
206742
206909
  3
206743
206910
  /* verbose */
206744
- ) ? logger : void 0;
206911
+ ) ? logger2 : void 0;
206745
206912
  }
206746
206913
  /**
206747
206914
  * Wait `number` milliseconds and then invoke `cb`. If, while waiting, schedule
@@ -206774,10 +206941,10 @@ ${options.prefix}` : "\n" : options.prefix
206774
206941
  }
206775
206942
  };
206776
206943
  var GcTimer = class _GcTimer {
206777
- constructor(host, delay, logger) {
206944
+ constructor(host, delay, logger2) {
206778
206945
  this.host = host;
206779
206946
  this.delay = delay;
206780
- this.logger = logger;
206947
+ this.logger = logger2;
206781
206948
  }
206782
206949
  scheduleCollect() {
206783
206950
  if (!this.host.gc || this.timerId !== void 0) {
@@ -214138,14 +214305,14 @@ Dynamic files must always be opened with service's current directory or service
214138
214305
  return edits.every((edit) => textSpanEnd(edit.span) < pos);
214139
214306
  }
214140
214307
  var CommandNames = CommandTypes;
214141
- function formatMessage2(msg, logger, byteLength, newLine) {
214142
- const verboseLogging = logger.hasLevel(
214308
+ function formatMessage2(msg, logger2, byteLength, newLine) {
214309
+ const verboseLogging = logger2.hasLevel(
214143
214310
  3
214144
214311
  /* verbose */
214145
214312
  );
214146
214313
  const json = JSON.stringify(msg);
214147
214314
  if (verboseLogging) {
214148
- logger.info(`${msg.type}:${stringifyIndented(msg)}`);
214315
+ logger2.info(`${msg.type}:${stringifyIndented(msg)}`);
214149
214316
  }
214150
214317
  const len = byteLength(json, "utf8");
214151
214318
  return `Content-Length: ${1 + len}\r
@@ -214300,7 +214467,7 @@ ${json}${newLine}`;
214300
214467
  const info = infos && firstOrUndefined(infos);
214301
214468
  return info && !info.isLocal ? { fileName: info.fileName, pos: info.textSpan.start } : void 0;
214302
214469
  }
214303
- function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2, logger) {
214470
+ function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2, logger2) {
214304
214471
  var _a, _b;
214305
214472
  const perProjectResults = getPerProjectReferences(
214306
214473
  projects2,
@@ -214314,7 +214481,7 @@ ${json}${newLine}`;
214314
214481
  ),
214315
214482
  mapDefinitionInProject,
214316
214483
  (project, position) => {
214317
- logger.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`);
214484
+ logger2.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`);
214318
214485
  return project.getLanguageService().findReferences(position.fileName, position.pos);
214319
214486
  },
214320
214487
  (referencedSymbol, cb) => {
@@ -218683,9 +218850,9 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
218683
218850
  }
218684
218851
  };
218685
218852
  var _TypingsInstallerAdapter = class _TypingsInstallerAdapter2 {
218686
- constructor(telemetryEnabled, logger, host, globalTypingsCacheLocation, event, maxActiveRequestCount) {
218853
+ constructor(telemetryEnabled, logger2, host, globalTypingsCacheLocation, event, maxActiveRequestCount) {
218687
218854
  this.telemetryEnabled = telemetryEnabled;
218688
- this.logger = logger;
218855
+ this.logger = logger2;
218689
218856
  this.host = host;
218690
218857
  this.globalTypingsCacheLocation = globalTypingsCacheLocation;
218691
218858
  this.event = event;
@@ -225663,13 +225830,13 @@ var require_reusify = __commonJS({
225663
225830
  current.next = null;
225664
225831
  return current;
225665
225832
  }
225666
- function release(obj) {
225833
+ function release2(obj) {
225667
225834
  tail.next = obj;
225668
225835
  tail = obj;
225669
225836
  }
225670
225837
  return {
225671
225838
  get,
225672
- release
225839
+ release: release2
225673
225840
  };
225674
225841
  }
225675
225842
  module2.exports = reusify;
@@ -225713,7 +225880,7 @@ var require_queue = __commonJS({
225713
225880
  if (self.paused) return;
225714
225881
  for (; queueHead && _running < _concurrency; ) {
225715
225882
  _running++;
225716
- release();
225883
+ release2();
225717
225884
  }
225718
225885
  },
225719
225886
  running,
@@ -225758,12 +225925,12 @@ var require_queue = __commonJS({
225758
225925
  self.paused = false;
225759
225926
  if (queueHead === null) {
225760
225927
  _running++;
225761
- release();
225928
+ release2();
225762
225929
  return;
225763
225930
  }
225764
225931
  for (; queueHead && _running < _concurrency; ) {
225765
225932
  _running++;
225766
- release();
225933
+ release2();
225767
225934
  }
225768
225935
  }
225769
225936
  function idle() {
@@ -225772,7 +225939,7 @@ var require_queue = __commonJS({
225772
225939
  function push2(value, done) {
225773
225940
  var current = cache.get();
225774
225941
  current.context = context;
225775
- current.release = release;
225942
+ current.release = release2;
225776
225943
  current.value = value;
225777
225944
  current.callback = done || noop3;
225778
225945
  current.errorHandler = errorHandler;
@@ -225793,7 +225960,7 @@ var require_queue = __commonJS({
225793
225960
  function unshift(value, done) {
225794
225961
  var current = cache.get();
225795
225962
  current.context = context;
225796
- current.release = release;
225963
+ current.release = release2;
225797
225964
  current.value = value;
225798
225965
  current.callback = done || noop3;
225799
225966
  current.errorHandler = errorHandler;
@@ -225811,7 +225978,7 @@ var require_queue = __commonJS({
225811
225978
  worker.call(context, current.value, current.worked);
225812
225979
  }
225813
225980
  }
225814
- function release(holder) {
225981
+ function release2(holder) {
225815
225982
  if (holder) {
225816
225983
  cache.release(holder);
225817
225984
  }
@@ -283168,7 +283335,7 @@ var import_child_process3 = require("child_process");
283168
283335
 
283169
283336
  // src/migrate.ts
283170
283337
  init_cjs_shims();
283171
- var import_errors7 = require("@abloatai/transaction/errors");
283338
+ var import_errors8 = require("@abloatai/transaction/errors");
283172
283339
  init_dist2();
283173
283340
  var import_picocolors6 = __toESM(require_picocolors(), 1);
283174
283341
  var import_fs5 = require("fs");
@@ -283215,7 +283382,7 @@ function parseMigrateArgs(argv) {
283215
283382
  targetSchema = argv[++i] ?? targetSchema;
283216
283383
  break;
283217
283384
  default:
283218
- throw new import_errors7.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283385
+ throw new import_errors8.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283219
283386
  }
283220
283387
  }
283221
283388
  return { schemaPath, exportName, targetSchema, dryRun, outputFile };
@@ -283331,7 +283498,7 @@ async function migrate(argv) {
283331
283498
  }
283332
283499
  const dbUrl = readProjectAdminDatabaseUrl();
283333
283500
  if (!dbUrl) {
283334
- throw new import_errors7.AbloValidationError(
283501
+ throw new import_errors8.AbloValidationError(
283335
283502
  `No ${ADMIN_URL_VAR} found (checked process env, .env.local, .env). Set it to apply, or use --dry-run to preview.`,
283336
283503
  { code: "cli_database_url_missing" }
283337
283504
  );
@@ -283546,14 +283713,14 @@ function requireKey2(explicit) {
283546
283713
  }
283547
283714
  return key;
283548
283715
  }
283549
- async function request2(path, init2 = {}, context = {}) {
283716
+ async function request2(path, init4 = {}, context = {}) {
283550
283717
  const response = await fetch(`${apiUrl2(context.baseUrl)}${path}`, {
283551
- method: init2.method ?? "GET",
283718
+ method: init4.method ?? "GET",
283552
283719
  headers: {
283553
283720
  authorization: `Bearer ${requireKey2(context.apiKey)}`,
283554
283721
  "content-type": "application/json"
283555
283722
  },
283556
- ...init2.body !== void 0 ? { body: JSON.stringify(init2.body) } : {}
283723
+ ...init4.body !== void 0 ? { body: JSON.stringify(init4.body) } : {}
283557
283724
  });
283558
283725
  let body;
283559
283726
  try {
@@ -283779,15 +283946,15 @@ async function branches(argv) {
283779
283946
 
283780
283947
  // src/branchDev.ts
283781
283948
  init_cjs_shims();
283782
- var import_node_crypto = require("crypto");
283949
+ var import_node_crypto2 = require("crypto");
283783
283950
  var import_node_child_process = require("child_process");
283784
283951
  var import_branches2 = require("@abloatai/transaction/branches");
283785
- var import_errors12 = require("@abloatai/transaction/errors");
283952
+ var import_errors13 = require("@abloatai/transaction/errors");
283786
283953
  init_config();
283787
283954
 
283788
283955
  // src/dev.ts
283789
283956
  init_cjs_shims();
283790
- var import_errors11 = require("@abloatai/transaction/errors");
283957
+ var import_errors12 = require("@abloatai/transaction/errors");
283791
283958
  var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
283792
283959
  var import_picocolors15 = __toESM(require_picocolors(), 1);
283793
283960
  init_dist2();
@@ -283833,7 +284000,7 @@ function parseDevArgs(argv) {
283833
284000
  sourcePath = argv[++i] ?? sourcePath;
283834
284001
  break;
283835
284002
  default:
283836
- throw new import_errors11.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284003
+ throw new import_errors12.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283837
284004
  }
283838
284005
  }
283839
284006
  url = url.replace(/\/+$/, "");
@@ -283851,7 +284018,7 @@ function parseDevArgs(argv) {
283851
284018
  async function loadLocalSourceHandler(sourcePath) {
283852
284019
  const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
283853
284020
  if (!(0, import_fs7.existsSync)(abs)) {
283854
- throw new import_errors11.AbloValidationError(
284021
+ throw new import_errors12.AbloValidationError(
283855
284022
  `local Data Source not found at ${import_picocolors15.default.bold(sourcePath)}. Add the signed Data Source handler described by ${import_picocolors15.default.bold("npx ablo docs data-sources")}, or pass ${import_picocolors15.default.bold("--source <path>")}.`,
283856
284023
  { code: "cli_invalid_arguments" }
283857
284024
  );
@@ -283862,7 +284029,7 @@ async function loadLocalSourceHandler(sourcePath) {
283862
284029
  const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
283863
284030
  const handler = mod.POST ?? nested?.POST;
283864
284031
  if (typeof handler !== "function") {
283865
- throw new import_errors11.AbloValidationError(
284032
+ throw new import_errors12.AbloValidationError(
283866
284033
  `${import_picocolors15.default.bold(sourcePath)} must export a ${import_picocolors15.default.bold("POST(request)")} Data Source handler.`,
283867
284034
  { code: "cli_invalid_arguments" }
283868
284035
  );
@@ -283886,7 +284053,7 @@ async function registerLocalSource(args) {
283886
284053
  });
283887
284054
  if (!response.ok) {
283888
284055
  const body = await response.text();
283889
- throw new import_errors11.AbloValidationError(
284056
+ throw new import_errors12.AbloValidationError(
283890
284057
  `Could not register the local Data Source (${response.status}): ${body}`,
283891
284058
  { code: "cli_invalid_arguments" }
283892
284059
  );
@@ -284063,7 +284230,7 @@ async function dev(argv, runtime = {}) {
284063
284230
  else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
284064
284231
  if (runtime.branch) args.planeLabel = runtime.branch.slug;
284065
284232
  if (args.local && !args.watch) {
284066
- throw new import_errors11.AbloValidationError(
284233
+ throw new import_errors12.AbloValidationError(
284067
284234
  `${import_picocolors15.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors15.default.bold("--no-watch")}.`,
284068
284235
  { code: "cli_invalid_arguments" }
284069
284236
  );
@@ -284214,7 +284381,7 @@ function parseBranchDevArgs(argv) {
284214
284381
  const arg = argv[index];
284215
284382
  if (!arg) continue;
284216
284383
  if (arg === "--no-branch") {
284217
- throw new import_errors12.AbloValidationError(
284384
+ throw new import_errors13.AbloValidationError(
284218
284385
  "--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
284219
284386
  { code: "cli_invalid_arguments" }
284220
284387
  );
@@ -284222,7 +284389,7 @@ function parseBranchDevArgs(argv) {
284222
284389
  if (arg === "--branch") {
284223
284390
  branchSlug = argv[++index];
284224
284391
  if (!branchSlug) {
284225
- throw new import_errors12.AbloValidationError("--branch requires a slug", {
284392
+ throw new import_errors13.AbloValidationError("--branch requires a slug", {
284226
284393
  code: "cli_invalid_arguments"
284227
284394
  });
284228
284395
  }
@@ -284231,7 +284398,7 @@ function parseBranchDevArgs(argv) {
284231
284398
  if (arg === "--branch-ttl-hours") {
284232
284399
  const value = Number(argv[++index]);
284233
284400
  if (!Number.isInteger(value) || value < 1 || value > 168) {
284234
- throw new import_errors12.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
284401
+ throw new import_errors13.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
284235
284402
  code: "cli_invalid_arguments"
284236
284403
  });
284237
284404
  }
@@ -284249,12 +284416,12 @@ function parseBranchDevArgs(argv) {
284249
284416
  function branchSlugFromRef(ref) {
284250
284417
  const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
284251
284418
  if (!base) {
284252
- throw new import_errors12.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
284419
+ throw new import_errors13.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
284253
284420
  code: "cli_invalid_arguments"
284254
284421
  });
284255
284422
  }
284256
284423
  const nonRoot = base === "production" ? "production-dev" : base;
284257
- const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
284424
+ const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto2.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
284258
284425
  return import_branches2.branchSlugSchema.parse(shortened);
284259
284426
  }
284260
284427
  function gitBranch() {
@@ -284271,7 +284438,7 @@ function gitBranch() {
284271
284438
  function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
284272
284439
  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();
284273
284440
  if (!value) {
284274
- throw new import_errors12.AbloValidationError(
284441
+ throw new import_errors13.AbloValidationError(
284275
284442
  "Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
284276
284443
  { code: "cli_invalid_arguments" }
284277
284444
  );
@@ -284289,13 +284456,13 @@ async function runBranchDev(argv, dependencies = {}) {
284289
284456
  const slug = branchSlugFromRef(ref);
284290
284457
  const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
284291
284458
  if (!managementKey) {
284292
- throw new import_errors12.AbloValidationError(
284459
+ throw new import_errors13.AbloValidationError(
284293
284460
  "Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY.",
284294
284461
  { code: "cli_invalid_arguments" }
284295
284462
  );
284296
284463
  }
284297
284464
  if (!managementKey.startsWith("mk_")) {
284298
- throw new import_errors12.AbloValidationError(
284465
+ throw new import_errors13.AbloValidationError(
284299
284466
  "Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
284300
284467
  { code: "cli_invalid_arguments" }
284301
284468
  );
@@ -284322,7 +284489,7 @@ async function runBranchDev(argv, dependencies = {}) {
284322
284489
  // src/whoami.ts
284323
284490
  init_cjs_shims();
284324
284491
  var import_picocolors16 = __toESM(require_picocolors(), 1);
284325
- var import_errors13 = require("@abloatai/transaction/errors");
284492
+ var import_errors14 = require("@abloatai/transaction/errors");
284326
284493
  init_config();
284327
284494
  init_controlPlane();
284328
284495
 
@@ -284397,7 +284564,7 @@ function parseWhoamiArgs(argv) {
284397
284564
  case "--key": {
284398
284565
  const value = argv[++i];
284399
284566
  if (!value || value.startsWith("--")) {
284400
- throw new import_errors13.AbloValidationError("`--key` needs a credential value.", {
284567
+ throw new import_errors14.AbloValidationError("`--key` needs a credential value.", {
284401
284568
  code: "cli_invalid_arguments"
284402
284569
  });
284403
284570
  }
@@ -284407,12 +284574,12 @@ function parseWhoamiArgs(argv) {
284407
284574
  case "--key-env": {
284408
284575
  const value = argv[++i];
284409
284576
  if (!value || value.startsWith("--")) {
284410
- throw new import_errors13.AbloValidationError("`--key-env` needs an environment variable name.", {
284577
+ throw new import_errors14.AbloValidationError("`--key-env` needs an environment variable name.", {
284411
284578
  code: "cli_invalid_arguments"
284412
284579
  });
284413
284580
  }
284414
284581
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
284415
- throw new import_errors13.AbloValidationError(
284582
+ throw new import_errors14.AbloValidationError(
284416
284583
  `\`${value}\` is not a valid environment variable name.`,
284417
284584
  { code: "cli_invalid_arguments" }
284418
284585
  );
@@ -284421,13 +284588,13 @@ function parseWhoamiArgs(argv) {
284421
284588
  break;
284422
284589
  }
284423
284590
  default:
284424
- throw new import_errors13.AbloValidationError(`unknown whoami flag: ${arg}`, {
284591
+ throw new import_errors14.AbloValidationError(`unknown whoami flag: ${arg}`, {
284425
284592
  code: "cli_invalid_arguments"
284426
284593
  });
284427
284594
  }
284428
284595
  }
284429
284596
  if (key && keyEnv) {
284430
- throw new import_errors13.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
284597
+ throw new import_errors14.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
284431
284598
  code: "cli_invalid_arguments"
284432
284599
  });
284433
284600
  }
@@ -284438,7 +284605,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
284438
284605
  if (args.keyEnv) {
284439
284606
  const found = readProjectEnvVariable(args.keyEnv, cwd);
284440
284607
  if (!found) {
284441
- throw new import_errors13.AbloAuthenticationError(
284608
+ throw new import_errors14.AbloAuthenticationError(
284442
284609
  `${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
284443
284610
  { code: "cli_api_key_missing" }
284444
284611
  );
@@ -284467,7 +284634,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
284467
284634
  };
284468
284635
  }
284469
284636
  const ambient = ambientEnvKeyNote();
284470
- throw new import_errors13.AbloAuthenticationError(
284637
+ throw new import_errors14.AbloAuthenticationError(
284471
284638
  `No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
284472
284639
 
284473
284640
  ${ambient}` : ""}`,
@@ -284485,7 +284652,7 @@ async function whoami(argv) {
284485
284652
  });
284486
284653
  const confirmed = target.confirmed;
284487
284654
  if (!confirmed) {
284488
- throw new import_errors13.AbloAuthenticationError(
284655
+ throw new import_errors14.AbloAuthenticationError(
284489
284656
  "The server did not confirm an identity for this credential.",
284490
284657
  { code: "identity_resolve_failed" }
284491
284658
  );
@@ -284820,12 +284987,12 @@ function fullRows(group) {
284820
284987
  }
284821
284988
 
284822
284989
  // src/index.ts
284823
- var import_errors21 = require("@abloatai/transaction/errors");
284990
+ var import_errors22 = require("@abloatai/transaction/errors");
284824
284991
  init_push();
284825
284992
 
284826
284993
  // src/generate.ts
284827
284994
  init_cjs_shims();
284828
- var import_errors14 = require("@abloatai/transaction/errors");
284995
+ var import_errors15 = require("@abloatai/transaction/errors");
284829
284996
  var import_fs8 = require("fs");
284830
284997
  var import_path6 = require("path");
284831
284998
  var import_picocolors17 = __toESM(require_picocolors(), 1);
@@ -284851,7 +285018,7 @@ function parseGenerateArgs(argv) {
284851
285018
  out = argv[++i] ?? out;
284852
285019
  break;
284853
285020
  default:
284854
- throw new import_errors14.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285021
+ throw new import_errors15.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284855
285022
  }
284856
285023
  }
284857
285024
  return { schemaPath, exportName, out };
@@ -284884,7 +285051,7 @@ init_cjs_shims();
284884
285051
  var import_child_process2 = require("child_process");
284885
285052
  var import_picocolors18 = __toESM(require_picocolors(), 1);
284886
285053
  init_dist2();
284887
- var import_errors15 = require("@abloatai/transaction/errors");
285054
+ var import_errors16 = require("@abloatai/transaction/errors");
284888
285055
  var import_wire8 = require("@abloatai/transaction/wire");
284889
285056
  init_config();
284890
285057
  init_theme();
@@ -285018,7 +285185,7 @@ ${import_picocolors18.default.dim(url)}`, "Approve in your browser");
285018
285185
  }
285019
285186
  if (!provRes.ok) {
285020
285187
  s.stop("Could not provision a key.");
285021
- const err = (0, import_errors15.translateHttpError)(
285188
+ const err = (0, import_errors16.translateHttpError)(
285022
285189
  provRes.status,
285023
285190
  await provRes.json().catch(() => null),
285024
285191
  provRes.headers.get("x-request-id") ?? void 0
@@ -285582,7 +285749,7 @@ async function doctor() {
285582
285749
 
285583
285750
  // src/logs.ts
285584
285751
  init_cjs_shims();
285585
- var import_errors16 = require("@abloatai/transaction/errors");
285752
+ var import_errors17 = require("@abloatai/transaction/errors");
285586
285753
  var import_wire9 = require("@abloatai/transaction/wire");
285587
285754
  var import_picocolors21 = __toESM(require_picocolors(), 1);
285588
285755
  init_config();
@@ -285624,12 +285791,12 @@ function parseLogsArgs(argv) {
285624
285791
  args.json = true;
285625
285792
  break;
285626
285793
  case "--mode":
285627
- throw new import_errors16.AbloValidationError(
285794
+ throw new import_errors17.AbloValidationError(
285628
285795
  "--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
285629
285796
  { code: "cli_invalid_arguments" }
285630
285797
  );
285631
285798
  default:
285632
- throw new import_errors16.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285799
+ throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285633
285800
  }
285634
285801
  }
285635
285802
  return args;
@@ -285908,7 +286075,7 @@ async function webhooks(argv) {
285908
286075
 
285909
286076
  // src/check.ts
285910
286077
  init_cjs_shims();
285911
- var import_errors17 = require("@abloatai/transaction/errors");
286078
+ var import_errors18 = require("@abloatai/transaction/errors");
285912
286079
  var import_picocolors23 = __toESM(require_picocolors(), 1);
285913
286080
  init_src();
285914
286081
  var import_schema9 = require("@abloatai/transaction/schema");
@@ -286056,7 +286223,7 @@ function parseCheckArgs(argv) {
286056
286223
  appSchema = argv[++i] ?? appSchema;
286057
286224
  break;
286058
286225
  default:
286059
- throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286226
+ throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286060
286227
  }
286061
286228
  }
286062
286229
  return { schemaPath, exportName, appSchema };
@@ -286222,9 +286389,9 @@ var ABLO_REACT = /* @__PURE__ */ new Set(["@abloatai/ablo/react", "@abloatai/hum
286222
286389
  function clientRoots(sf) {
286223
286390
  const roots = /* @__PURE__ */ new Set(["ablo", "sync"]);
286224
286391
  for (const decl of sf.getVariableDeclarations()) {
286225
- const init2 = decl.getInitializer();
286226
- if (!init2) continue;
286227
- const text = init2.getText();
286392
+ const init4 = decl.getInitializer();
286393
+ if (!init4) continue;
286394
+ const text = init4.getText();
286228
286395
  if (/^Ablo\s*\(/.test(text) || /^useAblo\s*\(\s*\)/.test(text)) {
286229
286396
  roots.add(decl.getName());
286230
286397
  }
@@ -286391,7 +286558,7 @@ async function upgrade(argv) {
286391
286558
 
286392
286559
  // src/pull.ts
286393
286560
  init_cjs_shims();
286394
- var import_errors18 = require("@abloatai/transaction/errors");
286561
+ var import_errors19 = require("@abloatai/transaction/errors");
286395
286562
  var import_picocolors25 = __toESM(require_picocolors(), 1);
286396
286563
  init_src();
286397
286564
  var import_fs10 = require("fs");
@@ -286420,7 +286587,7 @@ function parsePullArgs(argv) {
286420
286587
  force = true;
286421
286588
  break;
286422
286589
  default:
286423
- throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286590
+ throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286424
286591
  }
286425
286592
  }
286426
286593
  return { out, appSchema, importPath, force };
@@ -286538,7 +286705,7 @@ async function pull(argv) {
286538
286705
 
286539
286706
  // src/prismaPull.ts
286540
286707
  init_cjs_shims();
286541
- var import_errors19 = require("@abloatai/transaction/errors");
286708
+ var import_errors20 = require("@abloatai/transaction/errors");
286542
286709
  var import_picocolors26 = __toESM(require_picocolors(), 1);
286543
286710
  var import_fs11 = require("fs");
286544
286711
  init_theme();
@@ -286736,7 +286903,7 @@ function parsePrismaPullArgs(argv) {
286736
286903
  force = true;
286737
286904
  break;
286738
286905
  default:
286739
- if (arg.startsWith("--")) throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286906
+ if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286740
286907
  schema = arg;
286741
286908
  }
286742
286909
  }
@@ -286796,7 +286963,7 @@ async function prismaPull(argv) {
286796
286963
  // src/drizzlePull.ts
286797
286964
  init_cjs_shims();
286798
286965
  var import_picocolors27 = __toESM(require_picocolors(), 1);
286799
- var import_errors20 = require("@abloatai/transaction/errors");
286966
+ var import_errors21 = require("@abloatai/transaction/errors");
286800
286967
  var import_fs12 = require("fs");
286801
286968
  var import_path7 = require("path");
286802
286969
  init_theme();
@@ -286903,7 +287070,7 @@ function parseDrizzlePullArgs(argv) {
286903
287070
  force = true;
286904
287071
  break;
286905
287072
  default:
286906
- if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287073
+ if (arg.startsWith("--")) throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286907
287074
  schema = arg;
286908
287075
  }
286909
287076
  }
@@ -286975,6 +287142,7 @@ async function drizzlePull(argv) {
286975
287142
  // src/index.ts
286976
287143
  init_theme();
286977
287144
  init_renderError();
287145
+ init_observeCliError();
286978
287146
 
286979
287147
  // src/generators/authScaffold.ts
286980
287148
  init_cjs_shims();
@@ -287056,7 +287224,7 @@ var LOGO = `
287056
287224
  ${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}
287057
287225
  `;
287058
287226
  var HANDLERS = {
287059
- init: (argv) => init([...argv]),
287227
+ init: (argv) => init3([...argv]),
287060
287228
  login: (argv) => login([...argv]),
287061
287229
  logout: () => logout(),
287062
287230
  projects: (argv) => projects([...argv]),
@@ -287109,7 +287277,7 @@ async function main() {
287109
287277
  const argv = process.argv.slice(3);
287110
287278
  if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
287111
287279
  const suggestion = suggestCommand(raw);
287112
- throw new import_errors21.AbloValidationError(
287280
+ throw new import_errors22.AbloValidationError(
287113
287281
  `\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
287114
287282
  { code: "cli_invalid_arguments" }
287115
287283
  );
@@ -287253,7 +287421,7 @@ async function chooseBool(flagValue, fallback, interactive, prompt) {
287253
287421
  bailIfCancelled(value);
287254
287422
  return value;
287255
287423
  }
287256
- async function init(args = []) {
287424
+ async function init3(args = []) {
287257
287425
  const opts = parseInitArgs(args);
287258
287426
  const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
287259
287427
  Ie(`${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}`);
@@ -287786,8 +287954,17 @@ function detectPackageManager() {
287786
287954
  if ((0, import_fs13.existsSync)("bun.lockb")) return "bun";
287787
287955
  return "npm";
287788
287956
  }
287789
- main().catch((err) => {
287957
+ installCliExitObservationBoundary();
287958
+ main().catch(async (err) => {
287959
+ if (err instanceof CliFailureExit) {
287960
+ observeCliError(err);
287961
+ await flushCliErrors();
287962
+ restoreCliExitObservationBoundary();
287963
+ process.exit(err.exitCode);
287964
+ }
287790
287965
  renderCliError(err);
287966
+ await flushCliErrors();
287967
+ restoreCliExitObservationBoundary();
287791
287968
  process.exit(process.exitCode ?? 1);
287792
287969
  });
287793
287970
  /*! Bundled license information: