@abloatai/cli 0.47.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.
- package/dist/cli.cjs +562 -223
- 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
|
|
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 =
|
|
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
|
|
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,
|
|
3458
|
+
async function request(path, apiKey, init4 = {}, baseUrl2) {
|
|
3459
3459
|
const res = await fetch(`${baseUrl2 ?? apiUrl()}${path}`, {
|
|
3460
|
-
method:
|
|
3460
|
+
method: init4.method ?? "GET",
|
|
3461
3461
|
headers: {
|
|
3462
3462
|
"content-type": "application/json",
|
|
3463
3463
|
authorization: `Bearer ${apiKey}`
|
|
3464
3464
|
},
|
|
3465
|
-
...
|
|
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,
|
|
4044
|
+
line(JSON.stringify((0, import_errors6.toAbloError)(err).toJSON()));
|
|
3886
4045
|
process.exitCode = 1;
|
|
3887
4046
|
return;
|
|
3888
4047
|
}
|
|
3889
|
-
if (err instanceof
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
);
|
|
@@ -4099,9 +4262,11 @@ async function loadSchema(schemaPath, exportName) {
|
|
|
4099
4262
|
function maskKey(key) {
|
|
4100
4263
|
return key ? `${key.slice(0, 12)}\u2026` : "(none)";
|
|
4101
4264
|
}
|
|
4102
|
-
function
|
|
4103
|
-
if (code
|
|
4104
|
-
|
|
4265
|
+
function schemaPushStorageHint(code) {
|
|
4266
|
+
if (code === "no_data_source_registered") {
|
|
4267
|
+
return `This branch is not connected to your database yet. Run ${import_picocolors5.default.bold("ablo connect")} for this branch, then retry the schema push.`;
|
|
4268
|
+
}
|
|
4269
|
+
return null;
|
|
4105
4270
|
}
|
|
4106
4271
|
function schemaGitState(schemaPath) {
|
|
4107
4272
|
try {
|
|
@@ -4277,7 +4442,7 @@ async function push(argv) {
|
|
|
4277
4442
|
try {
|
|
4278
4443
|
process.loadEnvFile(args.envFile);
|
|
4279
4444
|
} catch (error) {
|
|
4280
|
-
throw new
|
|
4445
|
+
throw new import_errors7.AbloValidationError(
|
|
4281
4446
|
`could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4282
4447
|
{ code: "cli_invalid_arguments" }
|
|
4283
4448
|
);
|
|
@@ -4411,9 +4576,9 @@ async function push(argv) {
|
|
|
4411
4576
|
const serverMsg = body.message ?? body.reason;
|
|
4412
4577
|
console.error(import_picocolors5.default.red(` Forbidden${code ? ` [${code}]` : ""}: ${serverMsg ?? "permission denied"}`));
|
|
4413
4578
|
console.error(import_picocolors5.default.dim(` Push used ${import_picocolors5.default.bold(maskKey(args.apiKey))} from ${describeKeySource(keySource)}.`));
|
|
4414
|
-
const
|
|
4415
|
-
if (
|
|
4416
|
-
console.error(import_picocolors5.default.dim(` ${
|
|
4579
|
+
const storageHint = schemaPushStorageHint(code);
|
|
4580
|
+
if (storageHint) {
|
|
4581
|
+
console.error(import_picocolors5.default.dim(` ${storageHint}`));
|
|
4417
4582
|
} else if (code === "database_role_cannot_enforce_rls") {
|
|
4418
4583
|
console.error(
|
|
4419
4584
|
import_picocolors5.default.dim(
|
|
@@ -4452,17 +4617,17 @@ async function push(argv) {
|
|
|
4452
4617
|
);
|
|
4453
4618
|
}
|
|
4454
4619
|
} else {
|
|
4455
|
-
renderCliError((0,
|
|
4620
|
+
renderCliError((0, import_errors7.translateHttpError)(status2, Object.keys(body).length > 0 ? body : bodyText));
|
|
4456
4621
|
}
|
|
4457
4622
|
process.exit(1);
|
|
4458
4623
|
}
|
|
4459
|
-
var import_picocolors5,
|
|
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;
|
|
4460
4625
|
var init_push = __esm({
|
|
4461
4626
|
"src/push.ts"() {
|
|
4462
4627
|
"use strict";
|
|
4463
4628
|
init_cjs_shims();
|
|
4464
4629
|
import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
4465
|
-
|
|
4630
|
+
import_errors7 = require("@abloatai/transaction/errors");
|
|
4466
4631
|
import_credentialPolicy = require("@abloatai/transaction/auth/credentialPolicy");
|
|
4467
4632
|
import_fs4 = require("fs");
|
|
4468
4633
|
import_path3 = require("path");
|
|
@@ -4702,7 +4867,7 @@ function connectSetupSql(input) {
|
|
|
4702
4867
|
const writeRole = input.writeRole && input.writeRole.length > 0 ? input.writeRole : import_footprint.ABLO_WRITE_ROLE;
|
|
4703
4868
|
const tables = input.tables ?? [];
|
|
4704
4869
|
const schema = input.schema ?? "public";
|
|
4705
|
-
const publication = input.publication
|
|
4870
|
+
const publication = input.publication;
|
|
4706
4871
|
const qualifiedTables = tables.map((table) => `${quoteIdent(schema)}.${quoteIdent(table)}`);
|
|
4707
4872
|
const publicationTarget = tables.length > 0 ? `FOR TABLE ${qualifiedTables.join(", ")}` : "FOR ALL TABLES";
|
|
4708
4873
|
const tableList = qualifiedTables.join(", ");
|
|
@@ -4780,8 +4945,8 @@ BEGIN
|
|
|
4780
4945
|
END $$;`
|
|
4781
4946
|
];
|
|
4782
4947
|
}
|
|
4783
|
-
function reconcilePublicationPlan(current, desiredTables, opts
|
|
4784
|
-
const pub = quoteIdent(opts.publication
|
|
4948
|
+
function reconcilePublicationPlan(current, desiredTables, opts) {
|
|
4949
|
+
const pub = quoteIdent(opts.publication);
|
|
4785
4950
|
const schema = opts.schema ?? "public";
|
|
4786
4951
|
const qualified = (table) => `${quoteIdent(schema)}.${quoteIdent(table)}`;
|
|
4787
4952
|
const desiredAll = desiredTables.length === 0;
|
|
@@ -4817,8 +4982,8 @@ function reconcilePublicationPlan(current, desiredTables, opts = {}) {
|
|
|
4817
4982
|
recreated: false
|
|
4818
4983
|
};
|
|
4819
4984
|
}
|
|
4820
|
-
async function readPublicationState(sql, opts
|
|
4821
|
-
const publication = opts.publication
|
|
4985
|
+
async function readPublicationState(sql, opts) {
|
|
4986
|
+
const publication = opts.publication;
|
|
4822
4987
|
const schema = opts.schema ?? "public";
|
|
4823
4988
|
const pubRows = await sql.unsafe(
|
|
4824
4989
|
`SELECT puballtables FROM pg_publication WHERE pubname = $1`,
|
|
@@ -4833,8 +4998,8 @@ async function readPublicationState(sql, opts = {}) {
|
|
|
4833
4998
|
);
|
|
4834
4999
|
return { exists: true, allTables: false, tables: tableRows.map((r2) => r2.tablename) };
|
|
4835
5000
|
}
|
|
4836
|
-
async function probeReadiness(sql, opts
|
|
4837
|
-
const publication = opts.publication
|
|
5001
|
+
async function probeReadiness(sql, opts) {
|
|
5002
|
+
const publication = opts.publication;
|
|
4838
5003
|
const schema = opts.schema ?? "public";
|
|
4839
5004
|
const coordinated = opts.coordinatedTables && opts.coordinatedTables.length > 0 ? new Set(opts.coordinatedTables) : null;
|
|
4840
5005
|
const items = [];
|
|
@@ -4981,6 +5146,18 @@ async function registerDirectDataSource(opts) {
|
|
|
4981
5146
|
` This deployment can\u2019t accept connection strings \u2014 use a self-hosted/hosted engine, or the signed endpoint fallback.`
|
|
4982
5147
|
)
|
|
4983
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.")}`);
|
|
4984
5161
|
} else if (err.code === "database_not_replication_ready" || err.code === "data_source_blocked") {
|
|
4985
5162
|
for (const f of failures) {
|
|
4986
5163
|
const { label, fix } = describeRemoteFailure(f);
|
|
@@ -5011,9 +5188,9 @@ async function registerDirectDataSource(opts) {
|
|
|
5011
5188
|
}
|
|
5012
5189
|
console.error(
|
|
5013
5190
|
import_picocolors7.default.dim(
|
|
5014
|
-
` Ablo's servers must be able to reach this database
|
|
5015
|
-
|
|
5016
|
-
|
|
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.`
|
|
5017
5194
|
)
|
|
5018
5195
|
);
|
|
5019
5196
|
}
|
|
@@ -5075,9 +5252,9 @@ async function deregisterDataSource(opts) {
|
|
|
5075
5252
|
});
|
|
5076
5253
|
return { removed: true, response };
|
|
5077
5254
|
} catch (err) {
|
|
5078
|
-
if (err instanceof
|
|
5079
|
-
if (err instanceof
|
|
5080
|
-
throw new
|
|
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(
|
|
5081
5258
|
`${err.message}. Disconnecting needs a branch-bound secret key (sk_\u2026).`,
|
|
5082
5259
|
{
|
|
5083
5260
|
code: "forbidden",
|
|
@@ -5133,7 +5310,7 @@ async function disconnect(argv) {
|
|
|
5133
5310
|
console.log(DISCONNECT_USAGE);
|
|
5134
5311
|
return;
|
|
5135
5312
|
} else {
|
|
5136
|
-
throw new
|
|
5313
|
+
throw new import_errors9.AbloValidationError(
|
|
5137
5314
|
`unknown flag: ${arg} \u2014 see \`ablo connect deregister --help\``,
|
|
5138
5315
|
{ code: "cli_invalid_arguments" }
|
|
5139
5316
|
);
|
|
@@ -5148,7 +5325,7 @@ async function disconnect(argv) {
|
|
|
5148
5325
|
try {
|
|
5149
5326
|
process.loadEnvFile(envFile);
|
|
5150
5327
|
} catch (error) {
|
|
5151
|
-
throw new
|
|
5328
|
+
throw new import_errors9.AbloValidationError(
|
|
5152
5329
|
`could not load --env-file ${envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5153
5330
|
{ code: "cli_invalid_arguments" }
|
|
5154
5331
|
);
|
|
@@ -5156,7 +5333,7 @@ async function disconnect(argv) {
|
|
|
5156
5333
|
}
|
|
5157
5334
|
const selected = keyEnv ? readProjectEnvVariable(keyEnv) : null;
|
|
5158
5335
|
if (keyEnv && !selected) {
|
|
5159
|
-
throw new
|
|
5336
|
+
throw new import_errors9.AbloAuthenticationError(
|
|
5160
5337
|
`No value named ${keyEnv} was found in the process environment, .env.local, or .env.`,
|
|
5161
5338
|
{ code: "cli_api_key_missing" }
|
|
5162
5339
|
);
|
|
@@ -5168,7 +5345,7 @@ async function disconnect(argv) {
|
|
|
5168
5345
|
const apiKey = resolved.key;
|
|
5169
5346
|
const keySource = resolved.source ?? "stored";
|
|
5170
5347
|
if (!apiKey) {
|
|
5171
|
-
throw new
|
|
5348
|
+
throw new import_errors9.AbloAuthenticationError(
|
|
5172
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>`.",
|
|
5173
5350
|
{ code: "cli_api_key_missing" }
|
|
5174
5351
|
);
|
|
@@ -5182,7 +5359,7 @@ async function disconnect(argv) {
|
|
|
5182
5359
|
`);
|
|
5183
5360
|
if (!skipConfirm) {
|
|
5184
5361
|
if (!process.stdout.isTTY) {
|
|
5185
|
-
throw new
|
|
5362
|
+
throw new import_errors9.AbloValidationError(
|
|
5186
5363
|
"This session has no terminal to confirm in. Re-run with --yes to disconnect non-interactively.",
|
|
5187
5364
|
{ code: "cli_invalid_arguments" }
|
|
5188
5365
|
);
|
|
@@ -5205,14 +5382,14 @@ async function disconnect(argv) {
|
|
|
5205
5382
|
}
|
|
5206
5383
|
renderDisconnected(outcome.response, project, branchLabel);
|
|
5207
5384
|
}
|
|
5208
|
-
var import_picocolors8,
|
|
5385
|
+
var import_picocolors8, import_errors9, import_wire4, DISCONNECT_USAGE;
|
|
5209
5386
|
var init_disconnect = __esm({
|
|
5210
5387
|
"src/disconnect.ts"() {
|
|
5211
5388
|
"use strict";
|
|
5212
5389
|
init_cjs_shims();
|
|
5213
5390
|
import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
5214
5391
|
init_dist2();
|
|
5215
|
-
|
|
5392
|
+
import_errors9 = require("@abloatai/transaction/errors");
|
|
5216
5393
|
import_wire4 = require("@abloatai/transaction/wire");
|
|
5217
5394
|
init_config();
|
|
5218
5395
|
init_dbRole();
|
|
@@ -5465,7 +5642,7 @@ function blockers(input) {
|
|
|
5465
5642
|
}
|
|
5466
5643
|
if (input.dataSource.kind === "none") {
|
|
5467
5644
|
found.push({
|
|
5468
|
-
problem: "no database is connected to this
|
|
5645
|
+
problem: "no database is connected to this branch, so writes are held",
|
|
5469
5646
|
fix: "connect one with `ablo connect apply`"
|
|
5470
5647
|
});
|
|
5471
5648
|
}
|
|
@@ -5517,7 +5694,7 @@ function connectApplyPlan(input) {
|
|
|
5517
5694
|
const writeRole = input.writeRole && input.writeRole.length > 0 ? input.writeRole : import_footprint.ABLO_WRITE_ROLE;
|
|
5518
5695
|
const tables = input.tables ?? [];
|
|
5519
5696
|
const schema = input.schema ?? "public";
|
|
5520
|
-
const publication = input.publication
|
|
5697
|
+
const publication = input.publication;
|
|
5521
5698
|
const provider = input.provider ?? "generic";
|
|
5522
5699
|
const recipe = connectSetupSql({ tables, role, writeRole, schema, publication });
|
|
5523
5700
|
const isWal = (s) => s.startsWith("ALTER SYSTEM SET wal_level");
|
|
@@ -5733,7 +5910,7 @@ function rotateWithoutConnection(input) {
|
|
|
5733
5910
|
}
|
|
5734
5911
|
if (!input.known || input.planeHasConnection) return null;
|
|
5735
5912
|
if (input.existingRoles.length > 0) return null;
|
|
5736
|
-
return "This
|
|
5913
|
+
return "This branch has no connected database and Ablo's roles are not in this database, so there is no credential to re-key. Connecting for the first time is `ablo connect apply`, which creates the roles and registers them in one run.";
|
|
5737
5914
|
}
|
|
5738
5915
|
async function locateExistingConnection(input) {
|
|
5739
5916
|
const result = await tryControlPlane({
|
|
@@ -5820,7 +5997,7 @@ async function runConnectApply(args) {
|
|
|
5820
5997
|
const verb = rotating ? "connect rotate" : "connect apply";
|
|
5821
5998
|
let adminUrl = args.url ?? readProjectAdminDatabaseUrl();
|
|
5822
5999
|
if (!adminUrl) {
|
|
5823
|
-
throw new
|
|
6000
|
+
throw new import_errors10.AbloValidationError(
|
|
5824
6001
|
"No admin connection string. Pass --url <admin-conn> (or set DATABASE_URL) and re-run.",
|
|
5825
6002
|
{ code: "cli_database_url_missing" }
|
|
5826
6003
|
);
|
|
@@ -5837,7 +6014,7 @@ async function runConnectApply(args) {
|
|
|
5837
6014
|
const loggedIn = resolveManagementKey() !== void 0;
|
|
5838
6015
|
const ambient = ambientEnvKeyNote();
|
|
5839
6016
|
const retry = `npx ablo connect ${rotating ? "rotate" : "apply"} --env-file .env.local --yes`;
|
|
5840
|
-
throw new
|
|
6017
|
+
throw new import_errors10.AbloAuthenticationError(
|
|
5841
6018
|
loggedIn ? `You are logged in, but connect needs a branch-bound runtime key.
|
|
5842
6019
|
|
|
5843
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 ? `
|
|
@@ -5902,22 +6079,6 @@ ${ambient}` : ""}`,
|
|
|
5902
6079
|
` + import_picocolors11.default.dim(
|
|
5903
6080
|
` Replication cannot run over a pooler, so if that is what this is, point ${import_picocolors11.default.bold("--url")}
|
|
5904
6081
|
at the database itself. Carrying on, since a database can use this port too.
|
|
5905
|
-
`
|
|
5906
|
-
)
|
|
5907
|
-
);
|
|
5908
|
-
}
|
|
5909
|
-
const coordinatedTables = await schemaDeclaredTables() ?? [];
|
|
5910
|
-
const tables = args.tables.length > 0 ? args.tables : coordinatedTables;
|
|
5911
|
-
if (tables.length === 0) {
|
|
5912
|
-
throw new import_errors9.AbloValidationError(
|
|
5913
|
-
`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.`,
|
|
5914
|
-
{ code: "cli_invalid_arguments" }
|
|
5915
|
-
);
|
|
5916
|
-
}
|
|
5917
|
-
if (args.tables.length === 0) {
|
|
5918
|
-
console.log(
|
|
5919
|
-
import_picocolors11.default.dim(
|
|
5920
|
-
` 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)
|
|
5921
6082
|
`
|
|
5922
6083
|
)
|
|
5923
6084
|
);
|
|
@@ -5934,7 +6095,7 @@ ${ambient}` : ""}`,
|
|
|
5934
6095
|
}
|
|
5935
6096
|
const confirmed = connectTarget?.confirmed;
|
|
5936
6097
|
if (!confirmed?.branchId) {
|
|
5937
|
-
throw new
|
|
6098
|
+
throw new import_errors10.AbloConnectionError(
|
|
5938
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.",
|
|
5939
6100
|
{ code: "cli_database_unreachable" }
|
|
5940
6101
|
);
|
|
@@ -5965,6 +6126,22 @@ ${ambient}` : ""}`,
|
|
|
5965
6126
|
);
|
|
5966
6127
|
process.exit(1);
|
|
5967
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
|
+
}
|
|
5968
6145
|
let rotatePlane = null;
|
|
5969
6146
|
if (rotating) {
|
|
5970
6147
|
const state = await fetchDataSourceState(apiBaseUrl(), apiKey).catch(
|
|
@@ -6000,7 +6177,7 @@ ${ambient}` : ""}`,
|
|
|
6000
6177
|
} catch (err) {
|
|
6001
6178
|
await admin.end({ timeout: 2 }).catch(() => void 0);
|
|
6002
6179
|
const pg = err ?? {};
|
|
6003
|
-
throw new
|
|
6180
|
+
throw new import_errors10.AbloConnectionError(`Couldn't connect: ${pg.message ?? String(err)}`, {
|
|
6004
6181
|
code: "cli_database_unreachable",
|
|
6005
6182
|
details: { target },
|
|
6006
6183
|
cause: err
|
|
@@ -6257,7 +6434,7 @@ ${ambient}` : ""}`,
|
|
|
6257
6434
|
}
|
|
6258
6435
|
process.exit(outcome.exitCode);
|
|
6259
6436
|
}
|
|
6260
|
-
var import_picocolors11,
|
|
6437
|
+
var import_picocolors11, import_errors10, import_footprint2, ROTATE_STRANDED_CREDENTIALS_NOTICE;
|
|
6261
6438
|
var init_connectApply = __esm({
|
|
6262
6439
|
"src/connectApply.ts"() {
|
|
6263
6440
|
"use strict";
|
|
@@ -6265,7 +6442,7 @@ var init_connectApply = __esm({
|
|
|
6265
6442
|
import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
6266
6443
|
init_src();
|
|
6267
6444
|
init_dist2();
|
|
6268
|
-
|
|
6445
|
+
import_errors10 = require("@abloatai/transaction/errors");
|
|
6269
6446
|
import_footprint2 = require("@abloatai/transaction/footprint");
|
|
6270
6447
|
init_connectSetup();
|
|
6271
6448
|
init_connectOwnership();
|
|
@@ -6329,7 +6506,7 @@ function parseConnectArgs(argv) {
|
|
|
6329
6506
|
locate = true;
|
|
6330
6507
|
break;
|
|
6331
6508
|
default:
|
|
6332
|
-
throw new
|
|
6509
|
+
throw new import_errors11.AbloValidationError(
|
|
6333
6510
|
`unknown connect subcommand: ${lead} (expected register, deregister, check, apply, rotate, resnapshot, scan, locate)`,
|
|
6334
6511
|
{ code: "cli_invalid_arguments" }
|
|
6335
6512
|
);
|
|
@@ -6372,7 +6549,7 @@ function parseConnectArgs(argv) {
|
|
|
6372
6549
|
case "--route": {
|
|
6373
6550
|
const value = argv[++i] ?? "";
|
|
6374
6551
|
if (!DIRECT_DATA_SOURCE_ROUTES.includes(value)) {
|
|
6375
|
-
throw new
|
|
6552
|
+
throw new import_errors11.AbloValidationError(
|
|
6376
6553
|
`invalid direct route: ${value || "(missing)"} (expected ${DIRECT_DATA_SOURCE_ROUTES.join(", ")})`,
|
|
6377
6554
|
{ code: "cli_invalid_arguments" }
|
|
6378
6555
|
);
|
|
@@ -6381,11 +6558,11 @@ function parseConnectArgs(argv) {
|
|
|
6381
6558
|
break;
|
|
6382
6559
|
}
|
|
6383
6560
|
default:
|
|
6384
|
-
throw new
|
|
6561
|
+
throw new import_errors11.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
6385
6562
|
}
|
|
6386
6563
|
}
|
|
6387
6564
|
if (role === writeRole) {
|
|
6388
|
-
throw new
|
|
6565
|
+
throw new import_errors11.AbloValidationError("replication and write roles must be different", {
|
|
6389
6566
|
code: "cli_invalid_arguments"
|
|
6390
6567
|
});
|
|
6391
6568
|
}
|
|
@@ -6409,12 +6586,15 @@ function parseConnectArgs(argv) {
|
|
|
6409
6586
|
manual
|
|
6410
6587
|
};
|
|
6411
6588
|
}
|
|
6412
|
-
function printConnectRecipe(args) {
|
|
6589
|
+
function printConnectRecipe(args, footprint) {
|
|
6590
|
+
const role = args.role === import_footprint.ABLO_REPLICATION_ROLE ? footprint.replicationRole : args.role;
|
|
6591
|
+
const writeRole = args.writeRole === import_footprint.ABLO_WRITE_ROLE ? footprint.writeRole : args.writeRole;
|
|
6413
6592
|
const sql = connectSetupSql({
|
|
6414
6593
|
tables: args.tables,
|
|
6415
|
-
role
|
|
6416
|
-
writeRole
|
|
6417
|
-
schema: args.schema
|
|
6594
|
+
role,
|
|
6595
|
+
writeRole,
|
|
6596
|
+
schema: args.schema,
|
|
6597
|
+
publication: footprint.publication
|
|
6418
6598
|
});
|
|
6419
6599
|
console.log(
|
|
6420
6600
|
`
|
|
@@ -6465,7 +6645,7 @@ function printConnectRecipe(args) {
|
|
|
6465
6645
|
console.log(
|
|
6466
6646
|
import_picocolors12.default.dim(
|
|
6467
6647
|
` On Amazon RDS, the REPLICATION attribute is granted, not set directly:
|
|
6468
|
-
${import_picocolors12.default.bold(`GRANT rds_replication TO ${quoteIdent(
|
|
6648
|
+
${import_picocolors12.default.bold(`GRANT rds_replication TO ${quoteIdent(role)};`)}`
|
|
6469
6649
|
)
|
|
6470
6650
|
);
|
|
6471
6651
|
console.log(
|
|
@@ -6489,8 +6669,8 @@ function printConnectRecipe(args) {
|
|
|
6489
6669
|
`
|
|
6490
6670
|
${import_picocolors12.default.bold("5.")} Register the two roles with Ablo. Set them just long enough to register \u2014
|
|
6491
6671
|
Ablo holds them from here, so your app keeps only ${import_picocolors12.default.bold("ABLO_API_KEY")}:
|
|
6492
|
-
${import_picocolors12.default.bold("ABLO_REPLICATION_DATABASE_URL")} ${import_picocolors12.default.dim(`\u2192 ${
|
|
6493
|
-
${import_picocolors12.default.bold("ABLO_WRITE_DATABASE_URL")} ${import_picocolors12.default.dim(`\u2192 ${
|
|
6672
|
+
${import_picocolors12.default.bold("ABLO_REPLICATION_DATABASE_URL")} ${import_picocolors12.default.dim(`\u2192 ${role} (replication only)`)}
|
|
6673
|
+
${import_picocolors12.default.bold("ABLO_WRITE_DATABASE_URL")} ${import_picocolors12.default.dim(`\u2192 ${writeRole} (DML only)`)}
|
|
6494
6674
|
${import_picocolors12.default.cyan("npx ablo connect register")}
|
|
6495
6675
|
`
|
|
6496
6676
|
);
|
|
@@ -6518,9 +6698,9 @@ function printCheckItem(item) {
|
|
|
6518
6698
|
}
|
|
6519
6699
|
}
|
|
6520
6700
|
}
|
|
6521
|
-
async function probeDirectWriteReadiness(sql, opts
|
|
6701
|
+
async function probeDirectWriteReadiness(sql, opts) {
|
|
6522
6702
|
const schema = opts.schema ?? "public";
|
|
6523
|
-
const publication = opts.publication
|
|
6703
|
+
const publication = opts.publication;
|
|
6524
6704
|
const items = [];
|
|
6525
6705
|
const roleRows = await sql.unsafe(
|
|
6526
6706
|
`SELECT rolname, rolsuper, rolbypassrls, rolcreatedb, rolcreaterole, rolreplication
|
|
@@ -6635,6 +6815,12 @@ async function probeDirectWriteReadiness(sql, opts = {}) {
|
|
|
6635
6815
|
}
|
|
6636
6816
|
async function auditTenantSyncInfra(sql, opts = {}) {
|
|
6637
6817
|
const artifacts = [];
|
|
6818
|
+
const branchScopedTemplates = /* @__PURE__ */ new Set([
|
|
6819
|
+
import_footprint.ABLO_PUBLICATION,
|
|
6820
|
+
import_footprint3.ABLO_REPLICATION_SLOT,
|
|
6821
|
+
import_footprint.ABLO_REPLICATION_ROLE,
|
|
6822
|
+
import_footprint.ABLO_WRITE_ROLE
|
|
6823
|
+
]);
|
|
6638
6824
|
for (const artifact of import_footprint3.ABLO_FOOTPRINT) {
|
|
6639
6825
|
const name = opts.names ? artifact.name === import_footprint.ABLO_PUBLICATION ? opts.names.publication : artifact.name === import_footprint3.ABLO_REPLICATION_SLOT ? opts.names.slot : artifact.name === import_footprint.ABLO_REPLICATION_ROLE ? opts.names.replicationRole : artifact.name === import_footprint.ABLO_WRITE_ROLE ? opts.names.writeRole : artifact.name : artifact.name;
|
|
6640
6826
|
const key = artifact.kind === "table" || artifact.kind === "type" ? `${artifact.retired ? "public" : opts.schema ?? "public"}.${name}` : name;
|
|
@@ -6647,7 +6833,7 @@ async function auditTenantSyncInfra(sql, opts = {}) {
|
|
|
6647
6833
|
present: rows[0]?.present === true,
|
|
6648
6834
|
purpose: artifact.purpose,
|
|
6649
6835
|
...artifact.hazard ? { hazard: artifact.hazard } : {},
|
|
6650
|
-
...artifact.retired ? { retired: true } : {}
|
|
6836
|
+
...artifact.retired || !opts.names && branchScopedTemplates.has(artifact.name) ? { retired: true } : {}
|
|
6651
6837
|
});
|
|
6652
6838
|
}
|
|
6653
6839
|
return artifacts;
|
|
@@ -6672,7 +6858,7 @@ function requireScopedUrl(kind, verb) {
|
|
|
6672
6858
|
);
|
|
6673
6859
|
process.exit(1);
|
|
6674
6860
|
}
|
|
6675
|
-
async function probeAndReport(dbUrl, kind
|
|
6861
|
+
async function probeAndReport(dbUrl, kind, opts) {
|
|
6676
6862
|
const sql = src_default(dbUrl, { max: 1, prepare: false, connect_timeout: 10, onnotice: () => {
|
|
6677
6863
|
} });
|
|
6678
6864
|
let items;
|
|
@@ -6683,7 +6869,7 @@ async function probeAndReport(dbUrl, kind = "replication", opts = {}) {
|
|
|
6683
6869
|
const dial = dialFailureReason(err);
|
|
6684
6870
|
if (dial) return { kind: "no-dial", reason: dial };
|
|
6685
6871
|
const pg = err ?? {};
|
|
6686
|
-
throw new
|
|
6872
|
+
throw new import_errors11.AbloConnectionError(`Couldn't read the database: ${pg.message ?? String(err)}`, {
|
|
6687
6873
|
code: "cli_database_unreachable",
|
|
6688
6874
|
cause: err
|
|
6689
6875
|
});
|
|
@@ -6701,7 +6887,7 @@ async function runCheck() {
|
|
|
6701
6887
|
const apiKey = resolveRuntimeApiKey().key;
|
|
6702
6888
|
if (!apiKey) {
|
|
6703
6889
|
const ambient = ambientEnvKeyNote();
|
|
6704
|
-
throw new
|
|
6890
|
+
throw new import_errors11.AbloAuthenticationError(
|
|
6705
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 ? `
|
|
6706
6892
|
|
|
6707
6893
|
${ambient}` : ""}`,
|
|
@@ -6713,7 +6899,7 @@ ${ambient}` : ""}`,
|
|
|
6713
6899
|
if (!result.ok) {
|
|
6714
6900
|
if (result.code === "no_data_source_registered") {
|
|
6715
6901
|
console.error(
|
|
6716
|
-
` ${import_picocolors12.default.yellow("\u2014")}
|
|
6902
|
+
` ${import_picocolors12.default.yellow("\u2014")} This branch is not connected to a database yet, so there's nothing to check.
|
|
6717
6903
|
` + import_picocolors12.default.dim(
|
|
6718
6904
|
` Connect one with ${import_picocolors12.default.bold("ablo connect apply")}, then re-run ${import_picocolors12.default.bold("ablo connect check")}.
|
|
6719
6905
|
`
|
|
@@ -6738,8 +6924,9 @@ ${ambient}` : ""}`,
|
|
|
6738
6924
|
);
|
|
6739
6925
|
console.error(
|
|
6740
6926
|
import_picocolors12.default.dim(
|
|
6741
|
-
`
|
|
6742
|
-
|
|
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.
|
|
6743
6930
|
`
|
|
6744
6931
|
)
|
|
6745
6932
|
);
|
|
@@ -6793,7 +6980,7 @@ async function runRegister(args) {
|
|
|
6793
6980
|
const apiKey = resolveMutationApiKey();
|
|
6794
6981
|
if (!apiKey) {
|
|
6795
6982
|
const ambient = ambientEnvKeyNote();
|
|
6796
|
-
throw new
|
|
6983
|
+
throw new import_errors11.AbloAuthenticationError(
|
|
6797
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 ? `
|
|
6798
6985
|
|
|
6799
6986
|
${ambient}` : ""}`,
|
|
@@ -6805,13 +6992,32 @@ ${ambient}` : ""}`,
|
|
|
6805
6992
|
${brand("ablo")} ${import_picocolors12.default.dim("connect register")} ${import_picocolors12.default.dim("register a direct DataSource")}
|
|
6806
6993
|
`
|
|
6807
6994
|
);
|
|
6995
|
+
const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
|
|
6996
|
+
const confirmed = target.confirmed;
|
|
6997
|
+
if (!confirmed?.branchId) {
|
|
6998
|
+
throw new import_errors11.AbloValidationError(
|
|
6999
|
+
"This key is not bound to a branch, so Ablo cannot validate isolated database objects safely.",
|
|
7000
|
+
{ code: "cli_database_unreachable" }
|
|
7001
|
+
);
|
|
7002
|
+
}
|
|
7003
|
+
const publication = (0, import_footprint3.footprintNamesFor)({
|
|
7004
|
+
organizationId: confirmed.organizationId,
|
|
7005
|
+
branchId: confirmed.branchId,
|
|
7006
|
+
...confirmed.projectId ? { projectId: confirmed.projectId } : {}
|
|
7007
|
+
}).publication;
|
|
6808
7008
|
console.log(` ${import_picocolors12.default.bold("Replication role")}
|
|
6809
7009
|
`);
|
|
6810
|
-
const replication = await probeAndReport(dbUrl, "replication", {
|
|
7010
|
+
const replication = await probeAndReport(dbUrl, "replication", {
|
|
7011
|
+
schema: args.schema,
|
|
7012
|
+
publication
|
|
7013
|
+
});
|
|
6811
7014
|
console.log(`
|
|
6812
7015
|
${import_picocolors12.default.bold("Direct-write role")}
|
|
6813
7016
|
`);
|
|
6814
|
-
const write = await probeAndReport(writeDbUrl, "write", {
|
|
7017
|
+
const write = await probeAndReport(writeDbUrl, "write", {
|
|
7018
|
+
schema: args.schema,
|
|
7019
|
+
publication
|
|
7020
|
+
});
|
|
6815
7021
|
const noDial = [
|
|
6816
7022
|
replication.kind === "no-dial" ? `replication: ${replication.reason}` : null,
|
|
6817
7023
|
write.kind === "no-dial" ? `write: ${write.reason}` : null
|
|
@@ -6871,7 +7077,7 @@ async function runScan(args) {
|
|
|
6871
7077
|
} catch (err) {
|
|
6872
7078
|
const pg = err ?? {};
|
|
6873
7079
|
await sql.end({ timeout: 2 });
|
|
6874
|
-
throw new
|
|
7080
|
+
throw new import_errors11.AbloConnectionError(`Couldn't audit the database: ${pg.message ?? String(err)}`, {
|
|
6875
7081
|
code: "cli_database_unreachable",
|
|
6876
7082
|
cause: err
|
|
6877
7083
|
});
|
|
@@ -6918,12 +7124,12 @@ async function runScan(args) {
|
|
|
6918
7124
|
async function runLocate(args) {
|
|
6919
7125
|
console.log(
|
|
6920
7126
|
`
|
|
6921
|
-
${brand("ablo")} ${import_picocolors12.default.dim("connect locate")} ${import_picocolors12.default.dim("which
|
|
7127
|
+
${brand("ablo")} ${import_picocolors12.default.dim("connect locate")} ${import_picocolors12.default.dim("which branch is connected to this database")}
|
|
6922
7128
|
`
|
|
6923
7129
|
);
|
|
6924
7130
|
const url = args.url ?? readProjectAdminDatabaseUrl();
|
|
6925
7131
|
if (!url) {
|
|
6926
|
-
throw new
|
|
7132
|
+
throw new import_errors11.AbloValidationError(
|
|
6927
7133
|
"Locating needs a connection string to identify the database. Pass --url <conn> (or set DATABASE_URL) and re-run.",
|
|
6928
7134
|
{ code: "cli_database_url_missing" }
|
|
6929
7135
|
);
|
|
@@ -6931,7 +7137,7 @@ async function runLocate(args) {
|
|
|
6931
7137
|
const apiKey = resolveRuntimeApiKey().key;
|
|
6932
7138
|
if (!apiKey) {
|
|
6933
7139
|
const ambient = ambientEnvKeyNote();
|
|
6934
|
-
throw new
|
|
7140
|
+
throw new import_errors11.AbloAuthenticationError(
|
|
6935
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 ? `
|
|
6936
7142
|
|
|
6937
7143
|
${ambient}` : ""}`,
|
|
@@ -6961,7 +7167,7 @@ ${ambient}` : ""}`,
|
|
|
6961
7167
|
}
|
|
6962
7168
|
if (!answer.held) {
|
|
6963
7169
|
console.log(
|
|
6964
|
-
` ${import_picocolors12.default.green("\u2713")} No
|
|
7170
|
+
` ${import_picocolors12.default.green("\u2713")} No branch is connected to ${import_picocolors12.default.bold(`${label}/${args.schema}`)} \u2014 ${import_picocolors12.default.bold("ablo connect apply")} can register it here.
|
|
6965
7171
|
`
|
|
6966
7172
|
);
|
|
6967
7173
|
return;
|
|
@@ -6972,9 +7178,9 @@ ${ambient}` : ""}`,
|
|
|
6972
7178
|
);
|
|
6973
7179
|
console.log(
|
|
6974
7180
|
import_picocolors12.default.dim(
|
|
6975
|
-
` Ablo
|
|
7181
|
+
` Ablo connects one branch to each database schema. To move this schema, disconnect it there
|
|
6976
7182
|
first \u2014 run `
|
|
6977
|
-
) + import_picocolors12.default.cyan("ablo connect deregister") + import_picocolors12.default.dim(` with a key for that
|
|
7183
|
+
) + import_picocolors12.default.cyan("ablo connect deregister") + import_picocolors12.default.dim(` with a key for that branch, then connect here.
|
|
6978
7184
|
`) + import_picocolors12.default.dim(` Confirm a candidate key first with `) + import_picocolors12.default.bold("ablo whoami --key-env <NAME>") + import_picocolors12.default.dim(`.
|
|
6979
7185
|
`) + import_picocolors12.default.dim(` Match the project id to a name with `) + import_picocolors12.default.bold("ablo projects list --json") + import_picocolors12.default.dim(".") + "\n"
|
|
6980
7186
|
);
|
|
@@ -6982,7 +7188,7 @@ ${ambient}` : ""}`,
|
|
|
6982
7188
|
async function runResnapshot() {
|
|
6983
7189
|
const apiKey = resolveMutationApiKey();
|
|
6984
7190
|
if (!apiKey) {
|
|
6985
|
-
throw new
|
|
7191
|
+
throw new import_errors11.AbloAuthenticationError(
|
|
6986
7192
|
"No branch-bound secret key found. Set ABLO_API_KEY to the sk_ key for the branch to resnapshot.",
|
|
6987
7193
|
{ code: "cli_api_key_missing" }
|
|
6988
7194
|
);
|
|
@@ -7027,7 +7233,7 @@ async function connect(argv) {
|
|
|
7027
7233
|
try {
|
|
7028
7234
|
process.loadEnvFile(args.envFile);
|
|
7029
7235
|
} catch (error) {
|
|
7030
|
-
throw new
|
|
7236
|
+
throw new import_errors11.AbloValidationError(
|
|
7031
7237
|
`could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
7032
7238
|
{ code: "cli_invalid_arguments" }
|
|
7033
7239
|
);
|
|
@@ -7065,14 +7271,36 @@ async function connect(argv) {
|
|
|
7065
7271
|
await runConnectApply2(args);
|
|
7066
7272
|
return;
|
|
7067
7273
|
}
|
|
7068
|
-
|
|
7274
|
+
const apiKey = resolveRuntimeApiKey().key;
|
|
7275
|
+
if (!apiKey) {
|
|
7276
|
+
throw new import_errors11.AbloAuthenticationError(
|
|
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`.",
|
|
7278
|
+
{ code: "cli_api_key_missing" }
|
|
7279
|
+
);
|
|
7280
|
+
}
|
|
7281
|
+
const target = await resolveTarget({ url: apiBaseUrl(), apiKey, keySource: "env" });
|
|
7282
|
+
const confirmed = target.confirmed;
|
|
7283
|
+
if (!confirmed?.branchId) {
|
|
7284
|
+
throw new import_errors11.AbloValidationError(
|
|
7285
|
+
"This key is not bound to a branch, so Ablo cannot derive isolated database object names safely.",
|
|
7286
|
+
{ code: "cli_database_unreachable" }
|
|
7287
|
+
);
|
|
7288
|
+
}
|
|
7289
|
+
printConnectRecipe(
|
|
7290
|
+
args,
|
|
7291
|
+
(0, import_footprint3.footprintNamesFor)({
|
|
7292
|
+
organizationId: confirmed.organizationId,
|
|
7293
|
+
branchId: confirmed.branchId,
|
|
7294
|
+
...confirmed.projectId ? { projectId: confirmed.projectId } : {}
|
|
7295
|
+
})
|
|
7296
|
+
);
|
|
7069
7297
|
}
|
|
7070
|
-
var
|
|
7298
|
+
var import_errors11, import_picocolors12, import_footprint3, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
|
|
7071
7299
|
var init_connect = __esm({
|
|
7072
7300
|
"src/connect.ts"() {
|
|
7073
7301
|
"use strict";
|
|
7074
7302
|
init_cjs_shims();
|
|
7075
|
-
|
|
7303
|
+
import_errors11 = require("@abloatai/transaction/errors");
|
|
7076
7304
|
import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
7077
7305
|
init_src();
|
|
7078
7306
|
import_footprint3 = require("@abloatai/transaction/footprint");
|
|
@@ -7105,7 +7333,7 @@ var init_connect = __esm({
|
|
|
7105
7333
|
npx ablo connect rotate New passwords for both logins, then re-register
|
|
7106
7334
|
npx ablo connect resnapshot Recreate only the slot and reload existing rows
|
|
7107
7335
|
npx ablo connect scan List anything Ablo ever set up in your database (read-only, never drops)
|
|
7108
|
-
npx ablo connect locate See which
|
|
7336
|
+
npx ablo connect locate See which branch is connected to this database (read-only; nothing is changed)
|
|
7109
7337
|
|
|
7110
7338
|
Running it: bare \`ablo connect\` sets everything up for you \u2014 creating the two
|
|
7111
7339
|
scoped logins, sharing your tables, and registering \u2014 whenever it finds a
|
|
@@ -12800,11 +13028,11 @@ var require_typescript = __commonJS({
|
|
|
12800
13028
|
function compareTextSpans(a, b4) {
|
|
12801
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);
|
|
12802
13030
|
}
|
|
12803
|
-
function maxBy(arr,
|
|
13031
|
+
function maxBy(arr, init4, mapper) {
|
|
12804
13032
|
for (let i = 0; i < arr.length; i++) {
|
|
12805
|
-
|
|
13033
|
+
init4 = Math.max(init4, mapper(arr[i]));
|
|
12806
13034
|
}
|
|
12807
|
-
return
|
|
13035
|
+
return init4;
|
|
12808
13036
|
}
|
|
12809
13037
|
function min(items, compare) {
|
|
12810
13038
|
return reduceLeft(items, (x2, y3) => compare(x2, y3) === -1 ? x2 : y3);
|
|
@@ -17303,8 +17531,8 @@ ${lanes.join("\n")}
|
|
|
17303
17531
|
function sysLog(s) {
|
|
17304
17532
|
return curSysLog(s);
|
|
17305
17533
|
}
|
|
17306
|
-
function setSysLog(
|
|
17307
|
-
curSysLog =
|
|
17534
|
+
function setSysLog(logger2) {
|
|
17535
|
+
curSysLog = logger2;
|
|
17308
17536
|
}
|
|
17309
17537
|
function createDirectoryWatcherSupportingRecursive({
|
|
17310
17538
|
watchDirectory,
|
|
@@ -28403,8 +28631,8 @@ ${lanes.join("\n")}
|
|
|
28403
28631
|
return node.initializer;
|
|
28404
28632
|
}
|
|
28405
28633
|
function getDeclaredExpandoInitializer(node) {
|
|
28406
|
-
const
|
|
28407
|
-
return
|
|
28634
|
+
const init4 = getEffectiveInitializer(node);
|
|
28635
|
+
return init4 && getExpandoInitializer(init4, isPrototypeAccess(node.name));
|
|
28408
28636
|
}
|
|
28409
28637
|
function hasExpandoValueProperty(node, isPrototypeAssignment) {
|
|
28410
28638
|
return forEach(node.properties, (p2) => isPropertyAssignment(p2) && isIdentifier2(p2.name) && p2.name.escapedText === "value" && p2.initializer && getExpandoInitializer(p2.initializer, isPrototypeAssignment));
|
|
@@ -61991,11 +62219,11 @@ ${lanes.join("\n")}
|
|
|
61991
62219
|
if (node && isCallExpression(node)) {
|
|
61992
62220
|
return !!getAssignedExpandoInitializer(node);
|
|
61993
62221
|
}
|
|
61994
|
-
let
|
|
61995
|
-
|
|
61996
|
-
if (
|
|
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) {
|
|
61997
62225
|
const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node) ? node.name : isBinaryExpression(node) ? node.left : node);
|
|
61998
|
-
return !!getExpandoInitializer(isBinaryExpression(
|
|
62226
|
+
return !!getExpandoInitializer(isBinaryExpression(init4) && (init4.operatorToken.kind === 57 || init4.operatorToken.kind === 61) ? init4.right : init4, isPrototypeAssignment);
|
|
61999
62227
|
}
|
|
62000
62228
|
return false;
|
|
62001
62229
|
}
|
|
@@ -62314,15 +62542,15 @@ ${lanes.join("\n")}
|
|
|
62314
62542
|
} else if (isIdentifier2(node)) {
|
|
62315
62543
|
const symbol = lookupSymbolForName(sourceFile, node.escapedText);
|
|
62316
62544
|
if (!!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) {
|
|
62317
|
-
const
|
|
62318
|
-
q2.enqueue(
|
|
62545
|
+
const init4 = symbol.valueDeclaration.initializer;
|
|
62546
|
+
q2.enqueue(init4);
|
|
62319
62547
|
if (isAssignmentExpression(
|
|
62320
|
-
|
|
62548
|
+
init4,
|
|
62321
62549
|
/*excludeCompoundAssignment*/
|
|
62322
62550
|
true
|
|
62323
62551
|
)) {
|
|
62324
|
-
q2.enqueue(
|
|
62325
|
-
q2.enqueue(
|
|
62552
|
+
q2.enqueue(init4.left);
|
|
62553
|
+
q2.enqueue(init4.right);
|
|
62326
62554
|
}
|
|
62327
62555
|
}
|
|
62328
62556
|
}
|
|
@@ -66910,9 +67138,9 @@ ${lanes.join("\n")}
|
|
|
66910
67138
|
)) {
|
|
66911
67139
|
return void 0;
|
|
66912
67140
|
}
|
|
66913
|
-
const
|
|
66914
|
-
if (
|
|
66915
|
-
const initSymbol = getSymbolOfNode(
|
|
67141
|
+
const init4 = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
|
|
67142
|
+
if (init4) {
|
|
67143
|
+
const initSymbol = getSymbolOfNode(init4);
|
|
66916
67144
|
if (initSymbol) {
|
|
66917
67145
|
return mergeJSSymbols(initSymbol, symbol);
|
|
66918
67146
|
}
|
|
@@ -73692,9 +73920,9 @@ ${lanes.join("\n")}
|
|
|
73692
73920
|
}
|
|
73693
73921
|
return widened;
|
|
73694
73922
|
}
|
|
73695
|
-
function getJSContainerObjectType(decl, symbol,
|
|
73923
|
+
function getJSContainerObjectType(decl, symbol, init4) {
|
|
73696
73924
|
var _a, _b;
|
|
73697
|
-
if (!isInJSFile(decl) || !
|
|
73925
|
+
if (!isInJSFile(decl) || !init4 || !isObjectLiteralExpression(init4) || init4.properties.length) {
|
|
73698
73926
|
return void 0;
|
|
73699
73927
|
}
|
|
73700
73928
|
const exports22 = createSymbolTable();
|
|
@@ -88668,8 +88896,8 @@ ${lanes.join("\n")}
|
|
|
88668
88896
|
return unreachableNeverType;
|
|
88669
88897
|
}
|
|
88670
88898
|
if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConstLike2(node))) {
|
|
88671
|
-
const
|
|
88672
|
-
if (
|
|
88899
|
+
const init4 = getDeclaredExpandoInitializer(node);
|
|
88900
|
+
if (init4 && (init4.kind === 218 || init4.kind === 219)) {
|
|
88673
88901
|
return getTypeAtFlowNode(flow.antecedent);
|
|
88674
88902
|
}
|
|
88675
88903
|
}
|
|
@@ -96290,8 +96518,8 @@ ${lanes.join("\n")}
|
|
|
96290
96518
|
true
|
|
96291
96519
|
);
|
|
96292
96520
|
const prototype = (_a = assignmentSymbol == null ? void 0 : assignmentSymbol.exports) == null ? void 0 : _a.get("prototype");
|
|
96293
|
-
const
|
|
96294
|
-
return
|
|
96521
|
+
const init4 = (prototype == null ? void 0 : prototype.valueDeclaration) && getAssignedJSPrototype(prototype.valueDeclaration);
|
|
96522
|
+
return init4 ? getSymbolOfDeclaration(init4) : void 0;
|
|
96295
96523
|
}
|
|
96296
96524
|
function getSymbolOfExpando(node, allowDeclaration) {
|
|
96297
96525
|
if (!node.parent) {
|
|
@@ -99307,8 +99535,8 @@ ${lanes.join("\n")}
|
|
|
99307
99535
|
case 3:
|
|
99308
99536
|
case 4:
|
|
99309
99537
|
const symbol = getSymbolOfNode(left);
|
|
99310
|
-
const
|
|
99311
|
-
return !!
|
|
99538
|
+
const init4 = getAssignedExpandoInitializer(right);
|
|
99539
|
+
return !!init4 && isObjectLiteralExpression(init4) && !!((_a = symbol == null ? void 0 : symbol.exports) == null ? void 0 : _a.size);
|
|
99312
99540
|
default:
|
|
99313
99541
|
return false;
|
|
99314
99542
|
}
|
|
@@ -163307,13 +163535,13 @@ ${lanes.join("\n")}
|
|
|
163307
163535
|
}
|
|
163308
163536
|
} else {
|
|
163309
163537
|
if (isVariableStatement(node) && node.parent === sourceFile && node.declarationList.flags & 2 && node.declarationList.declarations.length === 1) {
|
|
163310
|
-
const
|
|
163311
|
-
if (
|
|
163312
|
-
|
|
163538
|
+
const init4 = node.declarationList.declarations[0].initializer;
|
|
163539
|
+
if (init4 && isRequireCall(
|
|
163540
|
+
init4,
|
|
163313
163541
|
/*requireStringLiteralLikeArgument*/
|
|
163314
163542
|
true
|
|
163315
163543
|
)) {
|
|
163316
|
-
diags.push(createDiagnosticForNode(
|
|
163544
|
+
diags.push(createDiagnosticForNode(init4, Diagnostics.require_call_may_be_converted_to_an_import));
|
|
163317
163545
|
}
|
|
163318
163546
|
}
|
|
163319
163547
|
const jsdocTypedefNodes = ts_codefix_exports.getJSDocTypedefNodes(node);
|
|
@@ -176204,7 +176432,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
176204
176432
|
factory.createIdentifier(name)
|
|
176205
176433
|
);
|
|
176206
176434
|
}
|
|
176207
|
-
function makeConst(modifiers, name,
|
|
176435
|
+
function makeConst(modifiers, name, init4) {
|
|
176208
176436
|
return factory.createVariableStatement(
|
|
176209
176437
|
modifiers,
|
|
176210
176438
|
factory.createVariableDeclarationList(
|
|
@@ -176214,7 +176442,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
176214
176442
|
void 0,
|
|
176215
176443
|
/*type*/
|
|
176216
176444
|
void 0,
|
|
176217
|
-
|
|
176445
|
+
init4
|
|
176218
176446
|
)],
|
|
176219
176447
|
2
|
|
176220
176448
|
/* Const */
|
|
@@ -195188,9 +195416,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
195188
195416
|
return isFunctionLike(be.right) ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner };
|
|
195189
195417
|
}
|
|
195190
195418
|
case 172:
|
|
195191
|
-
const
|
|
195192
|
-
if (
|
|
195193
|
-
return { commentOwner, parameters:
|
|
195419
|
+
const init4 = commentOwner.initializer;
|
|
195420
|
+
if (init4 && (isFunctionExpression(init4) || isArrowFunction(init4))) {
|
|
195421
|
+
return { commentOwner, parameters: init4.parameters, hasReturn: hasReturn(init4, options) };
|
|
195194
195422
|
}
|
|
195195
195423
|
}
|
|
195196
195424
|
}
|
|
@@ -206683,13 +206911,13 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
206683
206911
|
return [];
|
|
206684
206912
|
}
|
|
206685
206913
|
var ThrottledOperations = class _ThrottledOperations {
|
|
206686
|
-
constructor(host,
|
|
206914
|
+
constructor(host, logger2) {
|
|
206687
206915
|
this.host = host;
|
|
206688
206916
|
this.pendingTimeouts = /* @__PURE__ */ new Map();
|
|
206689
|
-
this.logger =
|
|
206917
|
+
this.logger = logger2.hasLevel(
|
|
206690
206918
|
3
|
|
206691
206919
|
/* verbose */
|
|
206692
|
-
) ?
|
|
206920
|
+
) ? logger2 : void 0;
|
|
206693
206921
|
}
|
|
206694
206922
|
/**
|
|
206695
206923
|
* Wait `number` milliseconds and then invoke `cb`. If, while waiting, schedule
|
|
@@ -206722,10 +206950,10 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
206722
206950
|
}
|
|
206723
206951
|
};
|
|
206724
206952
|
var GcTimer = class _GcTimer {
|
|
206725
|
-
constructor(host, delay,
|
|
206953
|
+
constructor(host, delay, logger2) {
|
|
206726
206954
|
this.host = host;
|
|
206727
206955
|
this.delay = delay;
|
|
206728
|
-
this.logger =
|
|
206956
|
+
this.logger = logger2;
|
|
206729
206957
|
}
|
|
206730
206958
|
scheduleCollect() {
|
|
206731
206959
|
if (!this.host.gc || this.timerId !== void 0) {
|
|
@@ -214086,14 +214314,14 @@ Dynamic files must always be opened with service's current directory or service
|
|
|
214086
214314
|
return edits.every((edit) => textSpanEnd(edit.span) < pos);
|
|
214087
214315
|
}
|
|
214088
214316
|
var CommandNames = CommandTypes;
|
|
214089
|
-
function formatMessage2(msg,
|
|
214090
|
-
const verboseLogging =
|
|
214317
|
+
function formatMessage2(msg, logger2, byteLength, newLine) {
|
|
214318
|
+
const verboseLogging = logger2.hasLevel(
|
|
214091
214319
|
3
|
|
214092
214320
|
/* verbose */
|
|
214093
214321
|
);
|
|
214094
214322
|
const json = JSON.stringify(msg);
|
|
214095
214323
|
if (verboseLogging) {
|
|
214096
|
-
|
|
214324
|
+
logger2.info(`${msg.type}:${stringifyIndented(msg)}`);
|
|
214097
214325
|
}
|
|
214098
214326
|
const len = byteLength(json, "utf8");
|
|
214099
214327
|
return `Content-Length: ${1 + len}\r
|
|
@@ -214248,7 +214476,7 @@ ${json}${newLine}`;
|
|
|
214248
214476
|
const info = infos && firstOrUndefined(infos);
|
|
214249
214477
|
return info && !info.isLocal ? { fileName: info.fileName, pos: info.textSpan.start } : void 0;
|
|
214250
214478
|
}
|
|
214251
|
-
function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2,
|
|
214479
|
+
function getReferencesWorker(projects2, defaultProject, initialLocation, useCaseSensitiveFileNames2, logger2) {
|
|
214252
214480
|
var _a, _b;
|
|
214253
214481
|
const perProjectResults = getPerProjectReferences(
|
|
214254
214482
|
projects2,
|
|
@@ -214262,7 +214490,7 @@ ${json}${newLine}`;
|
|
|
214262
214490
|
),
|
|
214263
214491
|
mapDefinitionInProject,
|
|
214264
214492
|
(project, position) => {
|
|
214265
|
-
|
|
214493
|
+
logger2.info(`Finding references to ${position.fileName} position ${position.pos} in project ${project.getProjectName()}`);
|
|
214266
214494
|
return project.getLanguageService().findReferences(position.fileName, position.pos);
|
|
214267
214495
|
},
|
|
214268
214496
|
(referencedSymbol, cb) => {
|
|
@@ -218631,9 +218859,9 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
218631
218859
|
}
|
|
218632
218860
|
};
|
|
218633
218861
|
var _TypingsInstallerAdapter = class _TypingsInstallerAdapter2 {
|
|
218634
|
-
constructor(telemetryEnabled,
|
|
218862
|
+
constructor(telemetryEnabled, logger2, host, globalTypingsCacheLocation, event, maxActiveRequestCount) {
|
|
218635
218863
|
this.telemetryEnabled = telemetryEnabled;
|
|
218636
|
-
this.logger =
|
|
218864
|
+
this.logger = logger2;
|
|
218637
218865
|
this.host = host;
|
|
218638
218866
|
this.globalTypingsCacheLocation = globalTypingsCacheLocation;
|
|
218639
218867
|
this.event = event;
|
|
@@ -225611,13 +225839,13 @@ var require_reusify = __commonJS({
|
|
|
225611
225839
|
current.next = null;
|
|
225612
225840
|
return current;
|
|
225613
225841
|
}
|
|
225614
|
-
function
|
|
225842
|
+
function release2(obj) {
|
|
225615
225843
|
tail.next = obj;
|
|
225616
225844
|
tail = obj;
|
|
225617
225845
|
}
|
|
225618
225846
|
return {
|
|
225619
225847
|
get,
|
|
225620
|
-
release
|
|
225848
|
+
release: release2
|
|
225621
225849
|
};
|
|
225622
225850
|
}
|
|
225623
225851
|
module2.exports = reusify;
|
|
@@ -225661,7 +225889,7 @@ var require_queue = __commonJS({
|
|
|
225661
225889
|
if (self.paused) return;
|
|
225662
225890
|
for (; queueHead && _running < _concurrency; ) {
|
|
225663
225891
|
_running++;
|
|
225664
|
-
|
|
225892
|
+
release2();
|
|
225665
225893
|
}
|
|
225666
225894
|
},
|
|
225667
225895
|
running,
|
|
@@ -225706,12 +225934,12 @@ var require_queue = __commonJS({
|
|
|
225706
225934
|
self.paused = false;
|
|
225707
225935
|
if (queueHead === null) {
|
|
225708
225936
|
_running++;
|
|
225709
|
-
|
|
225937
|
+
release2();
|
|
225710
225938
|
return;
|
|
225711
225939
|
}
|
|
225712
225940
|
for (; queueHead && _running < _concurrency; ) {
|
|
225713
225941
|
_running++;
|
|
225714
|
-
|
|
225942
|
+
release2();
|
|
225715
225943
|
}
|
|
225716
225944
|
}
|
|
225717
225945
|
function idle() {
|
|
@@ -225720,7 +225948,7 @@ var require_queue = __commonJS({
|
|
|
225720
225948
|
function push2(value, done) {
|
|
225721
225949
|
var current = cache.get();
|
|
225722
225950
|
current.context = context;
|
|
225723
|
-
current.release =
|
|
225951
|
+
current.release = release2;
|
|
225724
225952
|
current.value = value;
|
|
225725
225953
|
current.callback = done || noop3;
|
|
225726
225954
|
current.errorHandler = errorHandler;
|
|
@@ -225741,7 +225969,7 @@ var require_queue = __commonJS({
|
|
|
225741
225969
|
function unshift(value, done) {
|
|
225742
225970
|
var current = cache.get();
|
|
225743
225971
|
current.context = context;
|
|
225744
|
-
current.release =
|
|
225972
|
+
current.release = release2;
|
|
225745
225973
|
current.value = value;
|
|
225746
225974
|
current.callback = done || noop3;
|
|
225747
225975
|
current.errorHandler = errorHandler;
|
|
@@ -225759,7 +225987,7 @@ var require_queue = __commonJS({
|
|
|
225759
225987
|
worker.call(context, current.value, current.worked);
|
|
225760
225988
|
}
|
|
225761
225989
|
}
|
|
225762
|
-
function
|
|
225990
|
+
function release2(holder) {
|
|
225763
225991
|
if (holder) {
|
|
225764
225992
|
cache.release(holder);
|
|
225765
225993
|
}
|
|
@@ -283116,7 +283344,7 @@ var import_child_process3 = require("child_process");
|
|
|
283116
283344
|
|
|
283117
283345
|
// src/migrate.ts
|
|
283118
283346
|
init_cjs_shims();
|
|
283119
|
-
var
|
|
283347
|
+
var import_errors8 = require("@abloatai/transaction/errors");
|
|
283120
283348
|
init_dist2();
|
|
283121
283349
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
283122
283350
|
var import_fs5 = require("fs");
|
|
@@ -283163,7 +283391,7 @@ function parseMigrateArgs(argv) {
|
|
|
283163
283391
|
targetSchema = argv[++i] ?? targetSchema;
|
|
283164
283392
|
break;
|
|
283165
283393
|
default:
|
|
283166
|
-
throw new
|
|
283394
|
+
throw new import_errors8.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
283167
283395
|
}
|
|
283168
283396
|
}
|
|
283169
283397
|
return { schemaPath, exportName, targetSchema, dryRun, outputFile };
|
|
@@ -283279,7 +283507,7 @@ async function migrate(argv) {
|
|
|
283279
283507
|
}
|
|
283280
283508
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
283281
283509
|
if (!dbUrl) {
|
|
283282
|
-
throw new
|
|
283510
|
+
throw new import_errors8.AbloValidationError(
|
|
283283
283511
|
`No ${ADMIN_URL_VAR} found (checked process env, .env.local, .env). Set it to apply, or use --dry-run to preview.`,
|
|
283284
283512
|
{ code: "cli_database_url_missing" }
|
|
283285
283513
|
);
|
|
@@ -283494,14 +283722,14 @@ function requireKey2(explicit) {
|
|
|
283494
283722
|
}
|
|
283495
283723
|
return key;
|
|
283496
283724
|
}
|
|
283497
|
-
async function request2(path,
|
|
283725
|
+
async function request2(path, init4 = {}, context = {}) {
|
|
283498
283726
|
const response = await fetch(`${apiUrl2(context.baseUrl)}${path}`, {
|
|
283499
|
-
method:
|
|
283727
|
+
method: init4.method ?? "GET",
|
|
283500
283728
|
headers: {
|
|
283501
283729
|
authorization: `Bearer ${requireKey2(context.apiKey)}`,
|
|
283502
283730
|
"content-type": "application/json"
|
|
283503
283731
|
},
|
|
283504
|
-
...
|
|
283732
|
+
...init4.body !== void 0 ? { body: JSON.stringify(init4.body) } : {}
|
|
283505
283733
|
});
|
|
283506
283734
|
let body;
|
|
283507
283735
|
try {
|
|
@@ -283584,7 +283812,7 @@ async function readStatus(ref, context = {}) {
|
|
|
283584
283812
|
return import_branches.branchStatusResponseSchema.parse(response.body);
|
|
283585
283813
|
}
|
|
283586
283814
|
function printStatus(status2) {
|
|
283587
|
-
const { branch, schema, data_source: source } = status2;
|
|
283815
|
+
const { branch, schema, storage, data_source: source } = status2;
|
|
283588
283816
|
console.log(` ${import_picocolors14.default.bold(branch.slug)} ${import_picocolors14.default.dim(branch.id)}`);
|
|
283589
283817
|
console.log(
|
|
283590
283818
|
` ${import_picocolors14.default.dim("state")} ${branch.state === "ready" ? import_picocolors14.default.green(branch.state) : import_picocolors14.default.yellow(branch.state)}`
|
|
@@ -283600,7 +283828,7 @@ function printStatus(status2) {
|
|
|
283600
283828
|
` ${import_picocolors14.default.dim("parent")} ${import_picocolors14.default.bold(schema.parent_compatibility)}${counts}`
|
|
283601
283829
|
);
|
|
283602
283830
|
}
|
|
283603
|
-
const sourceLabel = source
|
|
283831
|
+
const sourceLabel = source ? `${source.connection} \xB7 ${source.host ?? "unknown host"}${source.database ? `/${source.database}` : ""} \xB7 ${source.status}` : storage.kind === "unbound" ? "not connected to a database" : storage.kind === "internal" ? `Ablo internal product storage \xB7 ${storage.implementation}` : storage.kind === "blocked" ? "storage configuration needs attention" : "customer database connection unavailable";
|
|
283604
283832
|
console.log(` ${import_picocolors14.default.dim("data")} ${sourceLabel}`);
|
|
283605
283833
|
if (status2.ready) {
|
|
283606
283834
|
console.log(`
|
|
@@ -283727,15 +283955,15 @@ async function branches(argv) {
|
|
|
283727
283955
|
|
|
283728
283956
|
// src/branchDev.ts
|
|
283729
283957
|
init_cjs_shims();
|
|
283730
|
-
var
|
|
283958
|
+
var import_node_crypto2 = require("crypto");
|
|
283731
283959
|
var import_node_child_process = require("child_process");
|
|
283732
283960
|
var import_branches2 = require("@abloatai/transaction/branches");
|
|
283733
|
-
var
|
|
283961
|
+
var import_errors13 = require("@abloatai/transaction/errors");
|
|
283734
283962
|
init_config();
|
|
283735
283963
|
|
|
283736
283964
|
// src/dev.ts
|
|
283737
283965
|
init_cjs_shims();
|
|
283738
|
-
var
|
|
283966
|
+
var import_errors12 = require("@abloatai/transaction/errors");
|
|
283739
283967
|
var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
|
|
283740
283968
|
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
283741
283969
|
init_dist2();
|
|
@@ -283747,11 +283975,15 @@ init_controlPlane();
|
|
|
283747
283975
|
init_config();
|
|
283748
283976
|
init_readiness();
|
|
283749
283977
|
init_theme();
|
|
283978
|
+
init_dbRole();
|
|
283979
|
+
var import_source3 = require("@abloatai/transaction/source");
|
|
283750
283980
|
function parseDevArgs(argv) {
|
|
283751
283981
|
let schemaPath = DEFAULT_SCHEMA_PATH;
|
|
283752
283982
|
let exportName = DEFAULT_EXPORT;
|
|
283753
283983
|
let url = process.env.ABLO_API_URL ?? DEFAULT_URL;
|
|
283754
283984
|
let watchEnabled = false;
|
|
283985
|
+
let local = false;
|
|
283986
|
+
let sourcePath = "ablo/data-source.ts";
|
|
283755
283987
|
for (let i = 0; i < argv.length; i++) {
|
|
283756
283988
|
const arg = argv[i];
|
|
283757
283989
|
switch (arg) {
|
|
@@ -283770,8 +284002,14 @@ function parseDevArgs(argv) {
|
|
|
283770
284002
|
case "--no-watch":
|
|
283771
284003
|
watchEnabled = false;
|
|
283772
284004
|
break;
|
|
284005
|
+
case "--local":
|
|
284006
|
+
local = true;
|
|
284007
|
+
break;
|
|
284008
|
+
case "--source":
|
|
284009
|
+
sourcePath = argv[++i] ?? sourcePath;
|
|
284010
|
+
break;
|
|
283773
284011
|
default:
|
|
283774
|
-
throw new
|
|
284012
|
+
throw new import_errors12.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
283775
284013
|
}
|
|
283776
284014
|
}
|
|
283777
284015
|
url = url.replace(/\/+$/, "");
|
|
@@ -283781,9 +284019,55 @@ function parseDevArgs(argv) {
|
|
|
283781
284019
|
url,
|
|
283782
284020
|
apiKey: process.env.ABLO_API_KEY,
|
|
283783
284021
|
watch: watchEnabled,
|
|
284022
|
+
local,
|
|
284023
|
+
sourcePath,
|
|
283784
284024
|
planeLabel: "branch"
|
|
283785
284025
|
};
|
|
283786
284026
|
}
|
|
284027
|
+
async function loadLocalSourceHandler(sourcePath) {
|
|
284028
|
+
const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
|
|
284029
|
+
if (!(0, import_fs7.existsSync)(abs)) {
|
|
284030
|
+
throw new import_errors12.AbloValidationError(
|
|
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>")}.`,
|
|
284032
|
+
{ code: "cli_invalid_arguments" }
|
|
284033
|
+
);
|
|
284034
|
+
}
|
|
284035
|
+
const { createJiti } = await import("jiti");
|
|
284036
|
+
const jiti = createJiti(process.cwd());
|
|
284037
|
+
const mod = await jiti.import(abs);
|
|
284038
|
+
const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
|
|
284039
|
+
const handler = mod.POST ?? nested?.POST;
|
|
284040
|
+
if (typeof handler !== "function") {
|
|
284041
|
+
throw new import_errors12.AbloValidationError(
|
|
284042
|
+
`${import_picocolors15.default.bold(sourcePath)} must export a ${import_picocolors15.default.bold("POST(request)")} Data Source handler.`,
|
|
284043
|
+
{ code: "cli_invalid_arguments" }
|
|
284044
|
+
);
|
|
284045
|
+
}
|
|
284046
|
+
return handler;
|
|
284047
|
+
}
|
|
284048
|
+
async function registerLocalSource(args) {
|
|
284049
|
+
const response = await fetch(`${args.url}/v1/datasources`, {
|
|
284050
|
+
method: "POST",
|
|
284051
|
+
headers: {
|
|
284052
|
+
authorization: `Bearer ${args.apiKey}`,
|
|
284053
|
+
"content-type": "application/json"
|
|
284054
|
+
},
|
|
284055
|
+
body: JSON.stringify({
|
|
284056
|
+
connection: "endpoint",
|
|
284057
|
+
endpoint: "http://localhost/ablo-dev/reverse-channel",
|
|
284058
|
+
signingKey: args.apiKey,
|
|
284059
|
+
reverseChannel: true,
|
|
284060
|
+
metadata: { managed_by: "ablo dev --local" }
|
|
284061
|
+
})
|
|
284062
|
+
});
|
|
284063
|
+
if (!response.ok) {
|
|
284064
|
+
const body = await response.text();
|
|
284065
|
+
throw new import_errors12.AbloValidationError(
|
|
284066
|
+
`Could not register the local Data Source (${response.status}): ${body}`,
|
|
284067
|
+
{ code: "cli_invalid_arguments" }
|
|
284068
|
+
);
|
|
284069
|
+
}
|
|
284070
|
+
}
|
|
283787
284071
|
function classifyKey(apiKey) {
|
|
283788
284072
|
if (!apiKey) {
|
|
283789
284073
|
return {
|
|
@@ -283921,7 +284205,7 @@ async function runPush(schema, args) {
|
|
|
283921
284205
|
}
|
|
283922
284206
|
if (status2 === 403) {
|
|
283923
284207
|
const serverSays = body.message ?? body.reason;
|
|
283924
|
-
const hint =
|
|
284208
|
+
const hint = schemaPushStorageHint(body.code) ?? (body.code === "database_role_cannot_enforce_rls" ? `Run ${import_picocolors15.default.bold("npx ablo migrate")} \u2014 it creates the scoped role for you (your DB credential never leaves this machine).` : `Schema authoring needs a branch-bound ${import_picocolors15.default.bold("sk_")} key with ${import_picocolors15.default.bold("schema:push")} \u2014 manage keys at ${import_picocolors15.default.cyan("https://abloatai.com")}.`);
|
|
283925
284209
|
return {
|
|
283926
284210
|
ok: false,
|
|
283927
284211
|
message: `${serverSays ?? "This key can't author schema (missing schema:push scope)."}
|
|
@@ -283929,6 +284213,11 @@ async function runPush(schema, args) {
|
|
|
283929
284213
|
};
|
|
283930
284214
|
}
|
|
283931
284215
|
const serverMessage = String(body.message ?? body.reason ?? bodyText);
|
|
284216
|
+
const storageHint = schemaPushStorageHint(body.code);
|
|
284217
|
+
if (storageHint) {
|
|
284218
|
+
return { ok: false, message: `${serverMessage}
|
|
284219
|
+
${import_picocolors15.default.dim(storageHint)}` };
|
|
284220
|
+
}
|
|
283932
284221
|
if (looksLikeCredentialRefusal(serverMessage)) {
|
|
283933
284222
|
const pooled = await poolerExplanation(apiBaseUrl(), args.apiKey);
|
|
283934
284223
|
if (pooled) {
|
|
@@ -283949,6 +284238,12 @@ async function dev(argv, runtime = {}) {
|
|
|
283949
284238
|
if (runtime.apiKey) args.apiKey = runtime.apiKey;
|
|
283950
284239
|
else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
|
|
283951
284240
|
if (runtime.branch) args.planeLabel = runtime.branch.slug;
|
|
284241
|
+
if (args.local && !args.watch) {
|
|
284242
|
+
throw new import_errors12.AbloValidationError(
|
|
284243
|
+
`${import_picocolors15.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors15.default.bold("--no-watch")}.`,
|
|
284244
|
+
{ code: "cli_invalid_arguments" }
|
|
284245
|
+
);
|
|
284246
|
+
}
|
|
283952
284247
|
const key = classifyKey(args.apiKey);
|
|
283953
284248
|
if (!key.ok) {
|
|
283954
284249
|
console.error(import_picocolors15.default.red(` ${key.reason}`));
|
|
@@ -283965,6 +284260,35 @@ async function dev(argv, runtime = {}) {
|
|
|
283965
284260
|
` ${import_picocolors15.default.dim("key")} temporary \xB7 expires ${runtime.branch.expiresAt}`
|
|
283966
284261
|
);
|
|
283967
284262
|
}
|
|
284263
|
+
let localAbort = null;
|
|
284264
|
+
if (args.local) {
|
|
284265
|
+
process.env.ABLO_API_KEY = args.apiKey;
|
|
284266
|
+
if (!process.env.DATABASE_URL) {
|
|
284267
|
+
const databaseUrl = readProjectEnvVariable("DATABASE_URL", process.cwd(), false);
|
|
284268
|
+
if (databaseUrl) process.env.DATABASE_URL = databaseUrl.value;
|
|
284269
|
+
}
|
|
284270
|
+
const handler = await loadLocalSourceHandler(args.sourcePath);
|
|
284271
|
+
await registerLocalSource(args);
|
|
284272
|
+
localAbort = new AbortController();
|
|
284273
|
+
const connector = (0, import_source3.createSourceConnector)({
|
|
284274
|
+
apiKey: args.apiKey,
|
|
284275
|
+
handler,
|
|
284276
|
+
baseURL: args.url,
|
|
284277
|
+
client: "ablo-dev",
|
|
284278
|
+
onStatus(status2) {
|
|
284279
|
+
if (status2 === "ready") {
|
|
284280
|
+
console.log(` ${import_picocolors15.default.green("\u2713")} local Postgres connected through the secure reverse channel`);
|
|
284281
|
+
}
|
|
284282
|
+
},
|
|
284283
|
+
onError(error) {
|
|
284284
|
+
console.error(import_picocolors15.default.yellow(` local connector: ${error instanceof Error ? error.message : String(error)}`));
|
|
284285
|
+
}
|
|
284286
|
+
});
|
|
284287
|
+
void connector.run(localAbort.signal).catch((error) => {
|
|
284288
|
+
console.error(import_picocolors15.default.red(` local connector stopped: ${error instanceof Error ? error.message : String(error)}`));
|
|
284289
|
+
});
|
|
284290
|
+
console.log(` ${import_picocolors15.default.dim("source")} ${args.sourcePath} ${import_picocolors15.default.dim("(outbound connector; no public URL)")}`);
|
|
284291
|
+
}
|
|
283968
284292
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
283969
284293
|
const modelCount = Object.keys(schema.models).length;
|
|
283970
284294
|
console.log(
|
|
@@ -283979,7 +284303,10 @@ async function dev(argv, runtime = {}) {
|
|
|
283979
284303
|
s.start("Pushing schema definition (development branch)");
|
|
283980
284304
|
const first = await runPush(schema, args);
|
|
283981
284305
|
s.stop(first.message, first.ok ? 0 : 1);
|
|
283982
|
-
if (!first.ok)
|
|
284306
|
+
if (!first.ok) {
|
|
284307
|
+
localAbort?.abort();
|
|
284308
|
+
process.exit(1);
|
|
284309
|
+
}
|
|
283983
284310
|
if (runtime.branch) {
|
|
283984
284311
|
console.log(
|
|
283985
284312
|
`
|
|
@@ -284033,6 +284360,7 @@ async function dev(argv, runtime = {}) {
|
|
|
284033
284360
|
}
|
|
284034
284361
|
const stop = () => {
|
|
284035
284362
|
watcher.close();
|
|
284363
|
+
localAbort?.abort();
|
|
284036
284364
|
console.log(`
|
|
284037
284365
|
${import_picocolors15.default.dim("stopped.")}`);
|
|
284038
284366
|
process.exit(0);
|
|
@@ -284048,6 +284376,7 @@ init_controlPlane();
|
|
|
284048
284376
|
var BRANCH_DEV_USAGE = `Usage:
|
|
284049
284377
|
ablo dev [--branch <slug>] [--branch-ttl-hours <1-168>]
|
|
284050
284378
|
[--schema <path>] [--export <name>] [--url <url>]
|
|
284379
|
+
[--local] [--source <path>]
|
|
284051
284380
|
ablo dev --no-watch [branch options]
|
|
284052
284381
|
|
|
284053
284382
|
By default, dev discovers the Git/CI branch, ensures its isolated Ablo branch,
|
|
@@ -284061,7 +284390,7 @@ function parseBranchDevArgs(argv) {
|
|
|
284061
284390
|
const arg = argv[index];
|
|
284062
284391
|
if (!arg) continue;
|
|
284063
284392
|
if (arg === "--no-branch") {
|
|
284064
|
-
throw new
|
|
284393
|
+
throw new import_errors13.AbloValidationError(
|
|
284065
284394
|
"--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
|
|
284066
284395
|
{ code: "cli_invalid_arguments" }
|
|
284067
284396
|
);
|
|
@@ -284069,7 +284398,7 @@ function parseBranchDevArgs(argv) {
|
|
|
284069
284398
|
if (arg === "--branch") {
|
|
284070
284399
|
branchSlug = argv[++index];
|
|
284071
284400
|
if (!branchSlug) {
|
|
284072
|
-
throw new
|
|
284401
|
+
throw new import_errors13.AbloValidationError("--branch requires a slug", {
|
|
284073
284402
|
code: "cli_invalid_arguments"
|
|
284074
284403
|
});
|
|
284075
284404
|
}
|
|
@@ -284078,7 +284407,7 @@ function parseBranchDevArgs(argv) {
|
|
|
284078
284407
|
if (arg === "--branch-ttl-hours") {
|
|
284079
284408
|
const value = Number(argv[++index]);
|
|
284080
284409
|
if (!Number.isInteger(value) || value < 1 || value > 168) {
|
|
284081
|
-
throw new
|
|
284410
|
+
throw new import_errors13.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
|
|
284082
284411
|
code: "cli_invalid_arguments"
|
|
284083
284412
|
});
|
|
284084
284413
|
}
|
|
@@ -284096,12 +284425,12 @@ function parseBranchDevArgs(argv) {
|
|
|
284096
284425
|
function branchSlugFromRef(ref) {
|
|
284097
284426
|
const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
284098
284427
|
if (!base) {
|
|
284099
|
-
throw new
|
|
284428
|
+
throw new import_errors13.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
|
|
284100
284429
|
code: "cli_invalid_arguments"
|
|
284101
284430
|
});
|
|
284102
284431
|
}
|
|
284103
284432
|
const nonRoot = base === "production" ? "production-dev" : base;
|
|
284104
|
-
const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0,
|
|
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)}`;
|
|
284105
284434
|
return import_branches2.branchSlugSchema.parse(shortened);
|
|
284106
284435
|
}
|
|
284107
284436
|
function gitBranch() {
|
|
@@ -284118,7 +284447,7 @@ function gitBranch() {
|
|
|
284118
284447
|
function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
|
|
284119
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();
|
|
284120
284449
|
if (!value) {
|
|
284121
|
-
throw new
|
|
284450
|
+
throw new import_errors13.AbloValidationError(
|
|
284122
284451
|
"Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
|
|
284123
284452
|
{ code: "cli_invalid_arguments" }
|
|
284124
284453
|
);
|
|
@@ -284136,13 +284465,13 @@ async function runBranchDev(argv, dependencies = {}) {
|
|
|
284136
284465
|
const slug = branchSlugFromRef(ref);
|
|
284137
284466
|
const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
|
|
284138
284467
|
if (!managementKey) {
|
|
284139
|
-
throw new
|
|
284468
|
+
throw new import_errors13.AbloValidationError(
|
|
284140
284469
|
"Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_MANAGEMENT_KEY.",
|
|
284141
284470
|
{ code: "cli_invalid_arguments" }
|
|
284142
284471
|
);
|
|
284143
284472
|
}
|
|
284144
284473
|
if (!managementKey.startsWith("mk_")) {
|
|
284145
|
-
throw new
|
|
284474
|
+
throw new import_errors13.AbloValidationError(
|
|
284146
284475
|
"Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
|
|
284147
284476
|
{ code: "cli_invalid_arguments" }
|
|
284148
284477
|
);
|
|
@@ -284169,7 +284498,7 @@ async function runBranchDev(argv, dependencies = {}) {
|
|
|
284169
284498
|
// src/whoami.ts
|
|
284170
284499
|
init_cjs_shims();
|
|
284171
284500
|
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
284172
|
-
var
|
|
284501
|
+
var import_errors14 = require("@abloatai/transaction/errors");
|
|
284173
284502
|
init_config();
|
|
284174
284503
|
init_controlPlane();
|
|
284175
284504
|
|
|
@@ -284244,7 +284573,7 @@ function parseWhoamiArgs(argv) {
|
|
|
284244
284573
|
case "--key": {
|
|
284245
284574
|
const value = argv[++i];
|
|
284246
284575
|
if (!value || value.startsWith("--")) {
|
|
284247
|
-
throw new
|
|
284576
|
+
throw new import_errors14.AbloValidationError("`--key` needs a credential value.", {
|
|
284248
284577
|
code: "cli_invalid_arguments"
|
|
284249
284578
|
});
|
|
284250
284579
|
}
|
|
@@ -284254,12 +284583,12 @@ function parseWhoamiArgs(argv) {
|
|
|
284254
284583
|
case "--key-env": {
|
|
284255
284584
|
const value = argv[++i];
|
|
284256
284585
|
if (!value || value.startsWith("--")) {
|
|
284257
|
-
throw new
|
|
284586
|
+
throw new import_errors14.AbloValidationError("`--key-env` needs an environment variable name.", {
|
|
284258
284587
|
code: "cli_invalid_arguments"
|
|
284259
284588
|
});
|
|
284260
284589
|
}
|
|
284261
284590
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
|
284262
|
-
throw new
|
|
284591
|
+
throw new import_errors14.AbloValidationError(
|
|
284263
284592
|
`\`${value}\` is not a valid environment variable name.`,
|
|
284264
284593
|
{ code: "cli_invalid_arguments" }
|
|
284265
284594
|
);
|
|
@@ -284268,13 +284597,13 @@ function parseWhoamiArgs(argv) {
|
|
|
284268
284597
|
break;
|
|
284269
284598
|
}
|
|
284270
284599
|
default:
|
|
284271
|
-
throw new
|
|
284600
|
+
throw new import_errors14.AbloValidationError(`unknown whoami flag: ${arg}`, {
|
|
284272
284601
|
code: "cli_invalid_arguments"
|
|
284273
284602
|
});
|
|
284274
284603
|
}
|
|
284275
284604
|
}
|
|
284276
284605
|
if (key && keyEnv) {
|
|
284277
|
-
throw new
|
|
284606
|
+
throw new import_errors14.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
|
|
284278
284607
|
code: "cli_invalid_arguments"
|
|
284279
284608
|
});
|
|
284280
284609
|
}
|
|
@@ -284285,7 +284614,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
|
|
|
284285
284614
|
if (args.keyEnv) {
|
|
284286
284615
|
const found = readProjectEnvVariable(args.keyEnv, cwd);
|
|
284287
284616
|
if (!found) {
|
|
284288
|
-
throw new
|
|
284617
|
+
throw new import_errors14.AbloAuthenticationError(
|
|
284289
284618
|
`${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
|
|
284290
284619
|
{ code: "cli_api_key_missing" }
|
|
284291
284620
|
);
|
|
@@ -284314,7 +284643,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
|
|
|
284314
284643
|
};
|
|
284315
284644
|
}
|
|
284316
284645
|
const ambient = ambientEnvKeyNote();
|
|
284317
|
-
throw new
|
|
284646
|
+
throw new import_errors14.AbloAuthenticationError(
|
|
284318
284647
|
`No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
|
|
284319
284648
|
|
|
284320
284649
|
${ambient}` : ""}`,
|
|
@@ -284332,7 +284661,7 @@ async function whoami(argv) {
|
|
|
284332
284661
|
});
|
|
284333
284662
|
const confirmed = target.confirmed;
|
|
284334
284663
|
if (!confirmed) {
|
|
284335
|
-
throw new
|
|
284664
|
+
throw new import_errors14.AbloAuthenticationError(
|
|
284336
284665
|
"The server did not confirm an identity for this credential.",
|
|
284337
284666
|
{ code: "identity_resolve_failed" }
|
|
284338
284667
|
);
|
|
@@ -284436,7 +284765,7 @@ var COMMANDS = [
|
|
|
284436
284765
|
{ run: "connect check", does: "Confirm your database is ready to share changes with Ablo" },
|
|
284437
284766
|
{ run: "connect resnapshot", does: "Reload existing rows without deregistering or rotating credentials" },
|
|
284438
284767
|
{ run: "connect scan", does: "List anything Ablo ever set up in your database (read-only)" },
|
|
284439
|
-
{ run: "connect locate", does: "See which
|
|
284768
|
+
{ run: "connect locate", does: "See which branch is connected to a database before connecting it" },
|
|
284440
284769
|
{ run: "connect deregister", does: "Disconnect this project's database \u2014 Ablo stops reading and writing it" }
|
|
284441
284770
|
]
|
|
284442
284771
|
}
|
|
@@ -284667,12 +284996,12 @@ function fullRows(group) {
|
|
|
284667
284996
|
}
|
|
284668
284997
|
|
|
284669
284998
|
// src/index.ts
|
|
284670
|
-
var
|
|
284999
|
+
var import_errors22 = require("@abloatai/transaction/errors");
|
|
284671
285000
|
init_push();
|
|
284672
285001
|
|
|
284673
285002
|
// src/generate.ts
|
|
284674
285003
|
init_cjs_shims();
|
|
284675
|
-
var
|
|
285004
|
+
var import_errors15 = require("@abloatai/transaction/errors");
|
|
284676
285005
|
var import_fs8 = require("fs");
|
|
284677
285006
|
var import_path6 = require("path");
|
|
284678
285007
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
@@ -284698,7 +285027,7 @@ function parseGenerateArgs(argv) {
|
|
|
284698
285027
|
out = argv[++i] ?? out;
|
|
284699
285028
|
break;
|
|
284700
285029
|
default:
|
|
284701
|
-
throw new
|
|
285030
|
+
throw new import_errors15.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
284702
285031
|
}
|
|
284703
285032
|
}
|
|
284704
285033
|
return { schemaPath, exportName, out };
|
|
@@ -284731,7 +285060,7 @@ init_cjs_shims();
|
|
|
284731
285060
|
var import_child_process2 = require("child_process");
|
|
284732
285061
|
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
284733
285062
|
init_dist2();
|
|
284734
|
-
var
|
|
285063
|
+
var import_errors16 = require("@abloatai/transaction/errors");
|
|
284735
285064
|
var import_wire8 = require("@abloatai/transaction/wire");
|
|
284736
285065
|
init_config();
|
|
284737
285066
|
init_theme();
|
|
@@ -284865,7 +285194,7 @@ ${import_picocolors18.default.dim(url)}`, "Approve in your browser");
|
|
|
284865
285194
|
}
|
|
284866
285195
|
if (!provRes.ok) {
|
|
284867
285196
|
s.stop("Could not provision a key.");
|
|
284868
|
-
const err = (0,
|
|
285197
|
+
const err = (0, import_errors16.translateHttpError)(
|
|
284869
285198
|
provRes.status,
|
|
284870
285199
|
await provRes.json().catch(() => null),
|
|
284871
285200
|
provRes.headers.get("x-request-id") ?? void 0
|
|
@@ -285180,11 +285509,11 @@ async function status(args = []) {
|
|
|
285180
285509
|
}
|
|
285181
285510
|
} else if (dataSource.kind === "none") {
|
|
285182
285511
|
console.log(
|
|
285183
|
-
` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.red("\u2717
|
|
285512
|
+
` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.red("\u2717 this branch is not connected to a database")} ${import_picocolors19.default.dim("\u2014 writes are held")}`
|
|
285184
285513
|
);
|
|
285185
285514
|
} else if (reachable) {
|
|
285186
285515
|
console.log(
|
|
285187
|
-
` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim(`could not read
|
|
285516
|
+
` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim(`could not read this branch's database connection (${dataSource.detail})`)}`
|
|
285188
285517
|
);
|
|
285189
285518
|
}
|
|
285190
285519
|
const pushed = reachable ? await fetchPushedSchema(apiUrl3, introspectKey) : null;
|
|
@@ -285230,7 +285559,7 @@ async function status(args = []) {
|
|
|
285230
285559
|
}
|
|
285231
285560
|
} else if (dataSource.kind === "unknown") {
|
|
285232
285561
|
console.log(
|
|
285233
|
-
` ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim("nothing is blocking a write, but this key could not read the
|
|
285562
|
+
` ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim("nothing is blocking a write, but this key could not read the branch's database connection \u2014 some checks were skipped")}`
|
|
285234
285563
|
);
|
|
285235
285564
|
} else {
|
|
285236
285565
|
console.log(
|
|
@@ -285337,7 +285666,7 @@ async function doctor() {
|
|
|
285337
285666
|
checks.push({
|
|
285338
285667
|
label: "data",
|
|
285339
285668
|
state: "fail",
|
|
285340
|
-
detail: "
|
|
285669
|
+
detail: "this branch is not connected to a database \u2014 writes are held",
|
|
285341
285670
|
fix: "connect one with `ablo connect apply`"
|
|
285342
285671
|
});
|
|
285343
285672
|
} else {
|
|
@@ -285429,7 +285758,7 @@ async function doctor() {
|
|
|
285429
285758
|
|
|
285430
285759
|
// src/logs.ts
|
|
285431
285760
|
init_cjs_shims();
|
|
285432
|
-
var
|
|
285761
|
+
var import_errors17 = require("@abloatai/transaction/errors");
|
|
285433
285762
|
var import_wire9 = require("@abloatai/transaction/wire");
|
|
285434
285763
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
285435
285764
|
init_config();
|
|
@@ -285471,12 +285800,12 @@ function parseLogsArgs(argv) {
|
|
|
285471
285800
|
args.json = true;
|
|
285472
285801
|
break;
|
|
285473
285802
|
case "--mode":
|
|
285474
|
-
throw new
|
|
285803
|
+
throw new import_errors17.AbloValidationError(
|
|
285475
285804
|
"--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
|
|
285476
285805
|
{ code: "cli_invalid_arguments" }
|
|
285477
285806
|
);
|
|
285478
285807
|
default:
|
|
285479
|
-
throw new
|
|
285808
|
+
throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
285480
285809
|
}
|
|
285481
285810
|
}
|
|
285482
285811
|
return args;
|
|
@@ -285755,7 +286084,7 @@ async function webhooks(argv) {
|
|
|
285755
286084
|
|
|
285756
286085
|
// src/check.ts
|
|
285757
286086
|
init_cjs_shims();
|
|
285758
|
-
var
|
|
286087
|
+
var import_errors18 = require("@abloatai/transaction/errors");
|
|
285759
286088
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
285760
286089
|
init_src();
|
|
285761
286090
|
var import_schema9 = require("@abloatai/transaction/schema");
|
|
@@ -285903,7 +286232,7 @@ function parseCheckArgs(argv) {
|
|
|
285903
286232
|
appSchema = argv[++i] ?? appSchema;
|
|
285904
286233
|
break;
|
|
285905
286234
|
default:
|
|
285906
|
-
throw new
|
|
286235
|
+
throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
285907
286236
|
}
|
|
285908
286237
|
}
|
|
285909
286238
|
return { schemaPath, exportName, appSchema };
|
|
@@ -285929,7 +286258,7 @@ async function reportReadSubject(dbUrl) {
|
|
|
285929
286258
|
}
|
|
285930
286259
|
if (state.kind === "none") {
|
|
285931
286260
|
console.log(
|
|
285932
|
-
` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.yellow("!")}
|
|
286261
|
+
` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.yellow("!")} this branch is not connected to a database, so Ablo does not read this one`
|
|
285933
286262
|
);
|
|
285934
286263
|
console.log(
|
|
285935
286264
|
` ${import_picocolors23.default.dim(`Connect it with ${import_picocolors23.default.bold("ablo connect apply")}. Until then a table here is invisible to the engine.`)}
|
|
@@ -286069,9 +286398,9 @@ var ABLO_REACT = /* @__PURE__ */ new Set(["@abloatai/ablo/react", "@abloatai/hum
|
|
|
286069
286398
|
function clientRoots(sf) {
|
|
286070
286399
|
const roots = /* @__PURE__ */ new Set(["ablo", "sync"]);
|
|
286071
286400
|
for (const decl of sf.getVariableDeclarations()) {
|
|
286072
|
-
const
|
|
286073
|
-
if (!
|
|
286074
|
-
const text =
|
|
286401
|
+
const init4 = decl.getInitializer();
|
|
286402
|
+
if (!init4) continue;
|
|
286403
|
+
const text = init4.getText();
|
|
286075
286404
|
if (/^Ablo\s*\(/.test(text) || /^useAblo\s*\(\s*\)/.test(text)) {
|
|
286076
286405
|
roots.add(decl.getName());
|
|
286077
286406
|
}
|
|
@@ -286238,7 +286567,7 @@ async function upgrade(argv) {
|
|
|
286238
286567
|
|
|
286239
286568
|
// src/pull.ts
|
|
286240
286569
|
init_cjs_shims();
|
|
286241
|
-
var
|
|
286570
|
+
var import_errors19 = require("@abloatai/transaction/errors");
|
|
286242
286571
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
286243
286572
|
init_src();
|
|
286244
286573
|
var import_fs10 = require("fs");
|
|
@@ -286267,7 +286596,7 @@ function parsePullArgs(argv) {
|
|
|
286267
286596
|
force = true;
|
|
286268
286597
|
break;
|
|
286269
286598
|
default:
|
|
286270
|
-
throw new
|
|
286599
|
+
throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
286271
286600
|
}
|
|
286272
286601
|
}
|
|
286273
286602
|
return { out, appSchema, importPath, force };
|
|
@@ -286385,7 +286714,7 @@ async function pull(argv) {
|
|
|
286385
286714
|
|
|
286386
286715
|
// src/prismaPull.ts
|
|
286387
286716
|
init_cjs_shims();
|
|
286388
|
-
var
|
|
286717
|
+
var import_errors20 = require("@abloatai/transaction/errors");
|
|
286389
286718
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
286390
286719
|
var import_fs11 = require("fs");
|
|
286391
286720
|
init_theme();
|
|
@@ -286583,7 +286912,7 @@ function parsePrismaPullArgs(argv) {
|
|
|
286583
286912
|
force = true;
|
|
286584
286913
|
break;
|
|
286585
286914
|
default:
|
|
286586
|
-
if (arg.startsWith("--")) throw new
|
|
286915
|
+
if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
286587
286916
|
schema = arg;
|
|
286588
286917
|
}
|
|
286589
286918
|
}
|
|
@@ -286643,7 +286972,7 @@ async function prismaPull(argv) {
|
|
|
286643
286972
|
// src/drizzlePull.ts
|
|
286644
286973
|
init_cjs_shims();
|
|
286645
286974
|
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
286646
|
-
var
|
|
286975
|
+
var import_errors21 = require("@abloatai/transaction/errors");
|
|
286647
286976
|
var import_fs12 = require("fs");
|
|
286648
286977
|
var import_path7 = require("path");
|
|
286649
286978
|
init_theme();
|
|
@@ -286750,7 +287079,7 @@ function parseDrizzlePullArgs(argv) {
|
|
|
286750
287079
|
force = true;
|
|
286751
287080
|
break;
|
|
286752
287081
|
default:
|
|
286753
|
-
if (arg.startsWith("--")) throw new
|
|
287082
|
+
if (arg.startsWith("--")) throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
286754
287083
|
schema = arg;
|
|
286755
287084
|
}
|
|
286756
287085
|
}
|
|
@@ -286822,6 +287151,7 @@ async function drizzlePull(argv) {
|
|
|
286822
287151
|
// src/index.ts
|
|
286823
287152
|
init_theme();
|
|
286824
287153
|
init_renderError();
|
|
287154
|
+
init_observeCliError();
|
|
286825
287155
|
|
|
286826
287156
|
// src/generators/authScaffold.ts
|
|
286827
287157
|
init_cjs_shims();
|
|
@@ -286903,7 +287233,7 @@ var LOGO = `
|
|
|
286903
287233
|
${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}
|
|
286904
287234
|
`;
|
|
286905
287235
|
var HANDLERS = {
|
|
286906
|
-
init: (argv) =>
|
|
287236
|
+
init: (argv) => init3([...argv]),
|
|
286907
287237
|
login: (argv) => login([...argv]),
|
|
286908
287238
|
logout: () => logout(),
|
|
286909
287239
|
projects: (argv) => projects([...argv]),
|
|
@@ -286956,7 +287286,7 @@ async function main() {
|
|
|
286956
287286
|
const argv = process.argv.slice(3);
|
|
286957
287287
|
if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
|
|
286958
287288
|
const suggestion = suggestCommand(raw);
|
|
286959
|
-
throw new
|
|
287289
|
+
throw new import_errors22.AbloValidationError(
|
|
286960
287290
|
`\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
|
|
286961
287291
|
{ code: "cli_invalid_arguments" }
|
|
286962
287292
|
);
|
|
@@ -287100,7 +287430,7 @@ async function chooseBool(flagValue, fallback, interactive, prompt) {
|
|
|
287100
287430
|
bailIfCancelled(value);
|
|
287101
287431
|
return value;
|
|
287102
287432
|
}
|
|
287103
|
-
async function
|
|
287433
|
+
async function init3(args = []) {
|
|
287104
287434
|
const opts = parseInitArgs(args);
|
|
287105
287435
|
const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
|
|
287106
287436
|
Ie(`${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}`);
|
|
@@ -287633,8 +287963,17 @@ function detectPackageManager() {
|
|
|
287633
287963
|
if ((0, import_fs13.existsSync)("bun.lockb")) return "bun";
|
|
287634
287964
|
return "npm";
|
|
287635
287965
|
}
|
|
287636
|
-
|
|
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
|
+
}
|
|
287637
287974
|
renderCliError(err);
|
|
287975
|
+
await flushCliErrors();
|
|
287976
|
+
restoreCliExitObservationBoundary();
|
|
287638
287977
|
process.exit(process.exitCode ?? 1);
|
|
287639
287978
|
});
|
|
287640
287979
|
/*! Bundled license information:
|