@abloatai/cli 0.60.0 → 0.61.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.
- package/dist/cli.cjs +425 -87
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -3976,7 +3976,7 @@ var init_observeCliError = __esm({
|
|
|
3976
3976
|
import_errorObservation = require("@abloatai/transaction/errorObservation");
|
|
3977
3977
|
import_errors5 = require("@abloatai/transaction/errors");
|
|
3978
3978
|
dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
|
|
3979
|
-
release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.
|
|
3979
|
+
release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.61.0";
|
|
3980
3980
|
initialized = false;
|
|
3981
3981
|
nativeProcessExit = process.exit.bind(process);
|
|
3982
3982
|
exitBoundaryInstalled = false;
|
|
@@ -4311,7 +4311,7 @@ var init_src2 = __esm({
|
|
|
4311
4311
|
|
|
4312
4312
|
// src/cliEnvironment.ts
|
|
4313
4313
|
function cliVersion() {
|
|
4314
|
-
return "0.
|
|
4314
|
+
return "0.61.0";
|
|
4315
4315
|
}
|
|
4316
4316
|
function cliOs() {
|
|
4317
4317
|
const value = (0, import_node_os.platform)();
|
|
@@ -5368,6 +5368,210 @@ var init_dbProvider = __esm({
|
|
|
5368
5368
|
}
|
|
5369
5369
|
});
|
|
5370
5370
|
|
|
5371
|
+
// src/connect/inspect.ts
|
|
5372
|
+
function inspectRegisteredConnection(validation) {
|
|
5373
|
+
if (!validation.ok) {
|
|
5374
|
+
return {
|
|
5375
|
+
object: "database_connection_reconcile",
|
|
5376
|
+
code: "operator_action_required",
|
|
5377
|
+
steps: {
|
|
5378
|
+
database: "pending",
|
|
5379
|
+
registration: "unchanged",
|
|
5380
|
+
snapshot: "pending",
|
|
5381
|
+
readiness: "action_required"
|
|
5382
|
+
},
|
|
5383
|
+
repairItems: [],
|
|
5384
|
+
needsDatabaseReconcile: false,
|
|
5385
|
+
needsSnapshotRequest: false,
|
|
5386
|
+
detail: validation.code ?? validation.message
|
|
5387
|
+
};
|
|
5388
|
+
}
|
|
5389
|
+
if (!validation.reachable) {
|
|
5390
|
+
return {
|
|
5391
|
+
object: "database_connection_reconcile",
|
|
5392
|
+
code: "operator_action_required",
|
|
5393
|
+
steps: {
|
|
5394
|
+
database: "action_required",
|
|
5395
|
+
registration: "unchanged",
|
|
5396
|
+
snapshot: "pending",
|
|
5397
|
+
readiness: "action_required"
|
|
5398
|
+
},
|
|
5399
|
+
repairItems: [],
|
|
5400
|
+
needsDatabaseReconcile: false,
|
|
5401
|
+
needsSnapshotRequest: false,
|
|
5402
|
+
detail: validation.reason ?? "source_unreachable"
|
|
5403
|
+
};
|
|
5404
|
+
}
|
|
5405
|
+
if (validation.failures.length > 0) {
|
|
5406
|
+
const repairItems = [...new Set(validation.failures.map((failure) => failure.item))].sort();
|
|
5407
|
+
const operatorItems = repairItems.filter((item) => !DATABASE_RECONCILABLE_ITEMS.has(item));
|
|
5408
|
+
if (operatorItems.length > 0) {
|
|
5409
|
+
return {
|
|
5410
|
+
object: "database_connection_reconcile",
|
|
5411
|
+
code: "operator_action_required",
|
|
5412
|
+
steps: {
|
|
5413
|
+
database: "action_required",
|
|
5414
|
+
registration: "unchanged",
|
|
5415
|
+
snapshot: "pending",
|
|
5416
|
+
readiness: "action_required"
|
|
5417
|
+
},
|
|
5418
|
+
repairItems,
|
|
5419
|
+
needsDatabaseReconcile: false,
|
|
5420
|
+
needsSnapshotRequest: false,
|
|
5421
|
+
detail: operatorItems.join(",")
|
|
5422
|
+
};
|
|
5423
|
+
}
|
|
5424
|
+
return {
|
|
5425
|
+
object: "database_connection_reconcile",
|
|
5426
|
+
code: "reconciling",
|
|
5427
|
+
steps: {
|
|
5428
|
+
database: "pending",
|
|
5429
|
+
registration: "unchanged",
|
|
5430
|
+
snapshot: "pending",
|
|
5431
|
+
readiness: "pending"
|
|
5432
|
+
},
|
|
5433
|
+
repairItems,
|
|
5434
|
+
needsDatabaseReconcile: true,
|
|
5435
|
+
needsSnapshotRequest: repairItems.some((item) => SNAPSHOT_SENSITIVE_ITEMS.has(item)) || validation.initialSnapshot?.status === "retrying"
|
|
5436
|
+
};
|
|
5437
|
+
}
|
|
5438
|
+
if (validation.initialSnapshot?.status === "retrying") {
|
|
5439
|
+
return {
|
|
5440
|
+
object: "database_connection_reconcile",
|
|
5441
|
+
code: "reconciling",
|
|
5442
|
+
steps: {
|
|
5443
|
+
database: "unchanged",
|
|
5444
|
+
registration: "unchanged",
|
|
5445
|
+
snapshot: "pending",
|
|
5446
|
+
readiness: "pending"
|
|
5447
|
+
},
|
|
5448
|
+
repairItems: [],
|
|
5449
|
+
needsDatabaseReconcile: false,
|
|
5450
|
+
needsSnapshotRequest: true,
|
|
5451
|
+
...validation.initialSnapshot.detail ? { detail: validation.initialSnapshot.detail } : {}
|
|
5452
|
+
};
|
|
5453
|
+
}
|
|
5454
|
+
if (validation.initialSnapshot?.status === "loading") {
|
|
5455
|
+
return {
|
|
5456
|
+
object: "database_connection_reconcile",
|
|
5457
|
+
code: "loading",
|
|
5458
|
+
steps: {
|
|
5459
|
+
database: "unchanged",
|
|
5460
|
+
registration: "unchanged",
|
|
5461
|
+
snapshot: "loading",
|
|
5462
|
+
readiness: "pending"
|
|
5463
|
+
},
|
|
5464
|
+
repairItems: [],
|
|
5465
|
+
needsDatabaseReconcile: false,
|
|
5466
|
+
needsSnapshotRequest: false
|
|
5467
|
+
};
|
|
5468
|
+
}
|
|
5469
|
+
if (validation.ready) {
|
|
5470
|
+
return {
|
|
5471
|
+
object: "database_connection_reconcile",
|
|
5472
|
+
code: "ready",
|
|
5473
|
+
steps: {
|
|
5474
|
+
database: "unchanged",
|
|
5475
|
+
registration: "unchanged",
|
|
5476
|
+
snapshot: "ready",
|
|
5477
|
+
readiness: "ready"
|
|
5478
|
+
},
|
|
5479
|
+
repairItems: [],
|
|
5480
|
+
needsDatabaseReconcile: false,
|
|
5481
|
+
needsSnapshotRequest: false
|
|
5482
|
+
};
|
|
5483
|
+
}
|
|
5484
|
+
return {
|
|
5485
|
+
object: "database_connection_reconcile",
|
|
5486
|
+
code: "operator_action_required",
|
|
5487
|
+
steps: {
|
|
5488
|
+
database: "unchanged",
|
|
5489
|
+
registration: "unchanged",
|
|
5490
|
+
snapshot: "pending",
|
|
5491
|
+
readiness: "action_required"
|
|
5492
|
+
},
|
|
5493
|
+
repairItems: [],
|
|
5494
|
+
needsDatabaseReconcile: false,
|
|
5495
|
+
needsSnapshotRequest: false,
|
|
5496
|
+
detail: "unclassified_not_ready"
|
|
5497
|
+
};
|
|
5498
|
+
}
|
|
5499
|
+
function absentConnectionStatus() {
|
|
5500
|
+
return {
|
|
5501
|
+
object: "database_connection_reconcile",
|
|
5502
|
+
code: "absent",
|
|
5503
|
+
steps: {
|
|
5504
|
+
database: "pending",
|
|
5505
|
+
registration: "pending",
|
|
5506
|
+
snapshot: "pending",
|
|
5507
|
+
readiness: "pending"
|
|
5508
|
+
},
|
|
5509
|
+
repairItems: [],
|
|
5510
|
+
needsDatabaseReconcile: true,
|
|
5511
|
+
needsSnapshotRequest: false
|
|
5512
|
+
};
|
|
5513
|
+
}
|
|
5514
|
+
var SNAPSHOT_SENSITIVE_ITEMS, DATABASE_RECONCILABLE_ITEMS;
|
|
5515
|
+
var init_inspect = __esm({
|
|
5516
|
+
"src/connect/inspect.ts"() {
|
|
5517
|
+
"use strict";
|
|
5518
|
+
init_cjs_shims();
|
|
5519
|
+
SNAPSHOT_SENSITIVE_ITEMS = /* @__PURE__ */ new Set([
|
|
5520
|
+
"publication",
|
|
5521
|
+
"publication_drift",
|
|
5522
|
+
"replica_identity",
|
|
5523
|
+
"snapshot_row_security",
|
|
5524
|
+
"table_select"
|
|
5525
|
+
]);
|
|
5526
|
+
DATABASE_RECONCILABLE_ITEMS = /* @__PURE__ */ new Set([
|
|
5527
|
+
"publication",
|
|
5528
|
+
"replication_role",
|
|
5529
|
+
"replica_identity",
|
|
5530
|
+
"table_select",
|
|
5531
|
+
"snapshot_row_security",
|
|
5532
|
+
"write_role",
|
|
5533
|
+
"row_security",
|
|
5534
|
+
"database_privileges",
|
|
5535
|
+
"schema_privileges",
|
|
5536
|
+
"idempotency_ledger",
|
|
5537
|
+
"table_privileges",
|
|
5538
|
+
"logical_marker",
|
|
5539
|
+
"publication_drift"
|
|
5540
|
+
]);
|
|
5541
|
+
}
|
|
5542
|
+
});
|
|
5543
|
+
|
|
5544
|
+
// src/connect/snapshot.ts
|
|
5545
|
+
function requestInitialSnapshot(input) {
|
|
5546
|
+
return requestControlPlane({
|
|
5547
|
+
path: "/v1/datasources/resnapshot",
|
|
5548
|
+
method: "POST",
|
|
5549
|
+
...input.apiUrl ? { baseUrl: input.apiUrl } : {},
|
|
5550
|
+
apiKey: input.apiKey,
|
|
5551
|
+
body: {},
|
|
5552
|
+
responseSchema: import_wire2.datasourceResnapshotResponseSchema
|
|
5553
|
+
});
|
|
5554
|
+
}
|
|
5555
|
+
var import_wire2;
|
|
5556
|
+
var init_snapshot = __esm({
|
|
5557
|
+
"src/connect/snapshot.ts"() {
|
|
5558
|
+
"use strict";
|
|
5559
|
+
init_cjs_shims();
|
|
5560
|
+
import_wire2 = require("@abloatai/transaction/wire");
|
|
5561
|
+
init_controlPlane();
|
|
5562
|
+
}
|
|
5563
|
+
});
|
|
5564
|
+
|
|
5565
|
+
// src/connect/index.ts
|
|
5566
|
+
var init_connect = __esm({
|
|
5567
|
+
"src/connect/index.ts"() {
|
|
5568
|
+
"use strict";
|
|
5569
|
+
init_cjs_shims();
|
|
5570
|
+
init_inspect();
|
|
5571
|
+
init_snapshot();
|
|
5572
|
+
}
|
|
5573
|
+
});
|
|
5574
|
+
|
|
5371
5575
|
// src/remoteValidation.ts
|
|
5372
5576
|
function dialFailureReason(err) {
|
|
5373
5577
|
if (err === null || typeof err !== "object") return null;
|
|
@@ -5385,7 +5589,7 @@ function dialFailureReason(err) {
|
|
|
5385
5589
|
return null;
|
|
5386
5590
|
}
|
|
5387
5591
|
function describeRemoteFailure(failure) {
|
|
5388
|
-
const label = (0,
|
|
5592
|
+
const label = (0, import_wire3.isReadinessItem)(failure.item) ? READINESS_LABELS[failure.item](failure) : failure.item;
|
|
5389
5593
|
return { label, fix: failure.fix };
|
|
5390
5594
|
}
|
|
5391
5595
|
async function requestRemoteValidation(input) {
|
|
@@ -5398,7 +5602,7 @@ async function requestRemoteValidation(input) {
|
|
|
5398
5602
|
...input.connectionString ? { connectionString: input.connectionString } : {},
|
|
5399
5603
|
...input.writeConnectionString ? { writeConnectionString: input.writeConnectionString } : {}
|
|
5400
5604
|
},
|
|
5401
|
-
responseSchema:
|
|
5605
|
+
responseSchema: import_wire3.datasourceValidationResponseSchema,
|
|
5402
5606
|
...input.fetchImpl ? { fetchImpl: input.fetchImpl } : {}
|
|
5403
5607
|
});
|
|
5404
5608
|
if (!result.ok) {
|
|
@@ -5419,12 +5623,12 @@ async function requestRemoteValidation(input) {
|
|
|
5419
5623
|
failures: verdict.failures
|
|
5420
5624
|
};
|
|
5421
5625
|
}
|
|
5422
|
-
var
|
|
5626
|
+
var import_wire3, DIAL_FAILURE_CODES, withActual, READINESS_LABELS;
|
|
5423
5627
|
var init_remoteValidation = __esm({
|
|
5424
5628
|
"src/remoteValidation.ts"() {
|
|
5425
5629
|
"use strict";
|
|
5426
5630
|
init_cjs_shims();
|
|
5427
|
-
|
|
5631
|
+
import_wire3 = require("@abloatai/transaction/wire");
|
|
5428
5632
|
init_controlPlane();
|
|
5429
5633
|
DIAL_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
5430
5634
|
"ENOTFOUND",
|
|
@@ -5777,19 +5981,21 @@ async function registerDirectDataSource(opts) {
|
|
|
5777
5981
|
...opts.replicationSlot ? { replicationSlot: opts.replicationSlot } : {},
|
|
5778
5982
|
...opts.publication ? { publication: opts.publication } : {}
|
|
5779
5983
|
},
|
|
5780
|
-
responseSchema:
|
|
5984
|
+
responseSchema: import_wire4.datasourceSummarySchema
|
|
5781
5985
|
});
|
|
5782
5986
|
if (result.ok) {
|
|
5783
5987
|
const body = result.value;
|
|
5784
5988
|
const statusNote = body.status === "active" ? `${opts.route}, active` : opts.route;
|
|
5785
|
-
|
|
5786
|
-
|
|
5989
|
+
if (!opts.quiet) {
|
|
5990
|
+
console.log(
|
|
5991
|
+
`
|
|
5787
5992
|
${import_picocolors8.default.green("\u2713")} Registered${body.host ? ` ${import_picocolors8.default.dim(body.host)}` : ""}${body.id ? ` ${import_picocolors8.default.dim(`(${body.id})`)}` : ""} as a direct DataSource (${statusNote}).
|
|
5788
5993
|
Your database is connected. Reads follow its replication stream; writes go through Ablo
|
|
5789
5994
|
and land in your own tables. Rows that already exist load automatically \u2014 no manual
|
|
5790
5995
|
backfill or row updates. Check their progress with ${import_picocolors8.default.cyan("ablo connect check")}.
|
|
5791
5996
|
`
|
|
5792
|
-
|
|
5997
|
+
);
|
|
5998
|
+
}
|
|
5793
5999
|
return true;
|
|
5794
6000
|
}
|
|
5795
6001
|
const err = result.error;
|
|
@@ -5861,14 +6067,14 @@ async function registerDirectDataSource(opts) {
|
|
|
5861
6067
|
console.error();
|
|
5862
6068
|
return false;
|
|
5863
6069
|
}
|
|
5864
|
-
var import_picocolors8, import_zod3,
|
|
6070
|
+
var import_picocolors8, import_zod3, import_wire4, import_source2, import_footprint, DIRECT_DATA_SOURCE_ROUTES, registerFailureDetailsSchema;
|
|
5865
6071
|
var init_connectSetup = __esm({
|
|
5866
6072
|
"src/connectSetup.ts"() {
|
|
5867
6073
|
"use strict";
|
|
5868
6074
|
init_cjs_shims();
|
|
5869
6075
|
import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
5870
6076
|
import_zod3 = require("zod");
|
|
5871
|
-
|
|
6077
|
+
import_wire4 = require("@abloatai/transaction/wire");
|
|
5872
6078
|
init_controlPlane();
|
|
5873
6079
|
init_remoteValidation();
|
|
5874
6080
|
import_source2 = require("@abloatai/transaction/source");
|
|
@@ -5881,10 +6087,10 @@ var init_connectSetup = __esm({
|
|
|
5881
6087
|
"vpn"
|
|
5882
6088
|
];
|
|
5883
6089
|
registerFailureDetailsSchema = import_zod3.z.object({
|
|
5884
|
-
failures: import_zod3.z.array(
|
|
6090
|
+
failures: import_zod3.z.array(import_wire4.readinessFailureSchema).optional(),
|
|
5885
6091
|
reason: import_zod3.z.string().optional(),
|
|
5886
6092
|
details: import_zod3.z.object({
|
|
5887
|
-
failures: import_zod3.z.array(
|
|
6093
|
+
failures: import_zod3.z.array(import_wire4.readinessFailureSchema).optional(),
|
|
5888
6094
|
reason: import_zod3.z.string().optional()
|
|
5889
6095
|
}).loose().optional()
|
|
5890
6096
|
}).loose();
|
|
@@ -5910,7 +6116,7 @@ async function deregisterDataSource(opts) {
|
|
|
5910
6116
|
path: "/v1/datasources",
|
|
5911
6117
|
method: "DELETE",
|
|
5912
6118
|
apiKey: opts.apiKey,
|
|
5913
|
-
responseSchema:
|
|
6119
|
+
responseSchema: import_wire5.datasourceDisconnectedResponseSchema,
|
|
5914
6120
|
...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {},
|
|
5915
6121
|
...opts.fetchImpl !== void 0 ? { fetchImpl: opts.fetchImpl } : {}
|
|
5916
6122
|
});
|
|
@@ -6046,7 +6252,7 @@ async function disconnect(argv) {
|
|
|
6046
6252
|
}
|
|
6047
6253
|
renderDisconnected(outcome.response, project, branchLabel);
|
|
6048
6254
|
}
|
|
6049
|
-
var import_picocolors9, import_errors10,
|
|
6255
|
+
var import_picocolors9, import_errors10, import_wire5, DISCONNECT_USAGE;
|
|
6050
6256
|
var init_disconnect = __esm({
|
|
6051
6257
|
"src/disconnect.ts"() {
|
|
6052
6258
|
"use strict";
|
|
@@ -6054,7 +6260,7 @@ var init_disconnect = __esm({
|
|
|
6054
6260
|
import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
6055
6261
|
init_dist2();
|
|
6056
6262
|
import_errors10 = require("@abloatai/transaction/errors");
|
|
6057
|
-
|
|
6263
|
+
import_wire5 = require("@abloatai/transaction/wire");
|
|
6058
6264
|
init_config();
|
|
6059
6265
|
init_dbRole();
|
|
6060
6266
|
init_controlPlane();
|
|
@@ -6207,7 +6413,7 @@ async function fetchPushedSchema(apiUrl3, apiKey) {
|
|
|
6207
6413
|
signal: ctrl.signal
|
|
6208
6414
|
});
|
|
6209
6415
|
if (!res.ok) return null;
|
|
6210
|
-
const parsed =
|
|
6416
|
+
const parsed = import_wire6.schemaReadResponseSchema.safeParse(await res.json());
|
|
6211
6417
|
if (!parsed.success) return null;
|
|
6212
6418
|
const read = parsed.data;
|
|
6213
6419
|
return read.active ? {
|
|
@@ -6235,7 +6441,7 @@ async function fetchDeliveryState(apiUrl3, apiKey, timeoutMs = 4e3) {
|
|
|
6235
6441
|
signal: ctrl.signal
|
|
6236
6442
|
});
|
|
6237
6443
|
if (!res.ok) return { kind: "unknown", detail: `HTTP ${res.status}` };
|
|
6238
|
-
const parsed =
|
|
6444
|
+
const parsed = import_wire6.logDeliveryResponseSchema.safeParse(await res.json());
|
|
6239
6445
|
if (!parsed.success) return { kind: "unknown", detail: "unrecognized response" };
|
|
6240
6446
|
const { window_seconds, recorded, unroutable, sample } = parsed.data;
|
|
6241
6447
|
return { kind: "known", window_seconds, recorded, unroutable, sample: sample ?? null };
|
|
@@ -6259,7 +6465,7 @@ async function fetchDataSourceState(apiUrl3, apiKey, timeoutMs = 4e3) {
|
|
|
6259
6465
|
if (!res.ok) {
|
|
6260
6466
|
return { kind: "unknown", detail: `HTTP ${res.status}` };
|
|
6261
6467
|
}
|
|
6262
|
-
const parsed =
|
|
6468
|
+
const parsed = import_wire6.datasourceListResponseSchema.safeParse(await res.json());
|
|
6263
6469
|
if (!parsed.success) return { kind: "unknown", detail: "unrecognized response" };
|
|
6264
6470
|
const rows = parsed.data.data;
|
|
6265
6471
|
if (rows.length === 0) return { kind: "none" };
|
|
@@ -6346,12 +6552,12 @@ function blockers(input) {
|
|
|
6346
6552
|
}
|
|
6347
6553
|
return found;
|
|
6348
6554
|
}
|
|
6349
|
-
var
|
|
6555
|
+
var import_wire6, import_schema5, WRITE_READY_VERDICT;
|
|
6350
6556
|
var init_readiness = __esm({
|
|
6351
6557
|
"src/readiness.ts"() {
|
|
6352
6558
|
"use strict";
|
|
6353
6559
|
init_cjs_shims();
|
|
6354
|
-
|
|
6560
|
+
import_wire6 = require("@abloatai/transaction/wire");
|
|
6355
6561
|
init_push();
|
|
6356
6562
|
init_dbProvider();
|
|
6357
6563
|
init_remoteValidation();
|
|
@@ -6646,7 +6852,7 @@ async function locateExistingConnection(input) {
|
|
|
6646
6852
|
connectionString: input.connectionString,
|
|
6647
6853
|
...input.schema ? { schema: input.schema } : {}
|
|
6648
6854
|
},
|
|
6649
|
-
responseSchema:
|
|
6855
|
+
responseSchema: import_wire7.datasourceLocationResponseSchema
|
|
6650
6856
|
});
|
|
6651
6857
|
if (!result.ok) return null;
|
|
6652
6858
|
if (result.value.held) return result.value.held;
|
|
@@ -6660,13 +6866,13 @@ function alreadyConnectedElsewhere(held) {
|
|
|
6660
6866
|
const where = held.project ? `project ${held.project}, branch ${held.branch}` : `branch ${held.branch}`;
|
|
6661
6867
|
return `This database schema is already connected to ${where}. A (database, schema) binding belongs to one plane at a time.`;
|
|
6662
6868
|
}
|
|
6663
|
-
var
|
|
6869
|
+
var import_wire7, import_schema6;
|
|
6664
6870
|
var init_connectPreflight = __esm({
|
|
6665
6871
|
"src/connectPreflight.ts"() {
|
|
6666
6872
|
"use strict";
|
|
6667
6873
|
init_cjs_shims();
|
|
6668
6874
|
init_src();
|
|
6669
|
-
|
|
6875
|
+
import_wire7 = require("@abloatai/transaction/wire");
|
|
6670
6876
|
init_controlPlane();
|
|
6671
6877
|
init_push();
|
|
6672
6878
|
import_schema6 = require("@abloatai/transaction/schema");
|
|
@@ -6689,6 +6895,26 @@ function postRegistrationOutcome(input) {
|
|
|
6689
6895
|
notice: ROTATE_STRANDED_CREDENTIALS_NOTICE
|
|
6690
6896
|
};
|
|
6691
6897
|
}
|
|
6898
|
+
function emitReconcileStatus(status2, json) {
|
|
6899
|
+
if (json) {
|
|
6900
|
+
console.log(JSON.stringify(status2));
|
|
6901
|
+
return;
|
|
6902
|
+
}
|
|
6903
|
+
if (status2.code === "ready") {
|
|
6904
|
+
console.log(
|
|
6905
|
+
` ${import_picocolors12.default.green("\u2713")} Already ready \u2014 database, credentials, and snapshot are unchanged.
|
|
6906
|
+
`
|
|
6907
|
+
);
|
|
6908
|
+
} else if (status2.code === "loading") {
|
|
6909
|
+
console.log(
|
|
6910
|
+
` ${import_picocolors12.default.yellow("\u2014")} Existing rows are loading; re-run the same command to poll readiness.
|
|
6911
|
+
`
|
|
6912
|
+
);
|
|
6913
|
+
} else {
|
|
6914
|
+
console.log(` ${import_picocolors12.default.yellow("\u2014")} ${status2.code}
|
|
6915
|
+
`);
|
|
6916
|
+
}
|
|
6917
|
+
}
|
|
6692
6918
|
function isPlaintextRefusal(err) {
|
|
6693
6919
|
const message2 = err instanceof Error ? err.message : String(err);
|
|
6694
6920
|
return /plaintext password/i.test(message2);
|
|
@@ -6720,15 +6946,10 @@ async function runConnectApply(args) {
|
|
|
6720
6946
|
const rotating = args.rotate;
|
|
6721
6947
|
const verb = rotating ? "connect rotate" : "connect apply";
|
|
6722
6948
|
let adminUrl = args.url ?? readProjectAdminDatabaseUrl();
|
|
6723
|
-
if (!adminUrl) {
|
|
6724
|
-
throw new import_errors11.AbloValidationError(
|
|
6725
|
-
"No admin connection string. Pass --url <admin-conn> (or set DATABASE_URL) and re-run.",
|
|
6726
|
-
{ code: "cli_database_url_missing" }
|
|
6727
|
-
);
|
|
6728
|
-
}
|
|
6729
6949
|
const adminSource = args.url ? "--url" : "DATABASE_URL";
|
|
6730
6950
|
let target = "your database";
|
|
6731
6951
|
try {
|
|
6952
|
+
if (!adminUrl) throw new Error("not resolved yet");
|
|
6732
6953
|
const parsed = new URL(adminUrl);
|
|
6733
6954
|
target = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
|
|
6734
6955
|
} catch {
|
|
@@ -6752,15 +6973,62 @@ ${ambient}` : ""}`,
|
|
|
6752
6973
|
{ code: "cli_api_key_missing" }
|
|
6753
6974
|
);
|
|
6754
6975
|
}
|
|
6755
|
-
|
|
6756
|
-
|
|
6976
|
+
const apiUrl3 = apiBaseUrl();
|
|
6977
|
+
const planeState = await fetchDataSourceState(apiUrl3, apiKey);
|
|
6978
|
+
const existingRegistration = !rotating && planeState.kind === "connected" && planeState.connections.includes("direct");
|
|
6979
|
+
let existingNeedsSnapshot = false;
|
|
6980
|
+
if (existingRegistration) {
|
|
6981
|
+
const inspected = inspectRegisteredConnection(
|
|
6982
|
+
await requestRemoteValidation({ apiUrl: apiUrl3, apiKey })
|
|
6983
|
+
);
|
|
6984
|
+
if (inspected.code === "ready") {
|
|
6985
|
+
emitReconcileStatus(inspected, args.json);
|
|
6986
|
+
return;
|
|
6987
|
+
}
|
|
6988
|
+
if (inspected.code === "loading") {
|
|
6989
|
+
emitReconcileStatus(inspected, args.json);
|
|
6990
|
+
return;
|
|
6991
|
+
}
|
|
6992
|
+
if (!inspected.needsDatabaseReconcile && inspected.needsSnapshotRequest) {
|
|
6993
|
+
const snapshot = await requestInitialSnapshot({ apiUrl: apiUrl3, apiKey });
|
|
6994
|
+
const resumed = {
|
|
6995
|
+
...inspected,
|
|
6996
|
+
code: snapshot.replication_slot?.released === false ? "operator_action_required" : "loading",
|
|
6997
|
+
steps: {
|
|
6998
|
+
...inspected.steps,
|
|
6999
|
+
snapshot: snapshot.replication_slot?.released === false ? "action_required" : "loading",
|
|
7000
|
+
readiness: snapshot.replication_slot?.released === false ? "action_required" : "pending"
|
|
7001
|
+
},
|
|
7002
|
+
...snapshot.replication_slot?.released === false ? { detail: snapshot.replication_slot.detail ?? "replication_slot_active" } : {}
|
|
7003
|
+
};
|
|
7004
|
+
emitReconcileStatus(resumed, args.json);
|
|
7005
|
+
return;
|
|
7006
|
+
}
|
|
7007
|
+
if (inspected.code === "operator_action_required") {
|
|
7008
|
+
throw new import_errors11.AbloConnectionError(
|
|
7009
|
+
`The registered source needs operator action before it can be reconciled (${inspected.detail ?? "not ready"}).`,
|
|
7010
|
+
{ code: "cli_database_unreachable", details: { ...inspected } }
|
|
7011
|
+
);
|
|
7012
|
+
}
|
|
7013
|
+
existingNeedsSnapshot = inspected.needsSnapshotRequest;
|
|
7014
|
+
}
|
|
7015
|
+
if (!adminUrl) {
|
|
7016
|
+
throw new import_errors11.AbloValidationError(
|
|
7017
|
+
"This connection needs database reconciliation. Pass the transient owner connection with --url <admin-conn> (or set DATABASE_URL) and re-run the same `ablo connect apply` operation.",
|
|
7018
|
+
{ code: "cli_database_url_missing" }
|
|
7019
|
+
);
|
|
7020
|
+
}
|
|
7021
|
+
if (!args.json) {
|
|
7022
|
+
console.log(
|
|
7023
|
+
`
|
|
6757
7024
|
${brand("ablo")} ${import_picocolors12.default.dim(verb)} ${import_picocolors12.default.dim(rotating ? "re-key the scoped roles" : "set up your database for Ablo")}
|
|
6758
7025
|
`
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
7026
|
+
);
|
|
7027
|
+
console.log(
|
|
7028
|
+
` ${import_picocolors12.default.dim("\u2192")} ${import_picocolors12.default.bold(target)}${adminSource === "DATABASE_URL" ? import_picocolors12.default.dim(" (admin via DATABASE_URL)") : ""}
|
|
6762
7029
|
`
|
|
6763
|
-
|
|
7030
|
+
);
|
|
7031
|
+
}
|
|
6764
7032
|
const pooledAdmin = detectPooler(adminUrl);
|
|
6765
7033
|
if (pooledAdmin?.confidence === "host") {
|
|
6766
7034
|
if (pooledAdmin.direct) {
|
|
@@ -6771,7 +7039,7 @@ ${ambient}` : ""}`,
|
|
|
6771
7039
|
target = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
|
|
6772
7040
|
} catch {
|
|
6773
7041
|
}
|
|
6774
|
-
console.log(
|
|
7042
|
+
if (!args.json) console.log(
|
|
6775
7043
|
` ${import_picocolors12.default.yellow("!")} ${import_picocolors12.default.bold(pooledLabel)} is a connection pooler, so this run uses the direct host:
|
|
6776
7044
|
${import_picocolors12.default.bold(target)}
|
|
6777
7045
|
` + import_picocolors12.default.dim(
|
|
@@ -6798,7 +7066,7 @@ ${ambient}` : ""}`,
|
|
|
6798
7066
|
}
|
|
6799
7067
|
}
|
|
6800
7068
|
if (pooledAdmin?.confidence === "port") {
|
|
6801
|
-
console.log(
|
|
7069
|
+
if (!args.json) console.log(
|
|
6802
7070
|
` ${import_picocolors12.default.yellow("!")} Port ${import_picocolors12.default.bold(new URL(adminUrl).port)} is the one a connection pooler usually answers on.
|
|
6803
7071
|
` + import_picocolors12.default.dim(
|
|
6804
7072
|
` Replication cannot run over a pooler, so if that is what this is, point ${import_picocolors12.default.bold("--url")}
|
|
@@ -6814,7 +7082,7 @@ ${ambient}` : ""}`,
|
|
|
6814
7082
|
}).catch(() => null);
|
|
6815
7083
|
const mismatch = connectTarget ? describeMismatches(connectTarget.mismatches) : null;
|
|
6816
7084
|
if (mismatch) {
|
|
6817
|
-
console.log(` ${import_picocolors12.default.yellow("!")} ${mismatch}
|
|
7085
|
+
if (!args.json) console.log(` ${import_picocolors12.default.yellow("!")} ${mismatch}
|
|
6818
7086
|
`);
|
|
6819
7087
|
}
|
|
6820
7088
|
const confirmed = connectTarget?.confirmed;
|
|
@@ -6859,7 +7127,7 @@ ${ambient}` : ""}`,
|
|
|
6859
7127
|
);
|
|
6860
7128
|
}
|
|
6861
7129
|
if (args.tables.length === 0) {
|
|
6862
|
-
console.log(
|
|
7130
|
+
if (!args.json) console.log(
|
|
6863
7131
|
import_picocolors12.default.dim(
|
|
6864
7132
|
` publishing the ${tables.length} table${tables.length === 1 ? "" : "s"} declared by your Ablo schema in ${import_picocolors12.default.bold(args.schema)} (${import_picocolors12.default.bold("--tables")} to override)
|
|
6865
7133
|
`
|
|
@@ -6950,6 +7218,13 @@ ${ambient}` : ""}`,
|
|
|
6950
7218
|
publication
|
|
6951
7219
|
});
|
|
6952
7220
|
const existingRoles = await presentRoles(admin, [role, writeRole]).catch(() => []);
|
|
7221
|
+
if (existingRegistration && existingRoles.length !== 2) {
|
|
7222
|
+
await admin.end({ timeout: 2 });
|
|
7223
|
+
throw new import_errors11.AbloValidationError(
|
|
7224
|
+
`The registered source's scoped role pair is incomplete (${existingRoles.length}/2 present). Re-run with \`ablo connect rotate\` to repair credentials explicitly; no database changes were made.`,
|
|
7225
|
+
{ code: "cli_invalid_arguments", details: { existingRoles: [...existingRoles] } }
|
|
7226
|
+
);
|
|
7227
|
+
}
|
|
6953
7228
|
if (rotatePlane) {
|
|
6954
7229
|
const refusal = rotateWithoutConnection({ rotating, ...rotatePlane, existingRoles });
|
|
6955
7230
|
if (refusal) {
|
|
@@ -6963,11 +7238,14 @@ ${ambient}` : ""}`,
|
|
|
6963
7238
|
}
|
|
6964
7239
|
const blocker2 = reapplyBlocker({
|
|
6965
7240
|
rotating,
|
|
6966
|
-
|
|
7241
|
+
// A complete, registered pair keeps its current passwords: apply repairs
|
|
7242
|
+
// only non-secret invariants and never re-registers it. A partial pair is
|
|
7243
|
+
// still refused because it cannot be completed without credential repair.
|
|
7244
|
+
existingRoles: existingRegistration && existingRoles.length === 2 ? [] : existingRoles
|
|
6967
7245
|
});
|
|
6968
7246
|
if (blocker2) {
|
|
6969
7247
|
await admin.end({ timeout: 2 });
|
|
6970
|
-
console.log(
|
|
7248
|
+
if (!args.json) console.log(
|
|
6971
7249
|
` ${import_picocolors12.default.yellow("!")} ${blocker2.roles.map((r2) => import_picocolors12.default.bold(r2)).join(" and ")} ${blocker2.plural ? "are" : "is"} already set up here.
|
|
6972
7250
|
`
|
|
6973
7251
|
);
|
|
@@ -7014,17 +7292,23 @@ ${ambient}` : ""}`,
|
|
|
7014
7292
|
});
|
|
7015
7293
|
const steps = buildPlan("scram-verifier");
|
|
7016
7294
|
if (pubReconcile.removed.length > 0 || pubReconcile.recreated) {
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7295
|
+
if (!args.json) {
|
|
7296
|
+
console.log(
|
|
7297
|
+
` ${import_picocolors12.default.yellow("!")} ${import_picocolors12.default.bold(publication)} already publishes a different set; reconciling to your mapped tables:`
|
|
7298
|
+
);
|
|
7299
|
+
for (const t of pubReconcile.added) console.log(` ${import_picocolors12.default.green("+")} ${t}`);
|
|
7300
|
+
for (const t of pubReconcile.removed) {
|
|
7301
|
+
console.log(` ${import_picocolors12.default.red("-")} ${t} ${import_picocolors12.default.dim("(stops replicating to Ablo)")}`);
|
|
7302
|
+
}
|
|
7303
|
+
if (pubReconcile.recreated && existingPublication.allTables) {
|
|
7304
|
+
console.log(
|
|
7305
|
+
` ${import_picocolors12.default.red("-")} ${import_picocolors12.default.dim("every other table (was FOR ALL TABLES)")}`
|
|
7306
|
+
);
|
|
7307
|
+
}
|
|
7308
|
+
console.log();
|
|
7309
|
+
}
|
|
7026
7310
|
}
|
|
7027
|
-
printPlan(steps, args.showSql);
|
|
7311
|
+
if (!args.json) printPlan(steps, args.showSql);
|
|
7028
7312
|
if (!args.yes) {
|
|
7029
7313
|
if (!process.stdout.isTTY) {
|
|
7030
7314
|
await admin.end({ timeout: 2 });
|
|
@@ -7075,9 +7359,39 @@ ${ambient}` : ""}`,
|
|
|
7075
7359
|
process.exit(1);
|
|
7076
7360
|
}
|
|
7077
7361
|
await admin.end({ timeout: 2 });
|
|
7362
|
+
if (existingRegistration) {
|
|
7363
|
+
const after = inspectRegisteredConnection(
|
|
7364
|
+
await requestRemoteValidation({ apiUrl: apiUrl3, apiKey })
|
|
7365
|
+
);
|
|
7366
|
+
if (after.needsDatabaseReconcile || after.code === "operator_action_required") {
|
|
7367
|
+
throw new import_errors11.AbloConnectionError(
|
|
7368
|
+
`Database reconciliation did not reach the snapshot boundary (${after.detail ?? after.repairItems.join(", ")}).`,
|
|
7369
|
+
{ code: "cli_database_unreachable", details: { ...after } }
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
if (existingNeedsSnapshot || after.needsSnapshotRequest) {
|
|
7373
|
+
const snapshot = await requestInitialSnapshot({ apiUrl: apiUrl3, apiKey });
|
|
7374
|
+
const reconciled = {
|
|
7375
|
+
...after,
|
|
7376
|
+
code: snapshot.replication_slot?.released === false ? "operator_action_required" : "loading",
|
|
7377
|
+
steps: {
|
|
7378
|
+
...after.steps,
|
|
7379
|
+
database: "changed",
|
|
7380
|
+
registration: "unchanged",
|
|
7381
|
+
snapshot: snapshot.replication_slot?.released === false ? "action_required" : "loading",
|
|
7382
|
+
readiness: snapshot.replication_slot?.released === false ? "action_required" : "pending"
|
|
7383
|
+
},
|
|
7384
|
+
...snapshot.replication_slot?.released === false ? { detail: snapshot.replication_slot.detail ?? "replication_slot_active" } : {}
|
|
7385
|
+
};
|
|
7386
|
+
emitReconcileStatus(reconciled, args.json);
|
|
7387
|
+
return;
|
|
7388
|
+
}
|
|
7389
|
+
emitReconcileStatus(after, args.json);
|
|
7390
|
+
return;
|
|
7391
|
+
}
|
|
7078
7392
|
const replicationUrl = rewriteDatabaseUrl(adminUrl, role, replicationPassword);
|
|
7079
7393
|
const writeUrl = rewriteDatabaseUrl(adminUrl, writeRole, writePassword);
|
|
7080
|
-
console.log(`
|
|
7394
|
+
if (!args.json) console.log(`
|
|
7081
7395
|
${import_picocolors12.default.green("\u2713")} Roles ${rotating ? "re-keyed" : "created"}.
|
|
7082
7396
|
`);
|
|
7083
7397
|
if (!walReady) {
|
|
@@ -7129,7 +7443,7 @@ ${ambient}` : ""}`,
|
|
|
7129
7443
|
process.exit(1);
|
|
7130
7444
|
}
|
|
7131
7445
|
if (replicationProbe.items === null || writeProbe.items === null) {
|
|
7132
|
-
console.log(import_picocolors12.default.dim(` Couldn't verify from here; Ablo will validate from its own network.
|
|
7446
|
+
if (!args.json) console.log(import_picocolors12.default.dim(` Couldn't verify from here; Ablo will validate from its own network.
|
|
7133
7447
|
`));
|
|
7134
7448
|
}
|
|
7135
7449
|
const items = [...replicationProbe.items ?? [], ...writeProbe.items ?? []];
|
|
@@ -7153,7 +7467,6 @@ ${ambient}` : ""}`,
|
|
|
7153
7467
|
`
|
|
7154
7468
|
);
|
|
7155
7469
|
}
|
|
7156
|
-
const apiUrl3 = apiBaseUrl();
|
|
7157
7470
|
const registered = await registerDirectDataSource({
|
|
7158
7471
|
apiUrl: apiUrl3,
|
|
7159
7472
|
apiKey,
|
|
@@ -7162,7 +7475,8 @@ ${ambient}` : ""}`,
|
|
|
7162
7475
|
route: args.route,
|
|
7163
7476
|
schema: args.schema,
|
|
7164
7477
|
replicationSlot: footprint.slot,
|
|
7165
|
-
publication
|
|
7478
|
+
publication,
|
|
7479
|
+
quiet: args.json
|
|
7166
7480
|
});
|
|
7167
7481
|
process.off("SIGINT", onRotateInterrupt);
|
|
7168
7482
|
process.off("SIGTERM", onRotateInterrupt);
|
|
@@ -7172,6 +7486,22 @@ ${ambient}` : ""}`,
|
|
|
7172
7486
|
${import_picocolors12.default.red(outcome.notice.split("\n").join("\n "))}
|
|
7173
7487
|
`);
|
|
7174
7488
|
}
|
|
7489
|
+
if (args.json && registered) {
|
|
7490
|
+
const initial = absentConnectionStatus();
|
|
7491
|
+
emitReconcileStatus(
|
|
7492
|
+
{
|
|
7493
|
+
...initial,
|
|
7494
|
+
code: "loading",
|
|
7495
|
+
steps: {
|
|
7496
|
+
database: "changed",
|
|
7497
|
+
registration: "changed",
|
|
7498
|
+
snapshot: "loading",
|
|
7499
|
+
readiness: "pending"
|
|
7500
|
+
}
|
|
7501
|
+
},
|
|
7502
|
+
true
|
|
7503
|
+
);
|
|
7504
|
+
}
|
|
7175
7505
|
process.exit(outcome.exitCode);
|
|
7176
7506
|
}
|
|
7177
7507
|
var import_picocolors12, import_errors11, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
|
|
@@ -7186,11 +7516,13 @@ var init_connectApply = __esm({
|
|
|
7186
7516
|
import_footprint2 = require("@abloatai/transaction/footprint");
|
|
7187
7517
|
init_connectSetup();
|
|
7188
7518
|
init_connectOwnership();
|
|
7189
|
-
|
|
7519
|
+
init_connect2();
|
|
7190
7520
|
init_dbProvider();
|
|
7191
7521
|
init_dbRole();
|
|
7192
7522
|
init_config();
|
|
7193
7523
|
init_readiness();
|
|
7524
|
+
init_remoteValidation();
|
|
7525
|
+
init_connect();
|
|
7194
7526
|
init_push();
|
|
7195
7527
|
init_controlPlane();
|
|
7196
7528
|
init_theme();
|
|
@@ -7212,6 +7544,7 @@ function parseConnectArgs(argv) {
|
|
|
7212
7544
|
let envFile;
|
|
7213
7545
|
let yes = false;
|
|
7214
7546
|
let showSql = false;
|
|
7547
|
+
let json = false;
|
|
7215
7548
|
let scan = false;
|
|
7216
7549
|
let locate = false;
|
|
7217
7550
|
let manual = false;
|
|
@@ -7269,6 +7602,9 @@ function parseConnectArgs(argv) {
|
|
|
7269
7602
|
case "--show-sql":
|
|
7270
7603
|
showSql = true;
|
|
7271
7604
|
break;
|
|
7605
|
+
case "--json":
|
|
7606
|
+
json = true;
|
|
7607
|
+
break;
|
|
7272
7608
|
case "--manual":
|
|
7273
7609
|
manual = true;
|
|
7274
7610
|
break;
|
|
@@ -7316,6 +7652,7 @@ function parseConnectArgs(argv) {
|
|
|
7316
7652
|
envFile,
|
|
7317
7653
|
yes,
|
|
7318
7654
|
showSql,
|
|
7655
|
+
json,
|
|
7319
7656
|
scan,
|
|
7320
7657
|
locate,
|
|
7321
7658
|
tables,
|
|
@@ -7899,7 +8236,7 @@ ${ambient}` : ""}`,
|
|
|
7899
8236
|
method: "POST",
|
|
7900
8237
|
apiKey,
|
|
7901
8238
|
body: { connectionString: url, schema: args.schema },
|
|
7902
|
-
responseSchema:
|
|
8239
|
+
responseSchema: import_wire8.datasourceLocationResponseSchema
|
|
7903
8240
|
});
|
|
7904
8241
|
if (answer.available === false && !answer.held) {
|
|
7905
8242
|
console.log(
|
|
@@ -7942,13 +8279,7 @@ async function runResnapshot() {
|
|
|
7942
8279
|
${brand("ablo")} ${import_picocolors13.default.dim("connect resnapshot")} ${import_picocolors13.default.dim("reload existing rows")}
|
|
7943
8280
|
`
|
|
7944
8281
|
);
|
|
7945
|
-
const result = await
|
|
7946
|
-
path: "/v1/datasources/resnapshot",
|
|
7947
|
-
method: "POST",
|
|
7948
|
-
apiKey,
|
|
7949
|
-
body: {},
|
|
7950
|
-
responseSchema: import_wire7.datasourceResnapshotResponseSchema
|
|
7951
|
-
});
|
|
8282
|
+
const result = await requestInitialSnapshot({ apiKey });
|
|
7952
8283
|
if (result.replication_slot?.released === false) {
|
|
7953
8284
|
console.log(` ${import_picocolors13.default.yellow("\u2014")} Snapshot reset recorded, but the old slot is still active.`);
|
|
7954
8285
|
if (result.replication_slot.detail) console.log(` ${import_picocolors13.default.dim(result.replication_slot.detail)}`);
|
|
@@ -8039,8 +8370,8 @@ async function connect(argv) {
|
|
|
8039
8370
|
})
|
|
8040
8371
|
);
|
|
8041
8372
|
}
|
|
8042
|
-
var import_errors12, import_picocolors13, import_footprint3,
|
|
8043
|
-
var
|
|
8373
|
+
var import_errors12, import_picocolors13, import_footprint3, import_wire8, FOOTPRINT_LOOKUP, CONNECT_USAGE;
|
|
8374
|
+
var init_connect2 = __esm({
|
|
8044
8375
|
"src/connect.ts"() {
|
|
8045
8376
|
"use strict";
|
|
8046
8377
|
init_cjs_shims();
|
|
@@ -8052,7 +8383,8 @@ var init_connect = __esm({
|
|
|
8052
8383
|
init_dbRole();
|
|
8053
8384
|
init_config();
|
|
8054
8385
|
init_controlPlane();
|
|
8055
|
-
|
|
8386
|
+
import_wire8 = require("@abloatai/transaction/wire");
|
|
8387
|
+
init_connect();
|
|
8056
8388
|
init_theme();
|
|
8057
8389
|
init_target();
|
|
8058
8390
|
init_remoteValidation();
|
|
@@ -8098,6 +8430,7 @@ var init_connect = __esm({
|
|
|
8098
8430
|
--manual Print the setup SQL instead of running it
|
|
8099
8431
|
--yes Set up without the confirmation (non-interactive)
|
|
8100
8432
|
--show-sql Show the exact statements before running them
|
|
8433
|
+
--json Emit stable result and step codes for automation
|
|
8101
8434
|
|
|
8102
8435
|
apply registers with Ablo directly; the admin credential is used only on this
|
|
8103
8436
|
machine and never persisted. Your app holds only ABLO_API_KEY.`;
|
|
@@ -284318,11 +284651,11 @@ async function migrate(argv) {
|
|
|
284318
284651
|
}
|
|
284319
284652
|
|
|
284320
284653
|
// src/index.ts
|
|
284321
|
-
|
|
284654
|
+
init_connect2();
|
|
284322
284655
|
|
|
284323
284656
|
// src/commands.ts
|
|
284324
284657
|
init_cjs_shims();
|
|
284325
|
-
|
|
284658
|
+
init_connect2();
|
|
284326
284659
|
|
|
284327
284660
|
// src/docs.ts
|
|
284328
284661
|
init_cjs_shims();
|
|
@@ -285039,7 +285372,7 @@ var import_path6 = require("path");
|
|
|
285039
285372
|
var import_schema7 = require("@abloatai/transaction/schema");
|
|
285040
285373
|
init_push();
|
|
285041
285374
|
init_controlPlane();
|
|
285042
|
-
var
|
|
285375
|
+
var import_wire9 = require("@abloatai/transaction/wire");
|
|
285043
285376
|
init_config();
|
|
285044
285377
|
init_readiness();
|
|
285045
285378
|
init_theme();
|
|
@@ -285214,7 +285547,7 @@ async function registerLocalSource(args) {
|
|
|
285214
285547
|
reverseChannel: true,
|
|
285215
285548
|
metadata: { managed_by: "ablo dev --local" }
|
|
285216
285549
|
},
|
|
285217
|
-
responseSchema:
|
|
285550
|
+
responseSchema: import_wire9.datasourceSummarySchema
|
|
285218
285551
|
});
|
|
285219
285552
|
}
|
|
285220
285553
|
function classifyKey(apiKey) {
|
|
@@ -288322,7 +288655,7 @@ var import_child_process2 = require("child_process");
|
|
|
288322
288655
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
288323
288656
|
init_dist2();
|
|
288324
288657
|
var import_errors21 = require("@abloatai/transaction/errors");
|
|
288325
|
-
var
|
|
288658
|
+
var import_wire10 = require("@abloatai/transaction/wire");
|
|
288326
288659
|
init_config();
|
|
288327
288660
|
init_projects();
|
|
288328
288661
|
init_theme();
|
|
@@ -288517,7 +288850,7 @@ ${import_picocolors23.default.dim(url)}`, "Approve in your browser");
|
|
|
288517
288850
|
}
|
|
288518
288851
|
process.exit(1);
|
|
288519
288852
|
}
|
|
288520
|
-
const parsedProv =
|
|
288853
|
+
const parsedProv = import_wire10.provisionKeyResponseSchema.safeParse(
|
|
288521
288854
|
await provRes.json().catch(() => null)
|
|
288522
288855
|
);
|
|
288523
288856
|
if (!parsedProv.success) {
|
|
@@ -288867,7 +289200,7 @@ async function status(args = []) {
|
|
|
288867
289200
|
// src/logs.ts
|
|
288868
289201
|
init_cjs_shims();
|
|
288869
289202
|
var import_errors22 = require("@abloatai/transaction/errors");
|
|
288870
|
-
var
|
|
289203
|
+
var import_wire11 = require("@abloatai/transaction/wire");
|
|
288871
289204
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
288872
289205
|
init_config();
|
|
288873
289206
|
init_theme();
|
|
@@ -288978,7 +289311,7 @@ async function logs(argv) {
|
|
|
288978
289311
|
const json = await res.json();
|
|
288979
289312
|
return {
|
|
288980
289313
|
events: json.data ?? json.events ?? [],
|
|
288981
|
-
cursor: json.next_cursor ?? (json.cursor != null ? (0,
|
|
289314
|
+
cursor: json.next_cursor ?? (json.cursor != null ? (0, import_wire11.formatFeedCursor)({ log: json.cursor, claims: 0 }) : (0, import_wire11.formatFeedCursor)(import_wire11.FEED_CURSOR_START))
|
|
288982
289315
|
};
|
|
288983
289316
|
}
|
|
288984
289317
|
if (!args.json) {
|
|
@@ -289010,9 +289343,9 @@ async function logs(argv) {
|
|
|
289010
289343
|
});
|
|
289011
289344
|
if (!page) continue;
|
|
289012
289345
|
for (const e2 of page.events) render2(e2, args.json);
|
|
289013
|
-
const prev = (0,
|
|
289014
|
-
const next = (0,
|
|
289015
|
-
if (prev && next && (0,
|
|
289346
|
+
const prev = (0, import_wire11.parseFeedCursor)(cursor);
|
|
289347
|
+
const next = (0, import_wire11.parseFeedCursor)(page.cursor);
|
|
289348
|
+
if (prev && next && (0, import_wire11.feedCursorAdvanced)(prev, next)) cursor = page.cursor;
|
|
289016
289349
|
}
|
|
289017
289350
|
}
|
|
289018
289351
|
|
|
@@ -289205,10 +289538,14 @@ var import_contract = require("@abloatai/transaction/claims/contract");
|
|
|
289205
289538
|
var import_routes = require("@abloatai/transaction/claims/routes");
|
|
289206
289539
|
init_controlPlane();
|
|
289207
289540
|
init_config();
|
|
289541
|
+
function writeStderr(message2) {
|
|
289542
|
+
process.stderr.write(`${message2}
|
|
289543
|
+
`);
|
|
289544
|
+
}
|
|
289208
289545
|
function requireRuntimeKey() {
|
|
289209
289546
|
const { key } = resolveRuntimeApiKey();
|
|
289210
289547
|
if (!key) {
|
|
289211
|
-
|
|
289548
|
+
writeStderr(
|
|
289212
289549
|
import_picocolors27.default.red(" No runtime credential.") + import_picocolors27.default.dim(
|
|
289213
289550
|
` Run ${import_picocolors27.default.bold("npx ablo login")}, or set ${import_picocolors27.default.bold("ABLO_API_KEY")} to a runtime key.`
|
|
289214
289551
|
)
|
|
@@ -289308,10 +289645,10 @@ function describeAcquired(model, id, granted) {
|
|
|
289308
289645
|
async function holdWhile(model, id, flags, apiKey, command) {
|
|
289309
289646
|
const granted = await acquireClaim(model, id, flags, apiKey);
|
|
289310
289647
|
if (granted.status === "queued") {
|
|
289311
|
-
if (!flags.json)
|
|
289648
|
+
if (!flags.json) writeStderr(describeAcquired(model, id, granted));
|
|
289312
289649
|
await waitForGrant(granted.id, flags.ttl, apiKey);
|
|
289313
289650
|
}
|
|
289314
|
-
if (!flags.json)
|
|
289651
|
+
if (!flags.json) writeStderr(` ${import_picocolors27.default.green("\u2713")} Holding ${import_picocolors27.default.bold(`${model} ${id}`)}.`);
|
|
289315
289652
|
const everyMs = Math.max(1e3, Math.floor((0, import_contract.claimTtlMs)(flags.ttl) / 3));
|
|
289316
289653
|
const timer2 = setInterval(() => {
|
|
289317
289654
|
void beat(model, id, flags.ttl, apiKey).catch(() => {
|
|
@@ -289351,7 +289688,7 @@ async function holdWhile(model, id, flags, apiKey, command) {
|
|
|
289351
289688
|
});
|
|
289352
289689
|
});
|
|
289353
289690
|
await giveBack();
|
|
289354
|
-
if (!flags.json)
|
|
289691
|
+
if (!flags.json) writeStderr(` ${import_picocolors27.default.dim("\xB7")} ${import_picocolors27.default.dim(`Released ${model} ${id}.`)}`);
|
|
289355
289692
|
return code;
|
|
289356
289693
|
}
|
|
289357
289694
|
function renderList(rows) {
|
|
@@ -289400,7 +289737,7 @@ async function claims(argv = []) {
|
|
|
289400
289737
|
}
|
|
289401
289738
|
const [model, id] = rest;
|
|
289402
289739
|
if (model === void 0 || id === void 0) {
|
|
289403
|
-
|
|
289740
|
+
writeStderr(` ${import_picocolors27.default.red("\u2717")} Name the row: ${import_picocolors27.default.bold(`ablo claims ${verb} <model> <id>`)}.`);
|
|
289404
289741
|
process.exitCode = 1;
|
|
289405
289742
|
return;
|
|
289406
289743
|
}
|
|
@@ -289427,8 +289764,9 @@ async function claims(argv = []) {
|
|
|
289427
289764
|
else console.log(` ${import_picocolors27.default.green("\u2713")} Still holding ${import_picocolors27.default.bold(`${model} ${id}`)}.`);
|
|
289428
289765
|
return;
|
|
289429
289766
|
}
|
|
289430
|
-
|
|
289431
|
-
|
|
289767
|
+
writeStderr(` ${import_picocolors27.default.red("\u2717")} Unknown: ${import_picocolors27.default.bold(`ablo claims ${verb}`)}.`);
|
|
289768
|
+
const usage = usageFor("claims");
|
|
289769
|
+
if (usage) writeStderr(usage);
|
|
289432
289770
|
process.exitCode = 1;
|
|
289433
289771
|
}
|
|
289434
289772
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.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
|
"homepage": "https://docs.abloatai.com/cli",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@sentry/node": "^10.18.0",
|
|
44
|
-
"@abloatai/transaction": "^0.
|
|
44
|
+
"@abloatai/transaction": "^0.61.0",
|
|
45
45
|
"jiti": "^2.7.0",
|
|
46
46
|
"zod": "^4.4.3",
|
|
47
|
-
"@abloatai/humans": "^0.
|
|
47
|
+
"@abloatai/humans": "^0.61.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@ablo/product-analytics": "file:../product-analytics",
|