@abloatai/cli 0.55.0 → 0.57.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 +130 -54
  2. package/package.json +3 -3
package/dist/cli.cjs CHANGED
@@ -3970,7 +3970,7 @@ var init_observeCliError = __esm({
3970
3970
  import_errorObservation = require("@abloatai/transaction/errorObservation");
3971
3971
  import_errors5 = require("@abloatai/transaction/errors");
3972
3972
  dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
3973
- release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.55.0";
3973
+ release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.57.0";
3974
3974
  initialized = false;
3975
3975
  nativeProcessExit = process.exit.bind(process);
3976
3976
  exitBoundaryInstalled = false;
@@ -4297,7 +4297,7 @@ var init_src2 = __esm({
4297
4297
 
4298
4298
  // src/cliEnvironment.ts
4299
4299
  function cliVersion() {
4300
- return "0.55.0";
4300
+ return "0.57.0";
4301
4301
  }
4302
4302
  function cliOs() {
4303
4303
  const value = (0, import_node_os.platform)();
@@ -4372,7 +4372,9 @@ function trackCliSchemaPushAttempted() {
4372
4372
  }
4373
4373
  function flushProductAnalytics(options = {}) {
4374
4374
  if (flushInFlight) return flushInFlight;
4375
- flushInFlight = flushOnce(options).catch(() => void 0).finally(() => {
4375
+ flushInFlight = flushOnce(options).catch((error) => {
4376
+ void error;
4377
+ }).finally(() => {
4376
4378
  flushInFlight = null;
4377
4379
  });
4378
4380
  return flushInFlight;
@@ -4395,8 +4397,8 @@ function queueEvent(eventName, properties) {
4395
4397
  state.queue = [...state.queue, parsed].slice(-MAX_QUEUED_EVENTS);
4396
4398
  writeState(state);
4397
4399
  if (disclose) {
4398
- console.error(
4399
- "Ablo collects limited usage analytics. Run `ablo telemetry disable` to opt out or `ablo telemetry status` for details."
4400
+ process.stderr.write(
4401
+ "Ablo collects limited usage analytics. Run `ablo telemetry disable` to opt out or `ablo telemetry status` for details.\n"
4400
4402
  );
4401
4403
  }
4402
4404
  } catch {
@@ -4473,8 +4475,9 @@ function writeState(state) {
4473
4475
  function environmentBlocker() {
4474
4476
  if (process.env.ABLO_TELEMETRY_DISABLED === "1") return "ABLO_TELEMETRY_DISABLED";
4475
4477
  if (process.env.DO_NOT_TRACK === "1") return "DO_NOT_TRACK";
4476
- const ciVariables = ["CI", "GITHUB_ACTIONS", "GITLAB_CI", "BUILDKITE", "CIRCLECI", "TF_BUILD"];
4477
- return ciVariables.find((name) => truthyEnvironmentValue(process.env[name])) ?? null;
4478
+ return TELEMETRY_BLOCKING_ENV.slice(2).find(
4479
+ (name) => truthyEnvironmentValue(process.env[name])
4480
+ ) ?? null;
4478
4481
  }
4479
4482
  function truthyEnvironmentValue(value) {
4480
4483
  return value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
@@ -4502,7 +4505,7 @@ function runTelemetryCommand(argv) {
4502
4505
  if (status2.blockedBy) console.log(`Environment override: ${status2.blockedBy}`);
4503
4506
  console.log(`Queued events: ${status2.queuedEvents}`);
4504
4507
  }
4505
- var import_node_crypto2, import_node_fs, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight;
4508
+ var import_node_crypto2, import_node_fs, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight, TELEMETRY_BLOCKING_ENV;
4506
4509
  var init_telemetry = __esm({
4507
4510
  "src/telemetry.ts"() {
4508
4511
  "use strict";
@@ -4519,6 +4522,16 @@ var init_telemetry = __esm({
4519
4522
  MAX_FLUSH_EVENTS = 20;
4520
4523
  DEFAULT_FLUSH_TIMEOUT_MS = 800;
4521
4524
  flushInFlight = null;
4525
+ TELEMETRY_BLOCKING_ENV = [
4526
+ "ABLO_TELEMETRY_DISABLED",
4527
+ "DO_NOT_TRACK",
4528
+ "CI",
4529
+ "GITHUB_ACTIONS",
4530
+ "GITLAB_CI",
4531
+ "BUILDKITE",
4532
+ "CIRCLECI",
4533
+ "TF_BUILD"
4534
+ ];
4522
4535
  }
4523
4536
  });
4524
4537
 
@@ -284792,21 +284805,14 @@ function classifyKey(apiKey) {
284792
284805
  reason: `${import_picocolors16.default.bold("ABLO_API_KEY")} is not a secret Ablo key. Expected a branch-bound ${import_picocolors16.default.bold("sk_\u2026")} credential. Run ${import_picocolors16.default.bold("npx ablo dev")} to prepare a development branch.`
284793
284806
  };
284794
284807
  }
284795
- function wireEnvLocal(apiKey, cwd = process.cwd(), projectId, branchId) {
284808
+ function wireEnvLocal(apiKey, cwd = process.cwd()) {
284796
284809
  const envPath = (0, import_path5.resolve)(cwd, ".env.local");
284797
284810
  const line = `ABLO_API_KEY=${apiKey}`;
284798
- const projectLine = projectId ? `ABLO_PROJECT_ID=${projectId}` : null;
284799
- const branchLine = branchId ? `ABLO_BRANCH_ID=${branchId}` : null;
284800
284811
  let action;
284812
+ let removedPins = [];
284801
284813
  if (!(0, import_fs7.existsSync)(envPath)) {
284802
- (0, import_fs7.writeFileSync)(
284803
- envPath,
284804
- `${line}
284805
- ${projectLine ? `${projectLine}
284806
- ` : ""}${branchLine ? `${branchLine}
284807
- ` : ""}`,
284808
- { mode: 384 }
284809
- );
284814
+ (0, import_fs7.writeFileSync)(envPath, `${line}
284815
+ `, { mode: 384 });
284810
284816
  action = `Created ${import_picocolors16.default.bold(".env.local")} with ${import_picocolors16.default.bold("ABLO_API_KEY")}`;
284811
284817
  } else {
284812
284818
  const content = (0, import_fs7.readFileSync)(envPath, "utf8");
@@ -284822,25 +284828,16 @@ ${projectLine ? `${projectLine}
284822
284828
  (0, import_fs7.writeFileSync)(envPath, content.replace(/^ABLO_API_KEY=.*$/m, line));
284823
284829
  action = `Updated ${import_picocolors16.default.bold("ABLO_API_KEY")} in ${import_picocolors16.default.bold(".env.local")} ${import_picocolors16.default.dim(`(was ${existing.slice(0, 12)}\u2026)`)}`;
284824
284830
  }
284825
- if (projectLine) {
284826
- const next = (0, import_fs7.readFileSync)(envPath, "utf8");
284827
- if (/^ABLO_PROJECT_ID=.*$/m.test(next)) {
284828
- (0, import_fs7.writeFileSync)(envPath, next.replace(/^ABLO_PROJECT_ID=.*$/m, projectLine));
284829
- } else {
284830
- (0, import_fs7.appendFileSync)(envPath, `${next.endsWith("\n") || next.length === 0 ? "" : "\n"}${projectLine}
284831
- `);
284832
- }
284833
- }
284834
- if (branchLine) {
284835
- const next = (0, import_fs7.readFileSync)(envPath, "utf8");
284836
- if (/^ABLO_BRANCH_ID=.*$/m.test(next)) {
284837
- (0, import_fs7.writeFileSync)(envPath, next.replace(/^ABLO_BRANCH_ID=.*$/m, branchLine));
284838
- } else {
284839
- (0, import_fs7.appendFileSync)(envPath, `${next.endsWith("\n") || next.length === 0 ? "" : "\n"}${branchLine}
284840
- `);
284841
- }
284831
+ const before = (0, import_fs7.readFileSync)(envPath, "utf8");
284832
+ const after = before.replace(/^ABLO_(?:PROJECT|BRANCH)_ID=.*\n?/gm, "");
284833
+ if (after !== before) {
284834
+ removedPins = ["ABLO_PROJECT_ID", "ABLO_BRANCH_ID"].filter(
284835
+ (key) => new RegExp(`^${key}=`, "m").test(before)
284836
+ );
284837
+ (0, import_fs7.writeFileSync)(envPath, after);
284842
284838
  }
284843
284839
  }
284840
+ const pinNote = removedPins.length ? ` Removed ${removedPins.map((key) => import_picocolors16.default.bold(key)).join(" and ")}; the key names its own project and branch.` : "";
284844
284841
  const gitignorePath = (0, import_path5.resolve)(cwd, ".gitignore");
284845
284842
  const gitignore = (0, import_fs7.existsSync)(gitignorePath) ? (0, import_fs7.readFileSync)(gitignorePath, "utf8") : "";
284846
284843
  const ignored = /^(\.env\.local|\.env\*|\.env\.\*|\.env.*)$/m.test(gitignore);
@@ -284854,7 +284851,7 @@ ${projectLine ? `${projectLine}
284854
284851
  );
284855
284852
  gitignoreNote = ` Added ${import_picocolors16.default.bold(".env.local")} to ${import_picocolors16.default.bold(".gitignore")} so the key can't be committed.`;
284856
284853
  }
284857
- return `${action}.${gitignoreNote}`;
284854
+ return `${action}.${pinNote}${gitignoreNote}`;
284858
284855
  }
284859
284856
  async function runPush(schema, args) {
284860
284857
  const { ok, status: status2, body, bodyText } = await pushSchema(schema, {
@@ -285015,7 +285012,7 @@ async function dev(argv, runtime = {}) {
285015
285012
  if (runtime.branch) {
285016
285013
  console.log(
285017
285014
  `
285018
- ${import_picocolors16.default.green("\u2713")} ${wireEnvLocal(args.apiKey, process.cwd(), runtime.branch.projectId, runtime.branch.id)}`
285015
+ ${import_picocolors16.default.green("\u2713")} ${wireEnvLocal(args.apiKey, process.cwd())}`
285019
285016
  );
285020
285017
  console.log(
285021
285018
  ` ${import_picocolors16.default.dim(`Temporary branch credential expires ${runtime.branch.expiresAt}; rerun ablo dev to rotate it.`)}`
@@ -285446,6 +285443,10 @@ init_controlPlane();
285446
285443
  init_config();
285447
285444
  init_target();
285448
285445
  init_readiness();
285446
+ function doctorVerdict(counts) {
285447
+ if (counts.blockers > 0 || counts.failed > 0) return "blocked";
285448
+ return counts.skipped > 0 ? "unverified" : "ready";
285449
+ }
285449
285450
  function render(check2) {
285450
285451
  const mark = check2.state === "ok" ? import_picocolors18.default.green("\u2713") : check2.state === "fail" ? import_picocolors18.default.red("\u2717") : import_picocolors18.default.dim("\u2013");
285451
285452
  console.log(
@@ -285607,7 +285608,15 @@ async function inspectDoctor(options = {}) {
285607
285608
  if (delivery.kind === "known") {
285608
285609
  const when = windowWords(delivery.window_seconds);
285609
285610
  checks.push(
285610
- delivery.unroutable > 0 ? {
285611
+ delivery.unroutable > 0 ? delivery.unroutable === delivery.recorded ? {
285612
+ // Nothing at all was routable. One bad row does not look like
285613
+ // this, so the cause is the plane rather than the rows: reporting
285614
+ // it as "N of N" would send the reader hunting for the N.
285615
+ label: "delivery",
285616
+ state: "fail",
285617
+ detail: `no change reached anyone (${delivery.recorded} in ${when})`,
285618
+ fix: "run `ablo check`. When nothing routes, the tenancy value is usually missing for the whole plane rather than for particular rows."
285619
+ } : {
285611
285620
  label: "delivery",
285612
285621
  state: "fail",
285613
285622
  detail: `${delivery.unroutable} of ${delivery.recorded} change${delivery.recorded === 1 ? "" : "s"} in ${when} reached nobody` + (delivery.sample ? ` (e.g. ${delivery.sample.model}/${delivery.sample.id})` : ""),
@@ -285642,7 +285651,8 @@ async function inspectDoctor(options = {}) {
285642
285651
  dataSource,
285643
285652
  pushedSchema: pushed,
285644
285653
  schemaDrift: drift,
285645
- delivery
285654
+ delivery,
285655
+ verdict: doctorVerdict({ blockers: blocking.length, failed, skipped })
285646
285656
  };
285647
285657
  }
285648
285658
  function renderDoctorReport(report) {
@@ -285660,7 +285670,7 @@ function renderDoctorReport(report) {
285660
285670
  );
285661
285671
  } else if (report.skipped > 0) {
285662
285672
  console.log(
285663
- ` ${import_picocolors18.default.yellow("?")} ${import_picocolors18.default.dim(`nothing is blocking a write, but ${report.skipped} check${report.skipped === 1 ? "" : "s"} could not be run`)}`
285673
+ ` ${import_picocolors18.default.yellow("?")} ${import_picocolors18.default.dim(`nothing found a problem, but ${report.skipped} check${report.skipped === 1 ? "" : "s"} could not be run. This is not a clean bill of health.`)}`
285664
285674
  );
285665
285675
  } else {
285666
285676
  console.log(
@@ -285669,10 +285679,26 @@ function renderDoctorReport(report) {
285669
285679
  }
285670
285680
  console.log();
285671
285681
  }
285672
- async function doctor() {
285682
+ function doctorReportAsJson(report) {
285683
+ return JSON.stringify(
285684
+ {
285685
+ object: "doctor_report",
285686
+ verdict: report.verdict,
285687
+ checks: report.checks,
285688
+ blockers: report.blockers
285689
+ },
285690
+ null,
285691
+ 2
285692
+ );
285693
+ }
285694
+ async function doctor(argv = []) {
285673
285695
  const report = await inspectDoctor();
285674
- renderDoctorReport(report);
285675
- if (!report.ready) process.exitCode = 1;
285696
+ if (argv.includes("--json") || process.env.ABLO_JSON === "1") {
285697
+ console.log(doctorReportAsJson(report));
285698
+ } else {
285699
+ renderDoctorReport(report);
285700
+ }
285701
+ if (report.verdict !== "ready") process.exitCode = 1;
285676
285702
  }
285677
285703
 
285678
285704
  // src/setup/contracts.ts
@@ -287508,7 +287534,10 @@ var COMMANDS = [
287508
287534
  core: { group: "Every day", does: "Check the whole setup at once and list everything that would block a write" },
287509
287535
  full: {
287510
287536
  group: "See what's happening",
287511
- rows: [{ run: "doctor", does: "Every setup check at once \u2014 exits non-zero when a write would fail" }]
287537
+ rows: [
287538
+ { run: "doctor", does: "Every setup check at once. Exits non-zero when a write would fail, or when a check could not be run" },
287539
+ { run: "doctor --json", does: "The same verdict as data, for a script or an agent" }
287540
+ ]
287512
287541
  }
287513
287542
  },
287514
287543
  {
@@ -288751,6 +288780,9 @@ async function check(argv) {
288751
288780
  }
288752
288781
  const schema = await loadSchema(args.schemaPath, args.exportName);
288753
288782
  const schemaJson = JSON.parse((0, import_schema9.serializeSchema)(schema));
288783
+ const accessFindings = new Map(
288784
+ (0, import_schema9.auditSchemaAccessPolicies)(schemaJson).map((finding) => [finding.model, finding])
288785
+ );
288754
288786
  console.log(`
288755
288787
  ${brand("ablo")} ${import_picocolors25.default.dim("check")} ${import_picocolors25.default.dim(`schema "${args.appSchema}"`)}
288756
288788
  `);
@@ -288791,6 +288823,12 @@ async function check(argv) {
288791
288823
  }
288792
288824
  const problems = [];
288793
288825
  const warns = [];
288826
+ const accessFinding = accessFindings.get(key);
288827
+ if (accessFinding) {
288828
+ problems.push(
288829
+ `[${accessFinding.code}] ${accessFinding.message} Fix: ${accessFinding.fix}`
288830
+ );
288831
+ }
288794
288832
  if (!present.has("id")) problems.push('missing primary key "id"');
288795
288833
  const orgCol = (0, import_schema9.tenancyColumn)((0, import_schema9.resolveTenancy)(model));
288796
288834
  if (orgCol && !present.has(orgCol)) {
@@ -289735,8 +289773,21 @@ export async function POST(request: Request): Promise<Response> {
289735
289773
  );
289736
289774
  }
289737
289775
 
289776
+ const authorizedScope = await authorizeActiveWorkspace(user.id);
289777
+ if (!authorizedScope) {
289778
+ return Response.json(
289779
+ credentialEndpointErrorSchema.parse({
289780
+ error: { code: 'policy_denied', message: 'Workspace membership is stale or revoked' },
289781
+ }),
289782
+ { status: 403, headers: noStore },
289783
+ );
289784
+ }
289785
+
289738
289786
  const { token, expiresAt } = await sync.sessions.create({
289739
289787
  user: { id: user.id },
289788
+ // These ids came from the server-side membership lookup below. Never take
289789
+ // organization, workspace, team, or group ids from the request body.
289790
+ syncGroups: authorizedScope.syncGroups,
289740
289791
  can: { records: ['read', 'create', 'update'] },
289741
289792
  });
289742
289793
  return Response.json(
@@ -289760,6 +289811,27 @@ async function getCurrentUser(): Promise<{ id: string } | null> {
289760
289811
  const session = await auth.api.getSession({ headers: await headers() });
289761
289812
  return session?.user ? { id: session.user.id } : null;
289762
289813
  }
289814
+
289815
+ type AuthorizedWorkspace = {
289816
+ workspaceId: string;
289817
+ syncGroups: readonly [\`workspace:\${string}\`, ...\`\${string}:\${string}\`[]];
289818
+ };
289819
+
289820
+ async function authorizeActiveWorkspace(userId: string): Promise<AuthorizedWorkspace | null> {
289821
+ void userId;
289822
+ // REQUIRED: query your membership table here, immediately before minting.
289823
+ // Read the active workspace from the server-side session, verify this user has
289824
+ // an active membership, and derive every team/group id on the server. Return
289825
+ // null for a stale or revoked membership. This refusal keeps a newly generated
289826
+ // route from turning "signed in" into workspace authorization by accident.
289827
+ //
289828
+ // Example after your membership query:
289829
+ // return {
289830
+ // workspaceId: membership.workspaceId,
289831
+ // syncGroups: [\`workspace:\${membership.workspaceId}\`],
289832
+ // };
289833
+ return null;
289834
+ }
289763
289835
  `;
289764
289836
  }
289765
289837
 
@@ -289792,7 +289864,7 @@ export const schema = defineSchema({
289792
289864
  });
289793
289865
  `;
289794
289866
  }
289795
- function generateSyncConfig(auth) {
289867
+ function generateSyncConfig(auth, options = {}) {
289796
289868
  const authLine = auth === "apikey" ? "" : auth === "firebase" ? `
289797
289869
  auth: async () => {
289798
289870
  const { getAuth } = await import('firebase/auth');
@@ -289804,7 +289876,7 @@ function generateSyncConfig(auth) {
289804
289876
  // auth: async () => { const { data } = await supabase.auth.getSession(); return data.session?.access_token ?? ''; },` : auth === "betterauth" ? `
289805
289877
  // auth: async () => { const session = await authClient.getSession(); return session?.token ?? ''; },` : `
289806
289878
  // auth: () => 'your-jwt-token', // replace with your auth provider`;
289807
- return `import Ablo from '@abloatai/ablo';
289879
+ return `${options.serverOnly ? "import 'server-only';\n\n" : ""}import Ablo from '@abloatai/ablo';
289808
289880
  import { schema } from './schema';
289809
289881
 
289810
289882
  // SERVER-ONLY client \u2014 it holds your \`sk_\` key. Use it from server code: the
@@ -289813,8 +289885,6 @@ import { schema } from './schema';
289813
289885
  // via the session route and never touches the key.
289814
289886
  export const sync = Ablo({
289815
289887
  apiKey: process.env.ABLO_API_KEY,${authLine}
289816
- workspaceId: process.env.ABLO_PROJECT_ID,
289817
- branchId: process.env.ABLO_BRANCH_ID,
289818
289888
  schema,
289819
289889
  });
289820
289890
 
@@ -289840,7 +289910,7 @@ function generateEnv(storage, opts = {}) {
289840
289910
  const { includeApiKey = true } = opts;
289841
289911
  const databaseBlock = storage === "replication" ? "# Used by `npx ablo connect` to set up + register logical replication \u2014 the\n# DIRECT (un-pooled) endpoint. Ablo TAILS your WAL from here; it never writes.\n# The client never sees it; the browser never sees it. Your DB stays yours.\nDATABASE_URL=postgres://user:password@host:5432/db\n" : "# Used by ablo/data-source.ts (your DB endpoint) + `ablo migrate` \u2014 NOT the client.\n# Ablo never sees it; the browser never sees it. Your DB stays in your app.\nDATABASE_URL=postgres://user:password@host:5432/db\n";
289842
289912
  const webhookBlock = storage === "endpoint" ? "# Signing secret for the webhook receiver (app/api/ablo/webhooks/route.ts).\n# Ablo mints this when you register the endpoint's URL (POST /v1/webhook_endpoints\n# or the dashboard) and returns it once \u2014 paste it here.\nABLO_WEBHOOK_SECRET=whsec_your_endpoint_secret_here\n" : "";
289843
- const apiKeyBlock = includeApiKey ? "# Ablo: a branch-bound sk_ key (`npx ablo dev` wires both values for you).\n# Project + branch are assertions: the SDK rejects a key for another app or environment.\nABLO_API_KEY=sk_your_key_here\nABLO_PROJECT_ID=proj_your_project_id\nABLO_BRANCH_ID=br_your_branch_id\n" : "";
289913
+ const apiKeyBlock = includeApiKey ? "# Ablo: a branch-bound sk_ key (`npx ablo dev` writes it for you).\n# The key names its own project and branch, so nothing else is needed here.\nABLO_API_KEY=sk_your_key_here\n" : "";
289844
289914
  return `${apiKeyBlock}${webhookBlock}${databaseBlock}`;
289845
289915
  }
289846
289916
  function generateDataSource(orm) {
@@ -289968,7 +290038,10 @@ export async function POST(req: Request): Promise<Response> {
289968
290038
  const model: unknown = Reflect.get(prisma, event.model); // prisma.record, prisma.task, \u2026
289969
290039
  if (!isModelDelegate(model)) continue; // a model you don't mirror locally \u2014 skip it
289970
290040
  if (event.data === null) {
289971
- await model.delete({ where: { id: event.objectId } }).catch(() => {}); // already gone
290041
+ await model.delete({ where: { id: event.objectId } }).catch((error) => {
290042
+ // Idempotent replay: a missing local row is already the desired state.
290043
+ void error;
290044
+ });
289972
290045
  } else {
289973
290046
  await model.upsert({ where: { id: event.objectId }, create: event.data, update: event.data });
289974
290047
  }
@@ -290048,7 +290121,7 @@ async function main() {
290048
290121
  main().catch((err) => {
290049
290122
  // Ablo errors stringify to one clean line (code + message + docs link),
290050
290123
  // never a stack/object dump \u2014 see AbloError.toString().
290051
- console.error(String(err));
290124
+ process.stderr.write(String(err) + '\\n');
290052
290125
  process.exit(1);
290053
290126
  });
290054
290127
  `;
@@ -290399,7 +290472,10 @@ async function runInit(args = []) {
290399
290472
  }
290400
290473
  }
290401
290474
  files.push({ path: (0, import_node_path5.join)(abloDir, "schema.ts"), content: schemaSource, note: schemaNote });
290402
- files.push({ path: (0, import_node_path5.join)(abloDir, "index.ts"), content: generateSyncConfig(auth) });
290475
+ files.push({
290476
+ path: (0, import_node_path5.join)(abloDir, "index.ts"),
290477
+ content: generateSyncConfig(auth, { serverOnly: framework === "nextjs" })
290478
+ });
290403
290479
  files.push({ path: (0, import_node_path5.join)(abloDir, "register.ts"), content: generateRegister() });
290404
290480
  const orm = detectOrm(opts.orm);
290405
290481
  if (storage === "endpoint") {
@@ -290531,7 +290607,7 @@ var HANDLERS = {
290531
290607
  branch: (argv) => branches([...argv]),
290532
290608
  status: (argv) => status([...argv]),
290533
290609
  whoami: (argv) => whoami([...argv]),
290534
- doctor: () => doctor(),
290610
+ doctor: (argv) => doctor([...argv]),
290535
290611
  logs: (argv) => logs([...argv]),
290536
290612
  webhooks: (argv) => webhooks([...argv]),
290537
290613
  check: (argv) => check([...argv]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/cli",
3
- "version": "0.55.0",
3
+ "version": "0.57.0",
4
4
  "description": "The ablo command line: set up Ablo, connect your database, and push your schema from the terminal.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -35,10 +35,10 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@sentry/node": "^10.18.0",
38
- "@abloatai/transaction": "^0.55.0",
38
+ "@abloatai/transaction": "^0.57.0",
39
39
  "jiti": "^2.7.0",
40
40
  "zod": "^4.4.3",
41
- "@abloatai/humans": "^0.55.0"
41
+ "@abloatai/humans": "^0.57.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@ablo/product-analytics": "file:../product-analytics",