@abloatai/cli 0.48.0 → 0.49.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 +371 -185
  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.49.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");
@@ -4983,6 +5146,18 @@ async function registerDirectDataSource(opts) {
4983
5146
  ` This deployment can\u2019t accept connection strings \u2014 use a self-hosted/hosted engine, or the signed endpoint fallback.`
4984
5147
  )
4985
5148
  );
5149
+ } else if (err.code === "database_loopback_requires_connector") {
5150
+ console.error(`
5151
+ ${import_picocolors7.default.cyan("Recommended for this localhost-first project")}
5152
+ 1. ${import_picocolors7.default.bold("npx ablo migrate")} ${import_picocolors7.default.dim("(once: models + idempotency + outbox)")}
5153
+ 2. ${import_picocolors7.default.bold("npx ablo dev --local")} ${import_picocolors7.default.dim("(keep running beside the app)")}
5154
+
5155
+ ${import_picocolors7.default.dim("This keeps Postgres private and supports reads, coordinated writes, claims,")}
5156
+ ${import_picocolors7.default.dim("subscriptions, and confirmations through the signed Data Source connector.")}
5157
+ ${import_picocolors7.default.yellow("Note:")} ${import_picocolors7.default.dim("raw SQL or unrelated ORM writes are not automatically observed without WAL.")}
5158
+
5159
+ ${import_picocolors7.default.dim("If every arbitrary database write must be observed, use a secure database-capable")}
5160
+ ${import_picocolors7.default.dim("tunnel, hosted direct Postgres, PrivateLink, peering, or VPN\u2014not a transaction pooler.")}`);
4986
5161
  } else if (err.code === "database_not_replication_ready" || err.code === "data_source_blocked") {
4987
5162
  for (const f of failures) {
4988
5163
  const { label, fix } = describeRemoteFailure(f);
@@ -5013,9 +5188,9 @@ async function registerDirectDataSource(opts) {
5013
5188
  }
5014
5189
  console.error(
5015
5190
  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.`
5191
+ ` Ablo's servers must be able to reach this database for the direct WAL path.
5192
+ For localhost development, run ${import_picocolors7.default.bold("ablo dev --local")}. For private deployments,
5193
+ establish an allowlist, PrivateLink, peering, or VPN.`
5019
5194
  )
5020
5195
  );
5021
5196
  }
@@ -5077,9 +5252,9 @@ async function deregisterDataSource(opts) {
5077
5252
  });
5078
5253
  return { removed: true, response };
5079
5254
  } 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(
5255
+ if (err instanceof import_errors9.AbloError && err.code === "entity_not_found") return { removed: false };
5256
+ if (err instanceof import_errors9.AbloError && err.code === "forbidden") {
5257
+ throw new import_errors9.AbloPermissionError(
5083
5258
  `${err.message}. Disconnecting needs a branch-bound secret key (sk_\u2026).`,
5084
5259
  {
5085
5260
  code: "forbidden",
@@ -5135,7 +5310,7 @@ async function disconnect(argv) {
5135
5310
  console.log(DISCONNECT_USAGE);
5136
5311
  return;
5137
5312
  } else {
5138
- throw new import_errors8.AbloValidationError(
5313
+ throw new import_errors9.AbloValidationError(
5139
5314
  `unknown flag: ${arg} \u2014 see \`ablo connect deregister --help\``,
5140
5315
  { code: "cli_invalid_arguments" }
5141
5316
  );
@@ -5150,7 +5325,7 @@ async function disconnect(argv) {
5150
5325
  try {
5151
5326
  process.loadEnvFile(envFile);
5152
5327
  } catch (error) {
5153
- throw new import_errors8.AbloValidationError(
5328
+ throw new import_errors9.AbloValidationError(
5154
5329
  `could not load --env-file ${envFile}: ${error instanceof Error ? error.message : String(error)}`,
5155
5330
  { code: "cli_invalid_arguments" }
5156
5331
  );
@@ -5158,7 +5333,7 @@ async function disconnect(argv) {
5158
5333
  }
5159
5334
  const selected = keyEnv ? readProjectEnvVariable(keyEnv) : null;
5160
5335
  if (keyEnv && !selected) {
5161
- throw new import_errors8.AbloAuthenticationError(
5336
+ throw new import_errors9.AbloAuthenticationError(
5162
5337
  `No value named ${keyEnv} was found in the process environment, .env.local, or .env.`,
5163
5338
  { code: "cli_api_key_missing" }
5164
5339
  );
@@ -5170,7 +5345,7 @@ async function disconnect(argv) {
5170
5345
  const apiKey = resolved.key;
5171
5346
  const keySource = resolved.source ?? "stored";
5172
5347
  if (!apiKey) {
5173
- throw new import_errors8.AbloAuthenticationError(
5348
+ throw new import_errors9.AbloAuthenticationError(
5174
5349
  "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
5350
  { code: "cli_api_key_missing" }
5176
5351
  );
@@ -5184,7 +5359,7 @@ async function disconnect(argv) {
5184
5359
  `);
5185
5360
  if (!skipConfirm) {
5186
5361
  if (!process.stdout.isTTY) {
5187
- throw new import_errors8.AbloValidationError(
5362
+ throw new import_errors9.AbloValidationError(
5188
5363
  "This session has no terminal to confirm in. Re-run with --yes to disconnect non-interactively.",
5189
5364
  { code: "cli_invalid_arguments" }
5190
5365
  );
@@ -5207,14 +5382,14 @@ async function disconnect(argv) {
5207
5382
  }
5208
5383
  renderDisconnected(outcome.response, project, branchLabel);
5209
5384
  }
5210
- var import_picocolors8, import_errors8, import_wire4, DISCONNECT_USAGE;
5385
+ var import_picocolors8, import_errors9, import_wire4, DISCONNECT_USAGE;
5211
5386
  var init_disconnect = __esm({
5212
5387
  "src/disconnect.ts"() {
5213
5388
  "use strict";
5214
5389
  init_cjs_shims();
5215
5390
  import_picocolors8 = __toESM(require_picocolors(), 1);
5216
5391
  init_dist2();
5217
- import_errors8 = require("@abloatai/transaction/errors");
5392
+ import_errors9 = require("@abloatai/transaction/errors");
5218
5393
  import_wire4 = require("@abloatai/transaction/wire");
5219
5394
  init_config();
5220
5395
  init_dbRole();
@@ -5467,7 +5642,7 @@ function blockers(input) {
5467
5642
  }
5468
5643
  if (input.dataSource.kind === "none") {
5469
5644
  found.push({
5470
- problem: "this branch is not connected to a database, so writes are held",
5645
+ problem: "no database is connected to this branch, so writes are held",
5471
5646
  fix: "connect one with `ablo connect apply`"
5472
5647
  });
5473
5648
  }
@@ -5822,7 +5997,7 @@ async function runConnectApply(args) {
5822
5997
  const verb = rotating ? "connect rotate" : "connect apply";
5823
5998
  let adminUrl = args.url ?? readProjectAdminDatabaseUrl();
5824
5999
  if (!adminUrl) {
5825
- throw new import_errors9.AbloValidationError(
6000
+ throw new import_errors10.AbloValidationError(
5826
6001
  "No admin connection string. Pass --url <admin-conn> (or set DATABASE_URL) and re-run.",
5827
6002
  { code: "cli_database_url_missing" }
5828
6003
  );
@@ -5839,7 +6014,7 @@ async function runConnectApply(args) {
5839
6014
  const loggedIn = resolveManagementKey() !== void 0;
5840
6015
  const ambient = ambientEnvKeyNote();
5841
6016
  const retry = `npx ablo connect ${rotating ? "rotate" : "apply"} --env-file .env.local --yes`;
5842
- throw new import_errors9.AbloAuthenticationError(
6017
+ throw new import_errors10.AbloAuthenticationError(
5843
6018
  loggedIn ? `You are logged in, but connect needs a branch-bound runtime key.
5844
6019
 
5845
6020
  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 +6079,6 @@ ${ambient}` : ""}`,
5904
6079
  ` + import_picocolors11.default.dim(
5905
6080
  ` Replication cannot run over a pooler, so if that is what this is, point ${import_picocolors11.default.bold("--url")}
5906
6081
  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
6082
  `
5924
6083
  )
5925
6084
  );
@@ -5936,7 +6095,7 @@ ${ambient}` : ""}`,
5936
6095
  }
5937
6096
  const confirmed = connectTarget?.confirmed;
5938
6097
  if (!confirmed?.branchId) {
5939
- throw new import_errors9.AbloConnectionError(
6098
+ throw new import_errors10.AbloConnectionError(
5940
6099
  "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
6100
  { code: "cli_database_unreachable" }
5942
6101
  );
@@ -5967,6 +6126,22 @@ ${ambient}` : ""}`,
5967
6126
  );
5968
6127
  process.exit(1);
5969
6128
  }
6129
+ const coordinatedTables = await schemaDeclaredTables() ?? [];
6130
+ const tables = args.tables.length > 0 ? args.tables : coordinatedTables;
6131
+ if (tables.length === 0) {
6132
+ throw new import_errors10.AbloValidationError(
6133
+ `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.`,
6134
+ { code: "cli_invalid_arguments" }
6135
+ );
6136
+ }
6137
+ if (args.tables.length === 0) {
6138
+ console.log(
6139
+ import_picocolors11.default.dim(
6140
+ ` 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)
6141
+ `
6142
+ )
6143
+ );
6144
+ }
5970
6145
  let rotatePlane = null;
5971
6146
  if (rotating) {
5972
6147
  const state = await fetchDataSourceState(apiBaseUrl(), apiKey).catch(
@@ -6002,7 +6177,7 @@ ${ambient}` : ""}`,
6002
6177
  } catch (err) {
6003
6178
  await admin.end({ timeout: 2 }).catch(() => void 0);
6004
6179
  const pg = err ?? {};
6005
- throw new import_errors9.AbloConnectionError(`Couldn't connect: ${pg.message ?? String(err)}`, {
6180
+ throw new import_errors10.AbloConnectionError(`Couldn't connect: ${pg.message ?? String(err)}`, {
6006
6181
  code: "cli_database_unreachable",
6007
6182
  details: { target },
6008
6183
  cause: err
@@ -6259,7 +6434,7 @@ ${ambient}` : ""}`,
6259
6434
  }
6260
6435
  process.exit(outcome.exitCode);
6261
6436
  }
6262
- var import_picocolors11, import_errors9, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
6437
+ var import_picocolors11, import_errors10, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
6263
6438
  var init_connectApply = __esm({
6264
6439
  "src/connectApply.ts"() {
6265
6440
  "use strict";
@@ -6267,7 +6442,7 @@ var init_connectApply = __esm({
6267
6442
  import_picocolors11 = __toESM(require_picocolors(), 1);
6268
6443
  init_src();
6269
6444
  init_dist2();
6270
- import_errors9 = require("@abloatai/transaction/errors");
6445
+ import_errors10 = require("@abloatai/transaction/errors");
6271
6446
  import_footprint2 = require("@abloatai/transaction/footprint");
6272
6447
  init_connectSetup();
6273
6448
  init_connectOwnership();
@@ -6331,7 +6506,7 @@ function parseConnectArgs(argv) {
6331
6506
  locate = true;
6332
6507
  break;
6333
6508
  default:
6334
- throw new import_errors10.AbloValidationError(
6509
+ throw new import_errors11.AbloValidationError(
6335
6510
  `unknown connect subcommand: ${lead} (expected register, deregister, check, apply, rotate, resnapshot, scan, locate)`,
6336
6511
  { code: "cli_invalid_arguments" }
6337
6512
  );
@@ -6374,7 +6549,7 @@ function parseConnectArgs(argv) {
6374
6549
  case "--route": {
6375
6550
  const value = argv[++i] ?? "";
6376
6551
  if (!DIRECT_DATA_SOURCE_ROUTES.includes(value)) {
6377
- throw new import_errors10.AbloValidationError(
6552
+ throw new import_errors11.AbloValidationError(
6378
6553
  `invalid direct route: ${value || "(missing)"} (expected ${DIRECT_DATA_SOURCE_ROUTES.join(", ")})`,
6379
6554
  { code: "cli_invalid_arguments" }
6380
6555
  );
@@ -6383,11 +6558,11 @@ function parseConnectArgs(argv) {
6383
6558
  break;
6384
6559
  }
6385
6560
  default:
6386
- throw new import_errors10.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
6561
+ throw new import_errors11.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
6387
6562
  }
6388
6563
  }
6389
6564
  if (role === writeRole) {
6390
- throw new import_errors10.AbloValidationError("replication and write roles must be different", {
6565
+ throw new import_errors11.AbloValidationError("replication and write roles must be different", {
6391
6566
  code: "cli_invalid_arguments"
6392
6567
  });
6393
6568
  }
@@ -6694,7 +6869,7 @@ async function probeAndReport(dbUrl, kind, opts) {
6694
6869
  const dial = dialFailureReason(err);
6695
6870
  if (dial) return { kind: "no-dial", reason: dial };
6696
6871
  const pg = err ?? {};
6697
- throw new import_errors10.AbloConnectionError(`Couldn't read the database: ${pg.message ?? String(err)}`, {
6872
+ throw new import_errors11.AbloConnectionError(`Couldn't read the database: ${pg.message ?? String(err)}`, {
6698
6873
  code: "cli_database_unreachable",
6699
6874
  cause: err
6700
6875
  });
@@ -6712,7 +6887,7 @@ async function runCheck() {
6712
6887
  const apiKey = resolveRuntimeApiKey().key;
6713
6888
  if (!apiKey) {
6714
6889
  const ambient = ambientEnvKeyNote();
6715
- throw new import_errors10.AbloAuthenticationError(
6890
+ throw new import_errors11.AbloAuthenticationError(
6716
6891
  `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
6892
 
6718
6893
  ${ambient}` : ""}`,
@@ -6749,8 +6924,9 @@ ${ambient}` : ""}`,
6749
6924
  );
6750
6925
  console.error(
6751
6926
  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.
6927
+ ` For localhost-first development, run ${import_picocolors12.default.bold("ablo dev --local")} and keep it beside the app.
6928
+ The direct WAL path needs a route Ablo's servers can dial \u2014 public allowlist,
6929
+ PrivateLink, peering, VPN, or a database-capable secure tunnel.
6754
6930
  `
6755
6931
  )
6756
6932
  );
@@ -6804,7 +6980,7 @@ async function runRegister(args) {
6804
6980
  const apiKey = resolveMutationApiKey();
6805
6981
  if (!apiKey) {
6806
6982
  const ambient = ambientEnvKeyNote();
6807
- throw new import_errors10.AbloAuthenticationError(
6983
+ throw new import_errors11.AbloAuthenticationError(
6808
6984
  `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
6985
 
6810
6986
  ${ambient}` : ""}`,
@@ -6819,7 +6995,7 @@ ${ambient}` : ""}`,
6819
6995
  const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
6820
6996
  const confirmed = target.confirmed;
6821
6997
  if (!confirmed?.branchId) {
6822
- throw new import_errors10.AbloValidationError(
6998
+ throw new import_errors11.AbloValidationError(
6823
6999
  "This key is not bound to a branch, so Ablo cannot validate isolated database objects safely.",
6824
7000
  { code: "cli_database_unreachable" }
6825
7001
  );
@@ -6901,7 +7077,7 @@ async function runScan(args) {
6901
7077
  } catch (err) {
6902
7078
  const pg = err ?? {};
6903
7079
  await sql.end({ timeout: 2 });
6904
- throw new import_errors10.AbloConnectionError(`Couldn't audit the database: ${pg.message ?? String(err)}`, {
7080
+ throw new import_errors11.AbloConnectionError(`Couldn't audit the database: ${pg.message ?? String(err)}`, {
6905
7081
  code: "cli_database_unreachable",
6906
7082
  cause: err
6907
7083
  });
@@ -6953,7 +7129,7 @@ async function runLocate(args) {
6953
7129
  );
6954
7130
  const url = args.url ?? readProjectAdminDatabaseUrl();
6955
7131
  if (!url) {
6956
- throw new import_errors10.AbloValidationError(
7132
+ throw new import_errors11.AbloValidationError(
6957
7133
  "Locating needs a connection string to identify the database. Pass --url <conn> (or set DATABASE_URL) and re-run.",
6958
7134
  { code: "cli_database_url_missing" }
6959
7135
  );
@@ -6961,7 +7137,7 @@ async function runLocate(args) {
6961
7137
  const apiKey = resolveRuntimeApiKey().key;
6962
7138
  if (!apiKey) {
6963
7139
  const ambient = ambientEnvKeyNote();
6964
- throw new import_errors10.AbloAuthenticationError(
7140
+ throw new import_errors11.AbloAuthenticationError(
6965
7141
  `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
7142
 
6967
7143
  ${ambient}` : ""}`,
@@ -7012,7 +7188,7 @@ ${ambient}` : ""}`,
7012
7188
  async function runResnapshot() {
7013
7189
  const apiKey = resolveMutationApiKey();
7014
7190
  if (!apiKey) {
7015
- throw new import_errors10.AbloAuthenticationError(
7191
+ throw new import_errors11.AbloAuthenticationError(
7016
7192
  "No branch-bound secret key found. Set ABLO_API_KEY to the sk_ key for the branch to resnapshot.",
7017
7193
  { code: "cli_api_key_missing" }
7018
7194
  );
@@ -7057,7 +7233,7 @@ async function connect(argv) {
7057
7233
  try {
7058
7234
  process.loadEnvFile(args.envFile);
7059
7235
  } catch (error) {
7060
- throw new import_errors10.AbloValidationError(
7236
+ throw new import_errors11.AbloValidationError(
7061
7237
  `could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
7062
7238
  { code: "cli_invalid_arguments" }
7063
7239
  );
@@ -7097,7 +7273,7 @@ async function connect(argv) {
7097
7273
  }
7098
7274
  const apiKey = resolveRuntimeApiKey().key;
7099
7275
  if (!apiKey) {
7100
- throw new import_errors10.AbloAuthenticationError(
7276
+ throw new import_errors11.AbloAuthenticationError(
7101
7277
  "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
7278
  { code: "cli_api_key_missing" }
7103
7279
  );
@@ -7105,7 +7281,7 @@ async function connect(argv) {
7105
7281
  const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
7106
7282
  const confirmed = target.confirmed;
7107
7283
  if (!confirmed?.branchId) {
7108
- throw new import_errors10.AbloValidationError(
7284
+ throw new import_errors11.AbloValidationError(
7109
7285
  "This key is not bound to a branch, so Ablo cannot derive isolated database object names safely.",
7110
7286
  { code: "cli_database_unreachable" }
7111
7287
  );
@@ -7119,12 +7295,12 @@ async function connect(argv) {
7119
7295
  })
7120
7296
  );
7121
7297
  }
7122
- var import_errors10, import_picocolors12, import_footprint3, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
7298
+ var import_errors11, import_picocolors12, import_footprint3, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
7123
7299
  var init_connect = __esm({
7124
7300
  "src/connect.ts"() {
7125
7301
  "use strict";
7126
7302
  init_cjs_shims();
7127
- import_errors10 = require("@abloatai/transaction/errors");
7303
+ import_errors11 = require("@abloatai/transaction/errors");
7128
7304
  import_picocolors12 = __toESM(require_picocolors(), 1);
7129
7305
  init_src();
7130
7306
  import_footprint3 = require("@abloatai/transaction/footprint");
@@ -12852,11 +13028,11 @@ var require_typescript = __commonJS({
12852
13028
  function compareTextSpans(a, b4) {
12853
13029
  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
13030
  }
12855
- function maxBy(arr, init2, mapper) {
13031
+ function maxBy(arr, init4, mapper) {
12856
13032
  for (let i = 0; i < arr.length; i++) {
12857
- init2 = Math.max(init2, mapper(arr[i]));
13033
+ init4 = Math.max(init4, mapper(arr[i]));
12858
13034
  }
12859
- return init2;
13035
+ return init4;
12860
13036
  }
12861
13037
  function min(items, compare) {
12862
13038
  return reduceLeft(items, (x2, y3) => compare(x2, y3) === -1 ? x2 : y3);
@@ -17355,8 +17531,8 @@ ${lanes.join("\n")}
17355
17531
  function sysLog(s) {
17356
17532
  return curSysLog(s);
17357
17533
  }
17358
- function setSysLog(logger) {
17359
- curSysLog = logger;
17534
+ function setSysLog(logger2) {
17535
+ curSysLog = logger2;
17360
17536
  }
17361
17537
  function createDirectoryWatcherSupportingRecursive({
17362
17538
  watchDirectory,
@@ -28455,8 +28631,8 @@ ${lanes.join("\n")}
28455
28631
  return node.initializer;
28456
28632
  }
28457
28633
  function getDeclaredExpandoInitializer(node) {
28458
- const init2 = getEffectiveInitializer(node);
28459
- return init2 && getExpandoInitializer(init2, isPrototypeAccess(node.name));
28634
+ const init4 = getEffectiveInitializer(node);
28635
+ return init4 && getExpandoInitializer(init4, isPrototypeAccess(node.name));
28460
28636
  }
28461
28637
  function hasExpandoValueProperty(node, isPrototypeAssignment) {
28462
28638
  return forEach(node.properties, (p2) => isPropertyAssignment(p2) && isIdentifier2(p2.name) && p2.name.escapedText === "value" && p2.initializer && getExpandoInitializer(p2.initializer, isPrototypeAssignment));
@@ -62043,11 +62219,11 @@ ${lanes.join("\n")}
62043
62219
  if (node && isCallExpression(node)) {
62044
62220
  return !!getAssignedExpandoInitializer(node);
62045
62221
  }
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) {
62222
+ let init4 = !node ? void 0 : isVariableDeclaration(node) ? node.initializer : isBinaryExpression(node) ? node.right : isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right : void 0;
62223
+ init4 = init4 && getRightMostAssignedExpression(init4);
62224
+ if (init4) {
62049
62225
  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);
62226
+ return !!getExpandoInitializer(isBinaryExpression(init4) && (init4.operatorToken.kind === 57 || init4.operatorToken.kind === 61) ? init4.right : init4, isPrototypeAssignment);
62051
62227
  }
62052
62228
  return false;
62053
62229
  }
@@ -62366,15 +62542,15 @@ ${lanes.join("\n")}
62366
62542
  } else if (isIdentifier2(node)) {
62367
62543
  const symbol = lookupSymbolForName(sourceFile, node.escapedText);
62368
62544
  if (!!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) {
62369
- const init2 = symbol.valueDeclaration.initializer;
62370
- q2.enqueue(init2);
62545
+ const init4 = symbol.valueDeclaration.initializer;
62546
+ q2.enqueue(init4);
62371
62547
  if (isAssignmentExpression(
62372
- init2,
62548
+ init4,
62373
62549
  /*excludeCompoundAssignment*/
62374
62550
  true
62375
62551
  )) {
62376
- q2.enqueue(init2.left);
62377
- q2.enqueue(init2.right);
62552
+ q2.enqueue(init4.left);
62553
+ q2.enqueue(init4.right);
62378
62554
  }
62379
62555
  }
62380
62556
  }
@@ -66962,9 +67138,9 @@ ${lanes.join("\n")}
66962
67138
  )) {
66963
67139
  return void 0;
66964
67140
  }
66965
- const init2 = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
66966
- if (init2) {
66967
- const initSymbol = getSymbolOfNode(init2);
67141
+ const init4 = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
67142
+ if (init4) {
67143
+ const initSymbol = getSymbolOfNode(init4);
66968
67144
  if (initSymbol) {
66969
67145
  return mergeJSSymbols(initSymbol, symbol);
66970
67146
  }
@@ -73744,9 +73920,9 @@ ${lanes.join("\n")}
73744
73920
  }
73745
73921
  return widened;
73746
73922
  }
73747
- function getJSContainerObjectType(decl, symbol, init2) {
73923
+ function getJSContainerObjectType(decl, symbol, init4) {
73748
73924
  var _a, _b;
73749
- if (!isInJSFile(decl) || !init2 || !isObjectLiteralExpression(init2) || init2.properties.length) {
73925
+ if (!isInJSFile(decl) || !init4 || !isObjectLiteralExpression(init4) || init4.properties.length) {
73750
73926
  return void 0;
73751
73927
  }
73752
73928
  const exports22 = createSymbolTable();
@@ -88720,8 +88896,8 @@ ${lanes.join("\n")}
88720
88896
  return unreachableNeverType;
88721
88897
  }
88722
88898
  if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConstLike2(node))) {
88723
- const init2 = getDeclaredExpandoInitializer(node);
88724
- if (init2 && (init2.kind === 218 || init2.kind === 219)) {
88899
+ const init4 = getDeclaredExpandoInitializer(node);
88900
+ if (init4 && (init4.kind === 218 || init4.kind === 219)) {
88725
88901
  return getTypeAtFlowNode(flow.antecedent);
88726
88902
  }
88727
88903
  }
@@ -96342,8 +96518,8 @@ ${lanes.join("\n")}
96342
96518
  true
96343
96519
  );
96344
96520
  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;
96521
+ const init4 = (prototype == null ? void 0 : prototype.valueDeclaration) && getAssignedJSPrototype(prototype.valueDeclaration);
96522
+ return init4 ? getSymbolOfDeclaration(init4) : void 0;
96347
96523
  }
96348
96524
  function getSymbolOfExpando(node, allowDeclaration) {
96349
96525
  if (!node.parent) {
@@ -99359,8 +99535,8 @@ ${lanes.join("\n")}
99359
99535
  case 3:
99360
99536
  case 4:
99361
99537
  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);
99538
+ const init4 = getAssignedExpandoInitializer(right);
99539
+ return !!init4 && isObjectLiteralExpression(init4) && !!((_a = symbol == null ? void 0 : symbol.exports) == null ? void 0 : _a.size);
99364
99540
  default:
99365
99541
  return false;
99366
99542
  }
@@ -163359,13 +163535,13 @@ ${lanes.join("\n")}
163359
163535
  }
163360
163536
  } else {
163361
163537
  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,
163538
+ const init4 = node.declarationList.declarations[0].initializer;
163539
+ if (init4 && isRequireCall(
163540
+ init4,
163365
163541
  /*requireStringLiteralLikeArgument*/
163366
163542
  true
163367
163543
  )) {
163368
- diags.push(createDiagnosticForNode(init2, Diagnostics.require_call_may_be_converted_to_an_import));
163544
+ diags.push(createDiagnosticForNode(init4, Diagnostics.require_call_may_be_converted_to_an_import));
163369
163545
  }
163370
163546
  }
163371
163547
  const jsdocTypedefNodes = ts_codefix_exports.getJSDocTypedefNodes(node);
@@ -176256,7 +176432,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
176256
176432
  factory.createIdentifier(name)
176257
176433
  );
176258
176434
  }
176259
- function makeConst(modifiers, name, init2) {
176435
+ function makeConst(modifiers, name, init4) {
176260
176436
  return factory.createVariableStatement(
176261
176437
  modifiers,
176262
176438
  factory.createVariableDeclarationList(
@@ -176266,7 +176442,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
176266
176442
  void 0,
176267
176443
  /*type*/
176268
176444
  void 0,
176269
- init2
176445
+ init4
176270
176446
  )],
176271
176447
  2
176272
176448
  /* Const */
@@ -195240,9 +195416,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
195240
195416
  return isFunctionLike(be.right) ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner };
195241
195417
  }
195242
195418
  case 172:
195243
- const init2 = commentOwner.initializer;
195244
- if (init2 && (isFunctionExpression(init2) || isArrowFunction(init2))) {
195245
- return { commentOwner, parameters: init2.parameters, hasReturn: hasReturn(init2, options) };
195419
+ const init4 = commentOwner.initializer;
195420
+ if (init4 && (isFunctionExpression(init4) || isArrowFunction(init4))) {
195421
+ return { commentOwner, parameters: init4.parameters, hasReturn: hasReturn(init4, options) };
195246
195422
  }
195247
195423
  }
195248
195424
  }
@@ -206735,13 +206911,13 @@ ${options.prefix}` : "\n" : options.prefix
206735
206911
  return [];
206736
206912
  }
206737
206913
  var ThrottledOperations = class _ThrottledOperations {
206738
- constructor(host, logger) {
206914
+ constructor(host, logger2) {
206739
206915
  this.host = host;
206740
206916
  this.pendingTimeouts = /* @__PURE__ */ new Map();
206741
- this.logger = logger.hasLevel(
206917
+ this.logger = logger2.hasLevel(
206742
206918
  3
206743
206919
  /* verbose */
206744
- ) ? logger : void 0;
206920
+ ) ? logger2 : void 0;
206745
206921
  }
206746
206922
  /**
206747
206923
  * Wait `number` milliseconds and then invoke `cb`. If, while waiting, schedule
@@ -206774,10 +206950,10 @@ ${options.prefix}` : "\n" : options.prefix
206774
206950
  }
206775
206951
  };
206776
206952
  var GcTimer = class _GcTimer {
206777
- constructor(host, delay, logger) {
206953
+ constructor(host, delay, logger2) {
206778
206954
  this.host = host;
206779
206955
  this.delay = delay;
206780
- this.logger = logger;
206956
+ this.logger = logger2;
206781
206957
  }
206782
206958
  scheduleCollect() {
206783
206959
  if (!this.host.gc || this.timerId !== void 0) {
@@ -214138,14 +214314,14 @@ Dynamic files must always be opened with service's current directory or service
214138
214314
  return edits.every((edit) => textSpanEnd(edit.span) < pos);
214139
214315
  }
214140
214316
  var CommandNames = CommandTypes;
214141
- function formatMessage2(msg, logger, byteLength, newLine) {
214142
- const verboseLogging = logger.hasLevel(
214317
+ function formatMessage2(msg, logger2, byteLength, newLine) {
214318
+ const verboseLogging = logger2.hasLevel(
214143
214319
  3
214144
214320
  /* verbose */
214145
214321
  );
214146
214322
  const json = JSON.stringify(msg);
214147
214323
  if (verboseLogging) {
214148
- logger.info(`${msg.type}:${stringifyIndented(msg)}`);
214324
+ logger2.info(`${msg.type}:${stringifyIndented(msg)}`);
214149
214325
  }
214150
214326
  const len = byteLength(json, "utf8");
214151
214327
  return `Content-Length: ${1 + len}\r
@@ -214300,7 +214476,7 @@ ${json}${newLine}`;
214300
214476
  const info = infos && firstOrUndefined(infos);
214301
214477
  return info && !info.isLocal ? { fileName: info.fileName, pos: info.textSpan.start } : void 0;
214302
214478
  }
214303
- function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2, logger) {
214479
+ function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2, logger2) {
214304
214480
  var _a, _b;
214305
214481
  const perProjectResults = getPerProjectReferences(
214306
214482
  projects2,
@@ -214314,7 +214490,7 @@ ${json}${newLine}`;
214314
214490
  ),
214315
214491
  mapDefinitionInProject,
214316
214492
  (project, position) => {
214317
- logger.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`);
214493
+ logger2.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`);
214318
214494
  return project.getLanguageService().findReferences(position.fileName, position.pos);
214319
214495
  },
214320
214496
  (referencedSymbol, cb) => {
@@ -218683,9 +218859,9 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
218683
218859
  }
218684
218860
  };
218685
218861
  var _TypingsInstallerAdapter = class _TypingsInstallerAdapter2 {
218686
- constructor(telemetryEnabled, logger, host, globalTypingsCacheLocation, event, maxActiveRequestCount) {
218862
+ constructor(telemetryEnabled, logger2, host, globalTypingsCacheLocation, event, maxActiveRequestCount) {
218687
218863
  this.telemetryEnabled = telemetryEnabled;
218688
- this.logger = logger;
218864
+ this.logger = logger2;
218689
218865
  this.host = host;
218690
218866
  this.globalTypingsCacheLocation = globalTypingsCacheLocation;
218691
218867
  this.event = event;
@@ -225663,13 +225839,13 @@ var require_reusify = __commonJS({
225663
225839
  current.next = null;
225664
225840
  return current;
225665
225841
  }
225666
- function release(obj) {
225842
+ function release2(obj) {
225667
225843
  tail.next = obj;
225668
225844
  tail = obj;
225669
225845
  }
225670
225846
  return {
225671
225847
  get,
225672
- release
225848
+ release: release2
225673
225849
  };
225674
225850
  }
225675
225851
  module2.exports = reusify;
@@ -225713,7 +225889,7 @@ var require_queue = __commonJS({
225713
225889
  if (self.paused) return;
225714
225890
  for (; queueHead && _running < _concurrency; ) {
225715
225891
  _running++;
225716
- release();
225892
+ release2();
225717
225893
  }
225718
225894
  },
225719
225895
  running,
@@ -225758,12 +225934,12 @@ var require_queue = __commonJS({
225758
225934
  self.paused = false;
225759
225935
  if (queueHead === null) {
225760
225936
  _running++;
225761
- release();
225937
+ release2();
225762
225938
  return;
225763
225939
  }
225764
225940
  for (; queueHead && _running < _concurrency; ) {
225765
225941
  _running++;
225766
- release();
225942
+ release2();
225767
225943
  }
225768
225944
  }
225769
225945
  function idle() {
@@ -225772,7 +225948,7 @@ var require_queue = __commonJS({
225772
225948
  function push2(value, done) {
225773
225949
  var current = cache.get();
225774
225950
  current.context = context;
225775
- current.release = release;
225951
+ current.release = release2;
225776
225952
  current.value = value;
225777
225953
  current.callback = done || noop3;
225778
225954
  current.errorHandler = errorHandler;
@@ -225793,7 +225969,7 @@ var require_queue = __commonJS({
225793
225969
  function unshift(value, done) {
225794
225970
  var current = cache.get();
225795
225971
  current.context = context;
225796
- current.release = release;
225972
+ current.release = release2;
225797
225973
  current.value = value;
225798
225974
  current.callback = done || noop3;
225799
225975
  current.errorHandler = errorHandler;
@@ -225811,7 +225987,7 @@ var require_queue = __commonJS({
225811
225987
  worker.call(context, current.value, current.worked);
225812
225988
  }
225813
225989
  }
225814
- function release(holder) {
225990
+ function release2(holder) {
225815
225991
  if (holder) {
225816
225992
  cache.release(holder);
225817
225993
  }
@@ -283168,7 +283344,7 @@ var import_child_process3 = require("child_process");
283168
283344
 
283169
283345
  // src/migrate.ts
283170
283346
  init_cjs_shims();
283171
- var import_errors7 = require("@abloatai/transaction/errors");
283347
+ var import_errors8 = require("@abloatai/transaction/errors");
283172
283348
  init_dist2();
283173
283349
  var import_picocolors6 = __toESM(require_picocolors(), 1);
283174
283350
  var import_fs5 = require("fs");
@@ -283215,7 +283391,7 @@ function parseMigrateArgs(argv) {
283215
283391
  targetSchema = argv[++i] ?? targetSchema;
283216
283392
  break;
283217
283393
  default:
283218
- throw new import_errors7.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283394
+ throw new import_errors8.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283219
283395
  }
283220
283396
  }
283221
283397
  return { schemaPath, exportName, targetSchema, dryRun, outputFile };
@@ -283331,7 +283507,7 @@ async function migrate(argv) {
283331
283507
  }
283332
283508
  const dbUrl = readProjectAdminDatabaseUrl();
283333
283509
  if (!dbUrl) {
283334
- throw new import_errors7.AbloValidationError(
283510
+ throw new import_errors8.AbloValidationError(
283335
283511
  `No ${ADMIN_URL_VAR} found (checked process env, .env.local, .env). Set it to apply, or use --dry-run to preview.`,
283336
283512
  { code: "cli_database_url_missing" }
283337
283513
  );
@@ -283546,14 +283722,14 @@ function requireKey2(explicit) {
283546
283722
  }
283547
283723
  return key;
283548
283724
  }
283549
- async function request2(path, init2 = {}, context = {}) {
283725
+ async function request2(path, init4 = {}, context = {}) {
283550
283726
  const response = await fetch(`${apiUrl2(context.baseUrl)}${path}`, {
283551
- method: init2.method ?? "GET",
283727
+ method: init4.method ?? "GET",
283552
283728
  headers: {
283553
283729
  authorization: `Bearer ${requireKey2(context.apiKey)}`,
283554
283730
  "content-type": "application/json"
283555
283731
  },
283556
- ...init2.body !== void 0 ? { body: JSON.stringify(init2.body) } : {}
283732
+ ...init4.body !== void 0 ? { body: JSON.stringify(init4.body) } : {}
283557
283733
  });
283558
283734
  let body;
283559
283735
  try {
@@ -283779,15 +283955,15 @@ async function branches(argv) {
283779
283955
 
283780
283956
  // src/branchDev.ts
283781
283957
  init_cjs_shims();
283782
- var import_node_crypto = require("crypto");
283958
+ var import_node_crypto2 = require("crypto");
283783
283959
  var import_node_child_process = require("child_process");
283784
283960
  var import_branches2 = require("@abloatai/transaction/branches");
283785
- var import_errors12 = require("@abloatai/transaction/errors");
283961
+ var import_errors13 = require("@abloatai/transaction/errors");
283786
283962
  init_config();
283787
283963
 
283788
283964
  // src/dev.ts
283789
283965
  init_cjs_shims();
283790
- var import_errors11 = require("@abloatai/transaction/errors");
283966
+ var import_errors12 = require("@abloatai/transaction/errors");
283791
283967
  var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
283792
283968
  var import_picocolors15 = __toESM(require_picocolors(), 1);
283793
283969
  init_dist2();
@@ -283833,7 +284009,7 @@ function parseDevArgs(argv) {
283833
284009
  sourcePath = argv[++i] ?? sourcePath;
283834
284010
  break;
283835
284011
  default:
283836
- throw new import_errors11.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284012
+ throw new import_errors12.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
283837
284013
  }
283838
284014
  }
283839
284015
  url = url.replace(/\/+$/, "");
@@ -283851,7 +284027,7 @@ function parseDevArgs(argv) {
283851
284027
  async function loadLocalSourceHandler(sourcePath) {
283852
284028
  const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
283853
284029
  if (!(0, import_fs7.existsSync)(abs)) {
283854
- throw new import_errors11.AbloValidationError(
284030
+ throw new import_errors12.AbloValidationError(
283855
284031
  `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
284032
  { code: "cli_invalid_arguments" }
283857
284033
  );
@@ -283862,7 +284038,7 @@ async function loadLocalSourceHandler(sourcePath) {
283862
284038
  const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
283863
284039
  const handler = mod.POST ?? nested?.POST;
283864
284040
  if (typeof handler !== "function") {
283865
- throw new import_errors11.AbloValidationError(
284041
+ throw new import_errors12.AbloValidationError(
283866
284042
  `${import_picocolors15.default.bold(sourcePath)} must export a ${import_picocolors15.default.bold("POST(request)")} Data Source handler.`,
283867
284043
  { code: "cli_invalid_arguments" }
283868
284044
  );
@@ -283886,7 +284062,7 @@ async function registerLocalSource(args) {
283886
284062
  });
283887
284063
  if (!response.ok) {
283888
284064
  const body = await response.text();
283889
- throw new import_errors11.AbloValidationError(
284065
+ throw new import_errors12.AbloValidationError(
283890
284066
  `Could not register the local Data Source (${response.status}): ${body}`,
283891
284067
  { code: "cli_invalid_arguments" }
283892
284068
  );
@@ -284063,7 +284239,7 @@ async function dev(argv, runtime = {}) {
284063
284239
  else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
284064
284240
  if (runtime.branch) args.planeLabel = runtime.branch.slug;
284065
284241
  if (args.local && !args.watch) {
284066
- throw new import_errors11.AbloValidationError(
284242
+ throw new import_errors12.AbloValidationError(
284067
284243
  `${import_picocolors15.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors15.default.bold("--no-watch")}.`,
284068
284244
  { code: "cli_invalid_arguments" }
284069
284245
  );
@@ -284214,7 +284390,7 @@ function parseBranchDevArgs(argv) {
284214
284390
  const arg = argv[index];
284215
284391
  if (!arg) continue;
284216
284392
  if (arg === "--no-branch") {
284217
- throw new import_errors12.AbloValidationError(
284393
+ throw new import_errors13.AbloValidationError(
284218
284394
  "--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
284219
284395
  { code: "cli_invalid_arguments" }
284220
284396
  );
@@ -284222,7 +284398,7 @@ function parseBranchDevArgs(argv) {
284222
284398
  if (arg === "--branch") {
284223
284399
  branchSlug = argv[++index];
284224
284400
  if (!branchSlug) {
284225
- throw new import_errors12.AbloValidationError("--branch requires a slug", {
284401
+ throw new import_errors13.AbloValidationError("--branch requires a slug", {
284226
284402
  code: "cli_invalid_arguments"
284227
284403
  });
284228
284404
  }
@@ -284231,7 +284407,7 @@ function parseBranchDevArgs(argv) {
284231
284407
  if (arg === "--branch-ttl-hours") {
284232
284408
  const value = Number(argv[++index]);
284233
284409
  if (!Number.isInteger(value) || value < 1 || value > 168) {
284234
- throw new import_errors12.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
284410
+ throw new import_errors13.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
284235
284411
  code: "cli_invalid_arguments"
284236
284412
  });
284237
284413
  }
@@ -284249,12 +284425,12 @@ function parseBranchDevArgs(argv) {
284249
284425
  function branchSlugFromRef(ref) {
284250
284426
  const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
284251
284427
  if (!base) {
284252
- throw new import_errors12.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
284428
+ throw new import_errors13.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
284253
284429
  code: "cli_invalid_arguments"
284254
284430
  });
284255
284431
  }
284256
284432
  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)}`;
284433
+ 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
284434
  return import_branches2.branchSlugSchema.parse(shortened);
284259
284435
  }
284260
284436
  function gitBranch() {
@@ -284271,7 +284447,7 @@ function gitBranch() {
284271
284447
  function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
284272
284448
  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
284449
  if (!value) {
284274
- throw new import_errors12.AbloValidationError(
284450
+ throw new import_errors13.AbloValidationError(
284275
284451
  "Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
284276
284452
  { code: "cli_invalid_arguments" }
284277
284453
  );
@@ -284289,13 +284465,13 @@ async function runBranchDev(argv, dependencies = {}) {
284289
284465
  const slug = branchSlugFromRef(ref);
284290
284466
  const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
284291
284467
  if (!managementKey) {
284292
- throw new import_errors12.AbloValidationError(
284468
+ throw new import_errors13.AbloValidationError(
284293
284469
  "Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY.",
284294
284470
  { code: "cli_invalid_arguments" }
284295
284471
  );
284296
284472
  }
284297
284473
  if (!managementKey.startsWith("mk_")) {
284298
- throw new import_errors12.AbloValidationError(
284474
+ throw new import_errors13.AbloValidationError(
284299
284475
  "Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
284300
284476
  { code: "cli_invalid_arguments" }
284301
284477
  );
@@ -284322,7 +284498,7 @@ async function runBranchDev(argv, dependencies = {}) {
284322
284498
  // src/whoami.ts
284323
284499
  init_cjs_shims();
284324
284500
  var import_picocolors16 = __toESM(require_picocolors(), 1);
284325
- var import_errors13 = require("@abloatai/transaction/errors");
284501
+ var import_errors14 = require("@abloatai/transaction/errors");
284326
284502
  init_config();
284327
284503
  init_controlPlane();
284328
284504
 
@@ -284397,7 +284573,7 @@ function parseWhoamiArgs(argv) {
284397
284573
  case "--key": {
284398
284574
  const value = argv[++i];
284399
284575
  if (!value || value.startsWith("--")) {
284400
- throw new import_errors13.AbloValidationError("`--key` needs a credential value.", {
284576
+ throw new import_errors14.AbloValidationError("`--key` needs a credential value.", {
284401
284577
  code: "cli_invalid_arguments"
284402
284578
  });
284403
284579
  }
@@ -284407,12 +284583,12 @@ function parseWhoamiArgs(argv) {
284407
284583
  case "--key-env": {
284408
284584
  const value = argv[++i];
284409
284585
  if (!value || value.startsWith("--")) {
284410
- throw new import_errors13.AbloValidationError("`--key-env` needs an environment variable name.", {
284586
+ throw new import_errors14.AbloValidationError("`--key-env` needs an environment variable name.", {
284411
284587
  code: "cli_invalid_arguments"
284412
284588
  });
284413
284589
  }
284414
284590
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
284415
- throw new import_errors13.AbloValidationError(
284591
+ throw new import_errors14.AbloValidationError(
284416
284592
  `\`${value}\` is not a valid environment variable name.`,
284417
284593
  { code: "cli_invalid_arguments" }
284418
284594
  );
@@ -284421,13 +284597,13 @@ function parseWhoamiArgs(argv) {
284421
284597
  break;
284422
284598
  }
284423
284599
  default:
284424
- throw new import_errors13.AbloValidationError(`unknown whoami flag: ${arg}`, {
284600
+ throw new import_errors14.AbloValidationError(`unknown whoami flag: ${arg}`, {
284425
284601
  code: "cli_invalid_arguments"
284426
284602
  });
284427
284603
  }
284428
284604
  }
284429
284605
  if (key && keyEnv) {
284430
- throw new import_errors13.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
284606
+ throw new import_errors14.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
284431
284607
  code: "cli_invalid_arguments"
284432
284608
  });
284433
284609
  }
@@ -284438,7 +284614,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
284438
284614
  if (args.keyEnv) {
284439
284615
  const found = readProjectEnvVariable(args.keyEnv, cwd);
284440
284616
  if (!found) {
284441
- throw new import_errors13.AbloAuthenticationError(
284617
+ throw new import_errors14.AbloAuthenticationError(
284442
284618
  `${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
284443
284619
  { code: "cli_api_key_missing" }
284444
284620
  );
@@ -284467,7 +284643,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
284467
284643
  };
284468
284644
  }
284469
284645
  const ambient = ambientEnvKeyNote();
284470
- throw new import_errors13.AbloAuthenticationError(
284646
+ throw new import_errors14.AbloAuthenticationError(
284471
284647
  `No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
284472
284648
 
284473
284649
  ${ambient}` : ""}`,
@@ -284485,7 +284661,7 @@ async function whoami(argv) {
284485
284661
  });
284486
284662
  const confirmed = target.confirmed;
284487
284663
  if (!confirmed) {
284488
- throw new import_errors13.AbloAuthenticationError(
284664
+ throw new import_errors14.AbloAuthenticationError(
284489
284665
  "The server did not confirm an identity for this credential.",
284490
284666
  { code: "identity_resolve_failed" }
284491
284667
  );
@@ -284820,12 +284996,12 @@ function fullRows(group) {
284820
284996
  }
284821
284997
 
284822
284998
  // src/index.ts
284823
- var import_errors21 = require("@abloatai/transaction/errors");
284999
+ var import_errors22 = require("@abloatai/transaction/errors");
284824
285000
  init_push();
284825
285001
 
284826
285002
  // src/generate.ts
284827
285003
  init_cjs_shims();
284828
- var import_errors14 = require("@abloatai/transaction/errors");
285004
+ var import_errors15 = require("@abloatai/transaction/errors");
284829
285005
  var import_fs8 = require("fs");
284830
285006
  var import_path6 = require("path");
284831
285007
  var import_picocolors17 = __toESM(require_picocolors(), 1);
@@ -284851,7 +285027,7 @@ function parseGenerateArgs(argv) {
284851
285027
  out = argv[++i] ?? out;
284852
285028
  break;
284853
285029
  default:
284854
- throw new import_errors14.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285030
+ throw new import_errors15.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
284855
285031
  }
284856
285032
  }
284857
285033
  return { schemaPath, exportName, out };
@@ -284884,7 +285060,7 @@ init_cjs_shims();
284884
285060
  var import_child_process2 = require("child_process");
284885
285061
  var import_picocolors18 = __toESM(require_picocolors(), 1);
284886
285062
  init_dist2();
284887
- var import_errors15 = require("@abloatai/transaction/errors");
285063
+ var import_errors16 = require("@abloatai/transaction/errors");
284888
285064
  var import_wire8 = require("@abloatai/transaction/wire");
284889
285065
  init_config();
284890
285066
  init_theme();
@@ -285018,7 +285194,7 @@ ${import_picocolors18.default.dim(url)}`, "Approve in your browser");
285018
285194
  }
285019
285195
  if (!provRes.ok) {
285020
285196
  s.stop("Could not provision a key.");
285021
- const err = (0, import_errors15.translateHttpError)(
285197
+ const err = (0, import_errors16.translateHttpError)(
285022
285198
  provRes.status,
285023
285199
  await provRes.json().catch(() => null),
285024
285200
  provRes.headers.get("x-request-id") ?? void 0
@@ -285582,7 +285758,7 @@ async function doctor() {
285582
285758
 
285583
285759
  // src/logs.ts
285584
285760
  init_cjs_shims();
285585
- var import_errors16 = require("@abloatai/transaction/errors");
285761
+ var import_errors17 = require("@abloatai/transaction/errors");
285586
285762
  var import_wire9 = require("@abloatai/transaction/wire");
285587
285763
  var import_picocolors21 = __toESM(require_picocolors(), 1);
285588
285764
  init_config();
@@ -285624,12 +285800,12 @@ function parseLogsArgs(argv) {
285624
285800
  args.json = true;
285625
285801
  break;
285626
285802
  case "--mode":
285627
- throw new import_errors16.AbloValidationError(
285803
+ throw new import_errors17.AbloValidationError(
285628
285804
  "--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
285629
285805
  { code: "cli_invalid_arguments" }
285630
285806
  );
285631
285807
  default:
285632
- throw new import_errors16.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285808
+ throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
285633
285809
  }
285634
285810
  }
285635
285811
  return args;
@@ -285908,7 +286084,7 @@ async function webhooks(argv) {
285908
286084
 
285909
286085
  // src/check.ts
285910
286086
  init_cjs_shims();
285911
- var import_errors17 = require("@abloatai/transaction/errors");
286087
+ var import_errors18 = require("@abloatai/transaction/errors");
285912
286088
  var import_picocolors23 = __toESM(require_picocolors(), 1);
285913
286089
  init_src();
285914
286090
  var import_schema9 = require("@abloatai/transaction/schema");
@@ -286056,7 +286232,7 @@ function parseCheckArgs(argv) {
286056
286232
  appSchema = argv[++i] ?? appSchema;
286057
286233
  break;
286058
286234
  default:
286059
- throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286235
+ throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286060
286236
  }
286061
286237
  }
286062
286238
  return { schemaPath, exportName, appSchema };
@@ -286222,9 +286398,9 @@ var ABLO_REACT = /* @__PURE__ */ new Set(["@abloatai/ablo/react", "@abloatai/hum
286222
286398
  function clientRoots(sf) {
286223
286399
  const roots = /* @__PURE__ */ new Set(["ablo", "sync"]);
286224
286400
  for (const decl of sf.getVariableDeclarations()) {
286225
- const init2 = decl.getInitializer();
286226
- if (!init2) continue;
286227
- const text = init2.getText();
286401
+ const init4 = decl.getInitializer();
286402
+ if (!init4) continue;
286403
+ const text = init4.getText();
286228
286404
  if (/^Ablo\s*\(/.test(text) || /^useAblo\s*\(\s*\)/.test(text)) {
286229
286405
  roots.add(decl.getName());
286230
286406
  }
@@ -286391,7 +286567,7 @@ async function upgrade(argv) {
286391
286567
 
286392
286568
  // src/pull.ts
286393
286569
  init_cjs_shims();
286394
- var import_errors18 = require("@abloatai/transaction/errors");
286570
+ var import_errors19 = require("@abloatai/transaction/errors");
286395
286571
  var import_picocolors25 = __toESM(require_picocolors(), 1);
286396
286572
  init_src();
286397
286573
  var import_fs10 = require("fs");
@@ -286420,7 +286596,7 @@ function parsePullArgs(argv) {
286420
286596
  force = true;
286421
286597
  break;
286422
286598
  default:
286423
- throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286599
+ throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286424
286600
  }
286425
286601
  }
286426
286602
  return { out, appSchema, importPath, force };
@@ -286538,7 +286714,7 @@ async function pull(argv) {
286538
286714
 
286539
286715
  // src/prismaPull.ts
286540
286716
  init_cjs_shims();
286541
- var import_errors19 = require("@abloatai/transaction/errors");
286717
+ var import_errors20 = require("@abloatai/transaction/errors");
286542
286718
  var import_picocolors26 = __toESM(require_picocolors(), 1);
286543
286719
  var import_fs11 = require("fs");
286544
286720
  init_theme();
@@ -286736,7 +286912,7 @@ function parsePrismaPullArgs(argv) {
286736
286912
  force = true;
286737
286913
  break;
286738
286914
  default:
286739
- if (arg.startsWith("--")) throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286915
+ if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286740
286916
  schema = arg;
286741
286917
  }
286742
286918
  }
@@ -286796,7 +286972,7 @@ async function prismaPull(argv) {
286796
286972
  // src/drizzlePull.ts
286797
286973
  init_cjs_shims();
286798
286974
  var import_picocolors27 = __toESM(require_picocolors(), 1);
286799
- var import_errors20 = require("@abloatai/transaction/errors");
286975
+ var import_errors21 = require("@abloatai/transaction/errors");
286800
286976
  var import_fs12 = require("fs");
286801
286977
  var import_path7 = require("path");
286802
286978
  init_theme();
@@ -286903,7 +287079,7 @@ function parseDrizzlePullArgs(argv) {
286903
287079
  force = true;
286904
287080
  break;
286905
287081
  default:
286906
- if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
287082
+ if (arg.startsWith("--")) throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
286907
287083
  schema = arg;
286908
287084
  }
286909
287085
  }
@@ -286975,6 +287151,7 @@ async function drizzlePull(argv) {
286975
287151
  // src/index.ts
286976
287152
  init_theme();
286977
287153
  init_renderError();
287154
+ init_observeCliError();
286978
287155
 
286979
287156
  // src/generators/authScaffold.ts
286980
287157
  init_cjs_shims();
@@ -287056,7 +287233,7 @@ var LOGO = `
287056
287233
  ${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}
287057
287234
  `;
287058
287235
  var HANDLERS = {
287059
- init: (argv) => init([...argv]),
287236
+ init: (argv) => init3([...argv]),
287060
287237
  login: (argv) => login([...argv]),
287061
287238
  logout: () => logout(),
287062
287239
  projects: (argv) => projects([...argv]),
@@ -287109,7 +287286,7 @@ async function main() {
287109
287286
  const argv = process.argv.slice(3);
287110
287287
  if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
287111
287288
  const suggestion = suggestCommand(raw);
287112
- throw new import_errors21.AbloValidationError(
287289
+ throw new import_errors22.AbloValidationError(
287113
287290
  `\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
287114
287291
  { code: "cli_invalid_arguments" }
287115
287292
  );
@@ -287253,7 +287430,7 @@ async function chooseBool(flagValue, fallback, interactive, prompt) {
287253
287430
  bailIfCancelled(value);
287254
287431
  return value;
287255
287432
  }
287256
- async function init(args = []) {
287433
+ async function init3(args = []) {
287257
287434
  const opts = parseInitArgs(args);
287258
287435
  const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
287259
287436
  Ie(`${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}`);
@@ -287786,8 +287963,17 @@ function detectPackageManager() {
287786
287963
  if ((0, import_fs13.existsSync)("bun.lockb")) return "bun";
287787
287964
  return "npm";
287788
287965
  }
287789
- main().catch((err) => {
287966
+ installCliExitObservationBoundary();
287967
+ main().catch(async (err) => {
287968
+ if (err instanceof CliFailureExit) {
287969
+ observeCliError(err);
287970
+ await flushCliErrors();
287971
+ restoreCliExitObservationBoundary();
287972
+ process.exit(err.exitCode);
287973
+ }
287790
287974
  renderCliError(err);
287975
+ await flushCliErrors();
287976
+ restoreCliExitObservationBoundary();
287791
287977
  process.exit(process.exitCode ?? 1);
287792
287978
  });
287793
287979
  /*! Bundled license information: