@abloatai/cli 0.56.0 → 0.58.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 +1145 -568
- package/package.json +4 -3
package/dist/cli.cjs
CHANGED
|
@@ -827,9 +827,9 @@ var init_query = __esm({
|
|
|
827
827
|
CLOSE = {};
|
|
828
828
|
Query = class extends Promise {
|
|
829
829
|
constructor(strings, args, handler, canceller, options = {}) {
|
|
830
|
-
let
|
|
830
|
+
let resolve11, reject;
|
|
831
831
|
super((a, b4) => {
|
|
832
|
-
|
|
832
|
+
resolve11 = a;
|
|
833
833
|
reject = b4;
|
|
834
834
|
});
|
|
835
835
|
this.tagged = Array.isArray(strings.raw);
|
|
@@ -840,7 +840,7 @@ var init_query = __esm({
|
|
|
840
840
|
this.options = options;
|
|
841
841
|
this.state = null;
|
|
842
842
|
this.statement = null;
|
|
843
|
-
this.resolve = (x2) => (this.active = false,
|
|
843
|
+
this.resolve = (x2) => (this.active = false, resolve11(x2));
|
|
844
844
|
this.reject = (x2) => (this.active = false, reject(x2));
|
|
845
845
|
this.active = false;
|
|
846
846
|
this.cancelled = null;
|
|
@@ -888,12 +888,12 @@ var init_query = __esm({
|
|
|
888
888
|
if (this.executed && !this.active)
|
|
889
889
|
return { done: true };
|
|
890
890
|
prev && prev();
|
|
891
|
-
const promise = new Promise((
|
|
891
|
+
const promise = new Promise((resolve11, reject) => {
|
|
892
892
|
this.cursorFn = (value) => {
|
|
893
|
-
|
|
893
|
+
resolve11({ value, done: false });
|
|
894
894
|
return new Promise((r2) => prev = r2);
|
|
895
895
|
};
|
|
896
|
-
this.resolve = () => (this.active = false,
|
|
896
|
+
this.resolve = () => (this.active = false, resolve11({ done: true }));
|
|
897
897
|
this.reject = (x2) => (this.active = false, reject(x2));
|
|
898
898
|
});
|
|
899
899
|
this.execute();
|
|
@@ -1491,12 +1491,12 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1491
1491
|
x2.on("drain", drain);
|
|
1492
1492
|
return x2;
|
|
1493
1493
|
}
|
|
1494
|
-
async function cancel({ pid, secret },
|
|
1494
|
+
async function cancel({ pid, secret }, resolve11, reject) {
|
|
1495
1495
|
try {
|
|
1496
1496
|
cancelMessage = bytes_default().i32(16).i32(80877102).i32(pid).i32(secret).end(16);
|
|
1497
1497
|
await connect2();
|
|
1498
1498
|
socket.once("error", reject);
|
|
1499
|
-
socket.once("close",
|
|
1499
|
+
socket.once("close", resolve11);
|
|
1500
1500
|
} catch (error2) {
|
|
1501
1501
|
reject(error2);
|
|
1502
1502
|
}
|
|
@@ -2519,7 +2519,7 @@ var init_subscribe = __esm({
|
|
|
2519
2519
|
|
|
2520
2520
|
// ../../node_modules/postgres/src/large.js
|
|
2521
2521
|
function largeObject(sql, oid, mode = 131072 | 262144) {
|
|
2522
|
-
return new Promise(async (
|
|
2522
|
+
return new Promise(async (resolve11, reject) => {
|
|
2523
2523
|
await sql.begin(async (sql2) => {
|
|
2524
2524
|
let finish;
|
|
2525
2525
|
!oid && ([{ oid }] = await sql2`select lo_creat(-1) as oid`);
|
|
@@ -2545,7 +2545,7 @@ function largeObject(sql, oid, mode = 131072 | 262144) {
|
|
|
2545
2545
|
) seek
|
|
2546
2546
|
`
|
|
2547
2547
|
};
|
|
2548
|
-
|
|
2548
|
+
resolve11(lo);
|
|
2549
2549
|
return new Promise(async (r2) => finish = r2);
|
|
2550
2550
|
async function readable({
|
|
2551
2551
|
highWaterMark = 2048 * 8,
|
|
@@ -2707,8 +2707,8 @@ function Postgres(a, b4) {
|
|
|
2707
2707
|
}
|
|
2708
2708
|
async function reserve() {
|
|
2709
2709
|
const queue = queue_default();
|
|
2710
|
-
const c = open.length ? open.shift() : await new Promise((
|
|
2711
|
-
const query = { reserve:
|
|
2710
|
+
const c = open.length ? open.shift() : await new Promise((resolve11, reject) => {
|
|
2711
|
+
const query = { reserve: resolve11, reject };
|
|
2712
2712
|
queries.push(query);
|
|
2713
2713
|
closed.length && connect2(closed.shift(), query);
|
|
2714
2714
|
});
|
|
@@ -2745,9 +2745,9 @@ function Postgres(a, b4) {
|
|
|
2745
2745
|
let uncaughtError, result;
|
|
2746
2746
|
name && await sql2`savepoint ${sql2(name)}`;
|
|
2747
2747
|
try {
|
|
2748
|
-
result = await new Promise((
|
|
2748
|
+
result = await new Promise((resolve11, reject) => {
|
|
2749
2749
|
const x2 = fn2(sql2);
|
|
2750
|
-
Promise.resolve(Array.isArray(x2) ? Promise.all(x2) : x2).then(
|
|
2750
|
+
Promise.resolve(Array.isArray(x2) ? Promise.all(x2) : x2).then(resolve11, reject);
|
|
2751
2751
|
});
|
|
2752
2752
|
if (uncaughtError)
|
|
2753
2753
|
throw uncaughtError;
|
|
@@ -2804,8 +2804,8 @@ function Postgres(a, b4) {
|
|
|
2804
2804
|
return c.execute(query) ? move(c, busy) : move(c, full);
|
|
2805
2805
|
}
|
|
2806
2806
|
function cancel(query) {
|
|
2807
|
-
return new Promise((
|
|
2808
|
-
query.state ? query.active ? connection_default(options).cancel(query.state,
|
|
2807
|
+
return new Promise((resolve11, reject) => {
|
|
2808
|
+
query.state ? query.active ? connection_default(options).cancel(query.state, resolve11, reject) : query.cancelled = { resolve: resolve11, reject } : (queries.remove(query), query.cancelled = true, query.reject(Errors.generic("57014", "canceling statement due to user request")), resolve11());
|
|
2809
2809
|
});
|
|
2810
2810
|
}
|
|
2811
2811
|
async function end({ timeout = null } = {}) {
|
|
@@ -2824,11 +2824,11 @@ function Postgres(a, b4) {
|
|
|
2824
2824
|
async function close() {
|
|
2825
2825
|
await Promise.all(connections.map((c) => c.end()));
|
|
2826
2826
|
}
|
|
2827
|
-
async function destroy(
|
|
2827
|
+
async function destroy(resolve11) {
|
|
2828
2828
|
await Promise.all(connections.map((c) => c.terminate()));
|
|
2829
2829
|
while (queries.length)
|
|
2830
2830
|
queries.shift().reject(Errors.connection("CONNECTION_DESTROYED", options));
|
|
2831
|
-
|
|
2831
|
+
resolve11();
|
|
2832
2832
|
}
|
|
2833
2833
|
function connect2(c, query) {
|
|
2834
2834
|
move(c, connecting);
|
|
@@ -3349,7 +3349,7 @@ function ambientEnvKeyNote(cwd) {
|
|
|
3349
3349
|
return `Note: ${ambient.source} in this directory holds an ABLO_API_KEY, which this command does not load \u2014 it reads only the process environment and your stored login, so a file cannot silently choose a branch. Export the variable, or pass \`--env-file ` + ambient.source + "` to a connect command, to choose it explicitly.";
|
|
3350
3350
|
}
|
|
3351
3351
|
function resolveManagementKey() {
|
|
3352
|
-
if (process.env.
|
|
3352
|
+
if (process.env.ABLO_API_KEY?.startsWith("mk_")) return process.env.ABLO_API_KEY;
|
|
3353
3353
|
const cfg = readConfig();
|
|
3354
3354
|
if (!cfg) return void 0;
|
|
3355
3355
|
const entry = cfg.profiles[activeProfileName(cfg)]?.management;
|
|
@@ -3358,7 +3358,7 @@ function resolveManagementKey() {
|
|
|
3358
3358
|
return entry.apiKey;
|
|
3359
3359
|
}
|
|
3360
3360
|
function resolveOrgManagementKey(options = {}) {
|
|
3361
|
-
if (process.env.
|
|
3361
|
+
if (process.env.ABLO_API_KEY?.startsWith("mk_")) return process.env.ABLO_API_KEY;
|
|
3362
3362
|
const cfg = readConfig({ persistMigrations: options.persistConfigMigrations });
|
|
3363
3363
|
if (!cfg) return void 0;
|
|
3364
3364
|
const profiles = [.../* @__PURE__ */ new Set([
|
|
@@ -3458,7 +3458,7 @@ function requireKey() {
|
|
|
3458
3458
|
if (!apiKey) {
|
|
3459
3459
|
console.error(
|
|
3460
3460
|
import_picocolors3.default.red(" No project management credential.") + import_picocolors3.default.dim(
|
|
3461
|
-
` Run ${import_picocolors3.default.bold("npx ablo login")} \u2014 or set ${import_picocolors3.default.bold("
|
|
3461
|
+
` Run ${import_picocolors3.default.bold("npx ablo login")} \u2014 or set ${import_picocolors3.default.bold("ABLO_API_KEY")} to an ${import_picocolors3.default.bold("mk_")} credential.`
|
|
3462
3462
|
)
|
|
3463
3463
|
);
|
|
3464
3464
|
process.exit(1);
|
|
@@ -3481,15 +3481,18 @@ async function request(path, apiKey, init3 = {}, baseUrl2) {
|
|
|
3481
3481
|
}
|
|
3482
3482
|
return { status: res.status, body };
|
|
3483
3483
|
}
|
|
3484
|
+
function projectListResult(status2, body) {
|
|
3485
|
+
if (status2 !== 200) {
|
|
3486
|
+
const code = typeof body === "object" && body !== null && "code" in body ? body.code : void 0;
|
|
3487
|
+
return { ok: false, reason: typeof code === "string" ? code : `HTTP ${status2}` };
|
|
3488
|
+
}
|
|
3489
|
+
const parsed = import_wire.projectListResponseSchema.safeParse(body);
|
|
3490
|
+
return parsed.success ? { ok: true, projects: parsed.data.data } : { ok: false, reason: "the response did not match the project list" };
|
|
3491
|
+
}
|
|
3484
3492
|
async function listProjects(apiKey, baseUrl2) {
|
|
3485
3493
|
try {
|
|
3486
3494
|
const { status: status2, body } = await request("/api/v1/projects", apiKey, {}, baseUrl2);
|
|
3487
|
-
|
|
3488
|
-
const code = body?.code;
|
|
3489
|
-
return { ok: false, reason: typeof code === "string" ? code : `HTTP ${status2}` };
|
|
3490
|
-
}
|
|
3491
|
-
const parsed = import_wire.projectListResponseSchema.safeParse(body);
|
|
3492
|
-
return parsed.success ? { ok: true, projects: parsed.data.data } : { ok: false, reason: "the response did not match the project list" };
|
|
3495
|
+
return projectListResult(status2, body);
|
|
3493
3496
|
} catch (err) {
|
|
3494
3497
|
return { ok: false, reason: err instanceof Error ? err.message : "the request failed" };
|
|
3495
3498
|
}
|
|
@@ -3538,6 +3541,10 @@ async function ensureProject(slug, name) {
|
|
|
3538
3541
|
return null;
|
|
3539
3542
|
}
|
|
3540
3543
|
}
|
|
3544
|
+
function projectDisplayName(p2) {
|
|
3545
|
+
const spelling = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3546
|
+
return p2.name && spelling(p2.name) !== spelling(p2.slug) ? p2.name : void 0;
|
|
3547
|
+
}
|
|
3541
3548
|
function describeKeys(profile) {
|
|
3542
3549
|
const now = Date.now();
|
|
3543
3550
|
let usable = 0;
|
|
@@ -3566,8 +3573,7 @@ function describeAge(createdAt) {
|
|
|
3566
3573
|
function printList(projects2) {
|
|
3567
3574
|
const active = getActiveProject();
|
|
3568
3575
|
const profiles = readConfig()?.profiles ?? {};
|
|
3569
|
-
const
|
|
3570
|
-
const nameOf = (p2) => p2.name && spelling(p2.name) !== spelling(p2.slug) ? p2.name : "";
|
|
3576
|
+
const nameOf = (p2) => projectDisplayName(p2) ?? "";
|
|
3571
3577
|
const showNames = projects2.some((p2) => nameOf(p2) !== "");
|
|
3572
3578
|
const slugWidth = Math.max(...projects2.map((p2) => p2.slug.length));
|
|
3573
3579
|
const nameWidth = showNames ? Math.max(...projects2.map((p2) => nameOf(p2).length)) : 0;
|
|
@@ -3970,7 +3976,7 @@ var init_observeCliError = __esm({
|
|
|
3970
3976
|
import_errorObservation = require("@abloatai/transaction/errorObservation");
|
|
3971
3977
|
import_errors5 = require("@abloatai/transaction/errors");
|
|
3972
3978
|
dsn = process.env.ABLO_CLI_SENTRY_DSN ?? "https://1ac154bff10b06836e1ea9de9e0d92f0@o4510928209772544.ingest.de.sentry.io/4511660691423312" ?? "";
|
|
3973
|
-
release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.
|
|
3979
|
+
release = process.env.ABLO_CLI_RELEASE ?? "@abloatai/cli@0.58.0";
|
|
3974
3980
|
initialized = false;
|
|
3975
3981
|
nativeProcessExit = process.exit.bind(process);
|
|
3976
3982
|
exitBoundaryInstalled = false;
|
|
@@ -4297,7 +4303,7 @@ var init_src2 = __esm({
|
|
|
4297
4303
|
|
|
4298
4304
|
// src/cliEnvironment.ts
|
|
4299
4305
|
function cliVersion() {
|
|
4300
|
-
return "0.
|
|
4306
|
+
return "0.58.0";
|
|
4301
4307
|
}
|
|
4302
4308
|
function cliOs() {
|
|
4303
4309
|
const value = (0, import_node_os.platform)();
|
|
@@ -4372,7 +4378,9 @@ function trackCliSchemaPushAttempted() {
|
|
|
4372
4378
|
}
|
|
4373
4379
|
function flushProductAnalytics(options = {}) {
|
|
4374
4380
|
if (flushInFlight) return flushInFlight;
|
|
4375
|
-
flushInFlight = flushOnce(options).catch(() =>
|
|
4381
|
+
flushInFlight = flushOnce(options).catch((error) => {
|
|
4382
|
+
void error;
|
|
4383
|
+
}).finally(() => {
|
|
4376
4384
|
flushInFlight = null;
|
|
4377
4385
|
});
|
|
4378
4386
|
return flushInFlight;
|
|
@@ -4395,8 +4403,8 @@ function queueEvent(eventName, properties) {
|
|
|
4395
4403
|
state.queue = [...state.queue, parsed].slice(-MAX_QUEUED_EVENTS);
|
|
4396
4404
|
writeState(state);
|
|
4397
4405
|
if (disclose) {
|
|
4398
|
-
|
|
4399
|
-
"Ablo collects limited usage analytics. Run `ablo telemetry disable` to opt out or `ablo telemetry status` for details
|
|
4406
|
+
process.stderr.write(
|
|
4407
|
+
"Ablo collects limited usage analytics. Run `ablo telemetry disable` to opt out or `ablo telemetry status` for details.\n"
|
|
4400
4408
|
);
|
|
4401
4409
|
}
|
|
4402
4410
|
} catch {
|
|
@@ -4473,8 +4481,9 @@ function writeState(state) {
|
|
|
4473
4481
|
function environmentBlocker() {
|
|
4474
4482
|
if (process.env.ABLO_TELEMETRY_DISABLED === "1") return "ABLO_TELEMETRY_DISABLED";
|
|
4475
4483
|
if (process.env.DO_NOT_TRACK === "1") return "DO_NOT_TRACK";
|
|
4476
|
-
|
|
4477
|
-
|
|
4484
|
+
return TELEMETRY_BLOCKING_ENV.slice(2).find(
|
|
4485
|
+
(name) => truthyEnvironmentValue(process.env[name])
|
|
4486
|
+
) ?? null;
|
|
4478
4487
|
}
|
|
4479
4488
|
function truthyEnvironmentValue(value) {
|
|
4480
4489
|
return value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
@@ -4502,7 +4511,7 @@ function runTelemetryCommand(argv) {
|
|
|
4502
4511
|
if (status2.blockedBy) console.log(`Environment override: ${status2.blockedBy}`);
|
|
4503
4512
|
console.log(`Queued events: ${status2.queuedEvents}`);
|
|
4504
4513
|
}
|
|
4505
|
-
var import_node_crypto2, import_node_fs, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight;
|
|
4514
|
+
var import_node_crypto2, import_node_fs, import_node_path, TELEMETRY_FILE_VERSION, MAX_QUEUED_EVENTS, MAX_FLUSH_EVENTS, DEFAULT_FLUSH_TIMEOUT_MS, flushInFlight, TELEMETRY_BLOCKING_ENV;
|
|
4506
4515
|
var init_telemetry = __esm({
|
|
4507
4516
|
"src/telemetry.ts"() {
|
|
4508
4517
|
"use strict";
|
|
@@ -4519,6 +4528,16 @@ var init_telemetry = __esm({
|
|
|
4519
4528
|
MAX_FLUSH_EVENTS = 20;
|
|
4520
4529
|
DEFAULT_FLUSH_TIMEOUT_MS = 800;
|
|
4521
4530
|
flushInFlight = null;
|
|
4531
|
+
TELEMETRY_BLOCKING_ENV = [
|
|
4532
|
+
"ABLO_TELEMETRY_DISABLED",
|
|
4533
|
+
"DO_NOT_TRACK",
|
|
4534
|
+
"CI",
|
|
4535
|
+
"GITHUB_ACTIONS",
|
|
4536
|
+
"GITLAB_CI",
|
|
4537
|
+
"BUILDKITE",
|
|
4538
|
+
"CIRCLECI",
|
|
4539
|
+
"TF_BUILD"
|
|
4540
|
+
];
|
|
4522
4541
|
}
|
|
4523
4542
|
});
|
|
4524
4543
|
|
|
@@ -4716,16 +4735,9 @@ async function fetchActiveSchema(url, apiKey) {
|
|
|
4716
4735
|
clearTimeout(t);
|
|
4717
4736
|
}
|
|
4718
4737
|
}
|
|
4719
|
-
function conflictStr(c) {
|
|
4720
|
-
if (!c) return "";
|
|
4721
|
-
const parts = import_schema2.participantKindSchema.options.flatMap((k3) => c[k3] ? [`${k3}:${c[k3]}`] : []);
|
|
4722
|
-
return parts.length ? `{${parts.join(",")}}` : "";
|
|
4723
|
-
}
|
|
4724
4738
|
function localModels(schema) {
|
|
4725
4739
|
const json = JSON.parse((0, import_schema.serializeSchema)(schema));
|
|
4726
|
-
|
|
4727
|
-
for (const [key, def] of Object.entries(json.models)) out.set(key, conflictStr(def.conflict));
|
|
4728
|
-
return out;
|
|
4740
|
+
return new Set(Object.keys(json.models));
|
|
4729
4741
|
}
|
|
4730
4742
|
function printPlan(local, remote) {
|
|
4731
4743
|
if (!remote?.models) {
|
|
@@ -4733,21 +4745,17 @@ function printPlan(local, remote) {
|
|
|
4733
4745
|
`);
|
|
4734
4746
|
return;
|
|
4735
4747
|
}
|
|
4736
|
-
const
|
|
4737
|
-
|
|
4738
|
-
const
|
|
4739
|
-
const removed = [...remoteMap.keys()].filter((k3) => !local.has(k3));
|
|
4740
|
-
const changed = [...local.keys()].filter((k3) => remoteMap.has(k3) && remoteMap.get(k3) !== local.get(k3));
|
|
4748
|
+
const remoteKeys = new Set(remote.models.map((model) => model.key));
|
|
4749
|
+
const added = [...local].filter((key) => !remoteKeys.has(key));
|
|
4750
|
+
const removed = [...remoteKeys].filter((key) => !local.has(key));
|
|
4741
4751
|
const verLabel = remote.version != null ? `v${remote.version}` : "active";
|
|
4742
|
-
if (added.length === 0 && removed.length === 0
|
|
4752
|
+
if (added.length === 0 && removed.length === 0) {
|
|
4743
4753
|
console.log(` ${import_picocolors5.default.dim("plan")} ${import_picocolors5.default.dim(`no model-level changes vs deployed ${verLabel} (any field changes apply on push)`)}
|
|
4744
4754
|
`);
|
|
4745
4755
|
return;
|
|
4746
4756
|
}
|
|
4747
4757
|
console.log(` ${import_picocolors5.default.dim("plan")} ${import_picocolors5.default.dim(`vs deployed ${verLabel}:`)}`);
|
|
4748
4758
|
for (const k3 of added) console.log(` ${import_picocolors5.default.green(`+ ${k3}`)} ${import_picocolors5.default.dim("(new model)")}`);
|
|
4749
|
-
for (const k3 of changed)
|
|
4750
|
-
console.log(` ${import_picocolors5.default.yellow(`~ ${k3}`)} ${import_picocolors5.default.dim(`conflict ${remoteMap.get(k3) || "(default)"} \u2192 ${local.get(k3) || "(default)"}`)}`);
|
|
4751
4759
|
for (const k3 of removed) console.log(` ${import_picocolors5.default.red(`- ${k3}`)} ${import_picocolors5.default.dim("(removed \u2014 destructive, needs --force)")}`);
|
|
4752
4760
|
console.log("");
|
|
4753
4761
|
}
|
|
@@ -5038,7 +5046,7 @@ async function push(argv) {
|
|
|
5038
5046
|
}
|
|
5039
5047
|
process.exit(1);
|
|
5040
5048
|
}
|
|
5041
|
-
var import_picocolors5, import_errors7, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema,
|
|
5049
|
+
var import_picocolors5, import_errors7, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT, PUSH_USAGE;
|
|
5042
5050
|
var init_push = __esm({
|
|
5043
5051
|
"src/push.ts"() {
|
|
5044
5052
|
"use strict";
|
|
@@ -5056,7 +5064,6 @@ var init_push = __esm({
|
|
|
5056
5064
|
init_target();
|
|
5057
5065
|
init_theme();
|
|
5058
5066
|
init_renderError();
|
|
5059
|
-
import_schema2 = require("@abloatai/transaction/coordination/schema");
|
|
5060
5067
|
init_telemetry();
|
|
5061
5068
|
DEFAULT_SCHEMA_PATH = "ablo/schema.ts";
|
|
5062
5069
|
DEFAULT_EXPORT = "schema";
|
|
@@ -5083,6 +5090,84 @@ var init_push = __esm({
|
|
|
5083
5090
|
}
|
|
5084
5091
|
});
|
|
5085
5092
|
|
|
5093
|
+
// src/dbProvider.ts
|
|
5094
|
+
function hostAndPort(hostOrTarget) {
|
|
5095
|
+
const withoutScheme = hostOrTarget.trim().replace(/^[a-z0-9+.-]+:\/\//i, "");
|
|
5096
|
+
const at = withoutScheme.lastIndexOf("@");
|
|
5097
|
+
const withoutUserinfo = at === -1 ? withoutScheme : withoutScheme.slice(at + 1);
|
|
5098
|
+
const authority = withoutUserinfo.split("/")[0] ?? "";
|
|
5099
|
+
const parts = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(authority);
|
|
5100
|
+
return { hostname: (parts?.[1] ?? authority).toLowerCase(), port: parts?.[2] ?? "" };
|
|
5101
|
+
}
|
|
5102
|
+
function inDomain(hostname, domain) {
|
|
5103
|
+
return hostname === domain || hostname.endsWith(`.${domain}`);
|
|
5104
|
+
}
|
|
5105
|
+
function detectProvider(hostOrTarget) {
|
|
5106
|
+
const { hostname } = hostAndPort(hostOrTarget);
|
|
5107
|
+
const spec = PROVIDERS.find((p2) => p2.domains.some((domain) => inDomain(hostname, domain)));
|
|
5108
|
+
return spec?.id ?? "generic";
|
|
5109
|
+
}
|
|
5110
|
+
function detectPooler(hostOrTarget) {
|
|
5111
|
+
const { hostname, port } = hostAndPort(hostOrTarget);
|
|
5112
|
+
const provider = detectProvider(hostOrTarget);
|
|
5113
|
+
const spec = PROVIDERS.find((p2) => p2.id === provider);
|
|
5114
|
+
if (spec?.isPooledHost?.(hostname)) {
|
|
5115
|
+
const direct = spec.directTarget?.(hostOrTarget);
|
|
5116
|
+
return direct === void 0 ? { provider, confidence: "host" } : { provider, direct, confidence: "host" };
|
|
5117
|
+
}
|
|
5118
|
+
if (POOLER_PORTS.has(port)) return { provider, confidence: "port" };
|
|
5119
|
+
return null;
|
|
5120
|
+
}
|
|
5121
|
+
function replicationGrantRole(provider) {
|
|
5122
|
+
const specs = PROVIDERS;
|
|
5123
|
+
const spec = specs.find((candidate) => candidate.id === provider);
|
|
5124
|
+
return spec?.replicationGrantRole ?? null;
|
|
5125
|
+
}
|
|
5126
|
+
function logicalReplicationGuidance(provider) {
|
|
5127
|
+
const spec = PROVIDERS.find((p2) => p2.id === provider);
|
|
5128
|
+
if (spec) return spec.logicalReplication;
|
|
5129
|
+
return `run the ALTER SYSTEM above, then restart Postgres (wal_level is not reloadable). On a managed host that refuses ALTER SYSTEM, set wal_level to logical in its dashboard instead`;
|
|
5130
|
+
}
|
|
5131
|
+
var PROVIDERS, POOLER_PORTS;
|
|
5132
|
+
var init_dbProvider = __esm({
|
|
5133
|
+
"src/dbProvider.ts"() {
|
|
5134
|
+
"use strict";
|
|
5135
|
+
init_cjs_shims();
|
|
5136
|
+
PROVIDERS = [
|
|
5137
|
+
{
|
|
5138
|
+
id: "neon",
|
|
5139
|
+
domains: ["neon.tech"],
|
|
5140
|
+
logicalReplication: `enable logical replication in your Neon project settings \u2014 it can't be set over SQL`,
|
|
5141
|
+
// Neon encodes pooling in the endpoint id, so the direct host is the same
|
|
5142
|
+
// name with the marker removed: a fix the reader applies without a lookup.
|
|
5143
|
+
isPooledHost: (hostname) => hostname.includes("-pooler"),
|
|
5144
|
+
directTarget: (hostOrTarget) => hostOrTarget.replace(/-pooler/i, "")
|
|
5145
|
+
},
|
|
5146
|
+
{
|
|
5147
|
+
id: "supabase",
|
|
5148
|
+
domains: ["supabase.co", "supabase.com"],
|
|
5149
|
+
logicalReplication: `raise wal_level to logical in your Supabase project's database settings`,
|
|
5150
|
+
// Supavisor is a separate host entirely (`aws-0-<region>.pooler.supabase.com`),
|
|
5151
|
+
// so there is no direct host to derive from it.
|
|
5152
|
+
isPooledHost: (hostname) => hostname.endsWith(".pooler.supabase.com")
|
|
5153
|
+
},
|
|
5154
|
+
{
|
|
5155
|
+
id: "rds",
|
|
5156
|
+
// Anchored to the real RDS domains, including the China partition, rather
|
|
5157
|
+
// than a bare `.rds.` anywhere in the name.
|
|
5158
|
+
domains: ["rds.amazonaws.com", "rds.amazonaws.com.cn"],
|
|
5159
|
+
logicalReplication: `set rds.logical_replication = 1 in the instance's parameter group, then reboot`,
|
|
5160
|
+
// RDS Proxy fronts the instance under a `.proxy-` subdomain.
|
|
5161
|
+
isPooledHost: (hostname) => hostname.includes(".proxy-"),
|
|
5162
|
+
// Neither the master user nor rds_superuser carries REPLICATION; AWS keeps
|
|
5163
|
+
// it on rdsadmin and exposes it through this role.
|
|
5164
|
+
replicationGrantRole: "rds_replication"
|
|
5165
|
+
}
|
|
5166
|
+
];
|
|
5167
|
+
POOLER_PORTS = /* @__PURE__ */ new Set(["6432", "6543"]);
|
|
5168
|
+
}
|
|
5169
|
+
});
|
|
5170
|
+
|
|
5086
5171
|
// src/remoteValidation.ts
|
|
5087
5172
|
function dialFailureReason(err) {
|
|
5088
5173
|
if (err === null || typeof err !== "object") return null;
|
|
@@ -5179,76 +5264,6 @@ var init_remoteValidation = __esm({
|
|
|
5179
5264
|
}
|
|
5180
5265
|
});
|
|
5181
5266
|
|
|
5182
|
-
// src/dbProvider.ts
|
|
5183
|
-
function hostAndPort(hostOrTarget) {
|
|
5184
|
-
const withoutScheme = hostOrTarget.trim().replace(/^[a-z0-9+.-]+:\/\//i, "");
|
|
5185
|
-
const at = withoutScheme.lastIndexOf("@");
|
|
5186
|
-
const withoutUserinfo = at === -1 ? withoutScheme : withoutScheme.slice(at + 1);
|
|
5187
|
-
const authority = withoutUserinfo.split("/")[0] ?? "";
|
|
5188
|
-
const parts = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(authority);
|
|
5189
|
-
return { hostname: (parts?.[1] ?? authority).toLowerCase(), port: parts?.[2] ?? "" };
|
|
5190
|
-
}
|
|
5191
|
-
function inDomain(hostname, domain) {
|
|
5192
|
-
return hostname === domain || hostname.endsWith(`.${domain}`);
|
|
5193
|
-
}
|
|
5194
|
-
function detectProvider(hostOrTarget) {
|
|
5195
|
-
const { hostname } = hostAndPort(hostOrTarget);
|
|
5196
|
-
const spec = PROVIDERS.find((p2) => p2.domains.some((domain) => inDomain(hostname, domain)));
|
|
5197
|
-
return spec?.id ?? "generic";
|
|
5198
|
-
}
|
|
5199
|
-
function detectPooler(hostOrTarget) {
|
|
5200
|
-
const { hostname, port } = hostAndPort(hostOrTarget);
|
|
5201
|
-
const provider = detectProvider(hostOrTarget);
|
|
5202
|
-
const spec = PROVIDERS.find((p2) => p2.id === provider);
|
|
5203
|
-
if (spec?.isPooledHost?.(hostname)) {
|
|
5204
|
-
const direct = spec.directTarget?.(hostOrTarget);
|
|
5205
|
-
return direct === void 0 ? { provider, confidence: "host" } : { provider, direct, confidence: "host" };
|
|
5206
|
-
}
|
|
5207
|
-
if (POOLER_PORTS.has(port)) return { provider, confidence: "port" };
|
|
5208
|
-
return null;
|
|
5209
|
-
}
|
|
5210
|
-
function logicalReplicationGuidance(provider) {
|
|
5211
|
-
const spec = PROVIDERS.find((p2) => p2.id === provider);
|
|
5212
|
-
if (spec) return spec.logicalReplication;
|
|
5213
|
-
return `run the ALTER SYSTEM above, then restart Postgres (wal_level is not reloadable). On a managed host that refuses ALTER SYSTEM, set wal_level to logical in its dashboard instead`;
|
|
5214
|
-
}
|
|
5215
|
-
var PROVIDERS, POOLER_PORTS;
|
|
5216
|
-
var init_dbProvider = __esm({
|
|
5217
|
-
"src/dbProvider.ts"() {
|
|
5218
|
-
"use strict";
|
|
5219
|
-
init_cjs_shims();
|
|
5220
|
-
PROVIDERS = [
|
|
5221
|
-
{
|
|
5222
|
-
id: "neon",
|
|
5223
|
-
domains: ["neon.tech"],
|
|
5224
|
-
logicalReplication: `enable logical replication in your Neon project settings \u2014 it can't be set over SQL`,
|
|
5225
|
-
// Neon encodes pooling in the endpoint id, so the direct host is the same
|
|
5226
|
-
// name with the marker removed: a fix the reader applies without a lookup.
|
|
5227
|
-
isPooledHost: (hostname) => hostname.includes("-pooler"),
|
|
5228
|
-
directTarget: (hostOrTarget) => hostOrTarget.replace(/-pooler/i, "")
|
|
5229
|
-
},
|
|
5230
|
-
{
|
|
5231
|
-
id: "supabase",
|
|
5232
|
-
domains: ["supabase.co", "supabase.com"],
|
|
5233
|
-
logicalReplication: `raise wal_level to logical in your Supabase project's database settings`,
|
|
5234
|
-
// Supavisor is a separate host entirely (`aws-0-<region>.pooler.supabase.com`),
|
|
5235
|
-
// so there is no direct host to derive from it.
|
|
5236
|
-
isPooledHost: (hostname) => hostname.endsWith(".pooler.supabase.com")
|
|
5237
|
-
},
|
|
5238
|
-
{
|
|
5239
|
-
id: "rds",
|
|
5240
|
-
// Anchored to the real RDS domains, including the China partition, rather
|
|
5241
|
-
// than a bare `.rds.` anywhere in the name.
|
|
5242
|
-
domains: ["rds.amazonaws.com", "rds.amazonaws.com.cn"],
|
|
5243
|
-
logicalReplication: `set rds.logical_replication = 1 in the instance's parameter group, then reboot`,
|
|
5244
|
-
// RDS Proxy fronts the instance under a `.proxy-` subdomain.
|
|
5245
|
-
isPooledHost: (hostname) => hostname.includes(".proxy-")
|
|
5246
|
-
}
|
|
5247
|
-
];
|
|
5248
|
-
POOLER_PORTS = /* @__PURE__ */ new Set(["6432", "6543"]);
|
|
5249
|
-
}
|
|
5250
|
-
});
|
|
5251
|
-
|
|
5252
5267
|
// src/connectSetup.ts
|
|
5253
5268
|
function hostLabel(connectionString) {
|
|
5254
5269
|
try {
|
|
@@ -5280,12 +5295,26 @@ BEGIN
|
|
|
5280
5295
|
END LOOP;
|
|
5281
5296
|
END $$;`;
|
|
5282
5297
|
}
|
|
5298
|
+
function replicationBypassSql(input) {
|
|
5299
|
+
if (input.canGrantBypassRls) return [];
|
|
5300
|
+
return input.tables.flatMap((table) => {
|
|
5301
|
+
const qualified = `${quoteIdent(input.schema)}.${quoteIdent(table)}`;
|
|
5302
|
+
const policy = quoteIdent(`${input.role}_snapshot`);
|
|
5303
|
+
return [
|
|
5304
|
+
// CREATE POLICY has no IF NOT EXISTS, and every step here is safe to
|
|
5305
|
+
// re-run, so the drop carries the idempotency.
|
|
5306
|
+
`DROP POLICY IF EXISTS ${policy} ON ${qualified};`,
|
|
5307
|
+
`CREATE POLICY ${policy} ON ${qualified} FOR SELECT TO ${quoteIdent(input.role)} USING (true);`
|
|
5308
|
+
];
|
|
5309
|
+
});
|
|
5310
|
+
}
|
|
5283
5311
|
function connectSetupSql(input) {
|
|
5284
5312
|
const role = input.role && input.role.length > 0 ? input.role : import_footprint.ABLO_REPLICATION_ROLE;
|
|
5285
5313
|
const writeRole = input.writeRole && input.writeRole.length > 0 ? input.writeRole : import_footprint.ABLO_WRITE_ROLE;
|
|
5286
5314
|
const tables = input.tables ?? [];
|
|
5287
5315
|
const schema = input.schema ?? "public";
|
|
5288
5316
|
const publication = input.publication;
|
|
5317
|
+
const canGrantBypassRls = input.canGrantBypassRls !== false;
|
|
5289
5318
|
const qualifiedTables = tables.map((table) => `${quoteIdent(schema)}.${quoteIdent(table)}`);
|
|
5290
5319
|
const publicationTarget = tables.length > 0 ? `FOR TABLE ${qualifiedTables.join(", ")}` : "FOR ALL TABLES";
|
|
5291
5320
|
const tableList = qualifiedTables.join(", ");
|
|
@@ -5305,9 +5334,11 @@ function connectSetupSql(input) {
|
|
|
5305
5334
|
// 3. A least-privilege role: it can stream replication and SELECT the
|
|
5306
5335
|
// published tables, including the initial snapshot of RLS-protected tables.
|
|
5307
5336
|
// Logical decoding already exposes every published row independently of
|
|
5308
|
-
// RLS
|
|
5309
|
-
|
|
5337
|
+
// RLS, so the reader needs the ordinary SELECT snapshot to match that same
|
|
5338
|
+
// scope. How it gets there depends on what this admin may grant.
|
|
5339
|
+
`CREATE ROLE ${quoteIdent(role)} WITH NOSUPERUSER ${canGrantBypassRls ? "BYPASSRLS " : ""}NOCREATEDB NOCREATEROLE ${canGrantBypassRls ? "REPLICATION NOINHERIT" : "NOREPLICATION INHERIT"} LOGIN PASSWORD '<password>';`,
|
|
5310
5340
|
...replicationReadGrants,
|
|
5341
|
+
...replicationBypassSql({ role, tables, schema, canGrantBypassRls }),
|
|
5311
5342
|
// 4. A distinct DML role: no replication, role administration, ownership,
|
|
5312
5343
|
// schema creation, or DDL. It runs NOBYPASSRLS with row_security on, so on a
|
|
5313
5344
|
// table that HAS row-level-security policies they govern its writes and it
|
|
@@ -5453,7 +5484,15 @@ On Neon enable Logical Replication in the project (Console \u2192 Settings \u219
|
|
|
5453
5484
|
`SELECT rolreplication, rolsuper, rolbypassrls FROM pg_roles WHERE rolname = current_user`
|
|
5454
5485
|
);
|
|
5455
5486
|
const role = roleRows[0];
|
|
5456
|
-
const
|
|
5487
|
+
const grantRole = opts.replicationGrantRole ?? null;
|
|
5488
|
+
const viaGrant = grantRole ? (await sql.unsafe(
|
|
5489
|
+
`SELECT EXISTS (
|
|
5490
|
+
SELECT 1 FROM pg_roles r
|
|
5491
|
+
WHERE r.rolname = $1 AND pg_has_role(current_user, r.oid, 'MEMBER')
|
|
5492
|
+
) AS member`,
|
|
5493
|
+
[grantRole]
|
|
5494
|
+
))[0]?.member === true : false;
|
|
5495
|
+
const hasReplication = Boolean(role && (role.rolreplication || role.rolsuper)) || viaGrant;
|
|
5457
5496
|
items.push(
|
|
5458
5497
|
hasReplication ? {
|
|
5459
5498
|
ok: true,
|
|
@@ -5473,6 +5512,20 @@ On RDS: GRANT rds_replication TO <your_role>;`
|
|
|
5473
5512
|
JOIN pg_class c ON c.relnamespace = n.oid AND c.relname = pt.tablename
|
|
5474
5513
|
WHERE pt.pubname = $1 AND pt.schemaname = $2
|
|
5475
5514
|
AND row_security_active(c.oid)
|
|
5515
|
+
AND NOT EXISTS (
|
|
5516
|
+
SELECT 1 FROM pg_policies p
|
|
5517
|
+
WHERE p.schemaname = pt.schemaname
|
|
5518
|
+
AND p.tablename = pt.tablename
|
|
5519
|
+
AND p.permissive = 'PERMISSIVE'
|
|
5520
|
+
AND p.cmd IN ('ALL', 'SELECT')
|
|
5521
|
+
AND p.qual = 'true'
|
|
5522
|
+
-- Membership, not containment: pg_policies.roles is name[], while
|
|
5523
|
+
-- ARRAY['public'] is text[]. Postgres has no name[] @> text[] operator, so
|
|
5524
|
+
-- the containment spelling fails at execution rather than at parse time:
|
|
5525
|
+
-- the probe threw instead of reporting, which reads as an unreachable
|
|
5526
|
+
-- database rather than a readable one.
|
|
5527
|
+
AND ('public' = ANY(p.roles) OR current_user = ANY(p.roles))
|
|
5528
|
+
)
|
|
5476
5529
|
ORDER BY table_name`,
|
|
5477
5530
|
[publication, schema]
|
|
5478
5531
|
);
|
|
@@ -5482,7 +5535,9 @@ On RDS: GRANT rds_replication TO <your_role>;`
|
|
|
5482
5535
|
ok: false,
|
|
5483
5536
|
label: `${rlsRelevant.length} published table${rlsRelevant.length === 1 ? "" : "s"} hide historical rows behind RLS`,
|
|
5484
5537
|
fix: `ALTER ROLE current_user WITH BYPASSRLS;
|
|
5485
|
-
|
|
5538
|
+
Where the provider reserves that attribute (Amazon RDS, Aurora), give the reader a policy instead:
|
|
5539
|
+
CREATE POLICY <reader>_snapshot ON <table> FOR SELECT TO <reader> USING (true);
|
|
5540
|
+
Logical replication already exposes every published row; either lets the ordinary initial SELECT read that same scope.`
|
|
5486
5541
|
}
|
|
5487
5542
|
);
|
|
5488
5543
|
const badRows = await sql.unsafe(
|
|
@@ -6020,7 +6075,7 @@ async function fetchDataSourceState(apiUrl3, apiKey, timeoutMs = 4e3) {
|
|
|
6020
6075
|
async function readLocalSchemaHash(schemaPath = DEFAULT_SCHEMA_PATH) {
|
|
6021
6076
|
try {
|
|
6022
6077
|
const schema = await loadSchema(schemaPath, DEFAULT_EXPORT);
|
|
6023
|
-
return (0,
|
|
6078
|
+
return (0, import_schema3.schemaHash)(schema);
|
|
6024
6079
|
} catch {
|
|
6025
6080
|
return null;
|
|
6026
6081
|
}
|
|
@@ -6091,7 +6146,7 @@ function blockers(input) {
|
|
|
6091
6146
|
}
|
|
6092
6147
|
return found;
|
|
6093
6148
|
}
|
|
6094
|
-
var import_wire5,
|
|
6149
|
+
var import_wire5, import_schema3, WRITE_READY_VERDICT;
|
|
6095
6150
|
var init_readiness = __esm({
|
|
6096
6151
|
"src/readiness.ts"() {
|
|
6097
6152
|
"use strict";
|
|
@@ -6100,7 +6155,7 @@ var init_readiness = __esm({
|
|
|
6100
6155
|
init_push();
|
|
6101
6156
|
init_dbProvider();
|
|
6102
6157
|
init_remoteValidation();
|
|
6103
|
-
|
|
6158
|
+
import_schema3 = require("@abloatai/transaction/schema");
|
|
6104
6159
|
WRITE_READY_VERDICT = "write infrastructure is ready. Your database constraints and row-level policies still apply.";
|
|
6105
6160
|
}
|
|
6106
6161
|
});
|
|
@@ -6128,7 +6183,17 @@ function connectApplyPlan(input) {
|
|
|
6128
6183
|
const schema = input.schema ?? "public";
|
|
6129
6184
|
const publication = input.publication;
|
|
6130
6185
|
const provider = input.provider ?? "generic";
|
|
6131
|
-
const
|
|
6186
|
+
const canGrantBypassRls = input.canGrantBypassRls !== false;
|
|
6187
|
+
const canGrantReplication = input.canGrantReplication !== false;
|
|
6188
|
+
const grantedReplicationRole = canGrantReplication ? null : replicationGrantRole(provider);
|
|
6189
|
+
const recipe = connectSetupSql({
|
|
6190
|
+
tables,
|
|
6191
|
+
role,
|
|
6192
|
+
writeRole,
|
|
6193
|
+
schema,
|
|
6194
|
+
publication,
|
|
6195
|
+
canGrantBypassRls
|
|
6196
|
+
});
|
|
6132
6197
|
const isWal = (s) => s.startsWith("ALTER SYSTEM SET wal_level");
|
|
6133
6198
|
const isPublication = (s) => s.startsWith("CREATE PUBLICATION");
|
|
6134
6199
|
const isRoleCreate = (s) => s.startsWith("CREATE ROLE ");
|
|
@@ -6176,19 +6241,46 @@ END $$;`
|
|
|
6176
6241
|
{
|
|
6177
6242
|
key: "replication-role",
|
|
6178
6243
|
title: "Create the read-only login Ablo reads with",
|
|
6179
|
-
detail: `${role} \u2014 it can follow your changes and snapshot the same published rows, including through RLS`,
|
|
6244
|
+
detail: canGrantBypassRls ? `${role} \u2014 it can follow your changes and snapshot the same published rows, including through RLS` : `${role} \u2014 it can follow your changes, and reads the published rows through a SELECT policy of its own, because this provider reserves BYPASSRLS`,
|
|
6180
6245
|
sql: [
|
|
6181
6246
|
idempotentRole(
|
|
6182
6247
|
role,
|
|
6183
|
-
|
|
6248
|
+
// NOINHERIT everywhere the capability is an attribute: the reader
|
|
6249
|
+
// should hold what it was given and nothing that arrives later.
|
|
6250
|
+
// Where the provider lends REPLICATION as a role instead, the
|
|
6251
|
+
// membership only confers it by inheriting — a NOINHERIT member holds
|
|
6252
|
+
// it in name, `pg_has_role(..., 'USAGE')` is false, and replication
|
|
6253
|
+
// fails while every "was it granted" check says yes. So the grant
|
|
6254
|
+
// path inherits, and its only membership is the one granted below.
|
|
6255
|
+
`NOSUPERUSER ${canGrantBypassRls ? "BYPASSRLS " : ""}NOCREATEDB NOCREATEROLE ${canGrantReplication ? "REPLICATION" : "NOREPLICATION"} ${grantedReplicationRole ? "INHERIT" : "NOINHERIT"}`,
|
|
6184
6256
|
input.credentials.replicationClause,
|
|
6185
6257
|
input.rotate === true
|
|
6186
6258
|
),
|
|
6187
6259
|
// Unlike a password, this is a required invariant rather than secret
|
|
6188
6260
|
// material owned by one plane. Re-assert it for an existing pre-snapshot
|
|
6189
6261
|
// role so `connect apply` repairs the exact upgrade gap that otherwise
|
|
6190
|
-
// certifies an RLS-filtered empty snapshot as complete.
|
|
6191
|
-
|
|
6262
|
+
// certifies an RLS-filtered empty snapshot as complete. Where the
|
|
6263
|
+
// attribute cannot be granted at all, the policies in the grants step
|
|
6264
|
+
// carry the same invariant.
|
|
6265
|
+
...canGrantBypassRls ? [`ALTER ROLE ${quoteIdent(role)} WITH BYPASSRLS;`] : [],
|
|
6266
|
+
// The provider keeps REPLICATION on an internal superuser and lends it
|
|
6267
|
+
// through a role. Without this the reader authenticates and then cannot
|
|
6268
|
+
// open a replication slot, which surfaces far from its cause.
|
|
6269
|
+
...grantedReplicationRole ? [
|
|
6270
|
+
// WITH INHERIT TRUE, because Postgres 16 records inheritance on
|
|
6271
|
+
// the MEMBERSHIP rather than only on the role. A member that does
|
|
6272
|
+
// not inherit holds the grant without holding what it carries:
|
|
6273
|
+
// `pg_has_role(..., 'MEMBER')` is true, `USAGE` is false, and
|
|
6274
|
+
// replication does not work while every "was it granted" check
|
|
6275
|
+
// says yes.
|
|
6276
|
+
//
|
|
6277
|
+
// Stated on the grant rather than left to the role's default so
|
|
6278
|
+
// it also repairs a reader created before this path existed.
|
|
6279
|
+
// `ALTER ROLE ... INHERIT` does not: it changes the default for
|
|
6280
|
+
// FUTURE memberships and leaves the recorded one untouched, which
|
|
6281
|
+
// is a fix that reports success and changes nothing.
|
|
6282
|
+
`GRANT ${quoteIdent(grantedReplicationRole)} TO ${quoteIdent(role)} WITH INHERIT TRUE;`
|
|
6283
|
+
] : []
|
|
6192
6284
|
]
|
|
6193
6285
|
},
|
|
6194
6286
|
{
|
|
@@ -6288,14 +6380,14 @@ function reapplyBlocker(input) {
|
|
|
6288
6380
|
}
|
|
6289
6381
|
async function adminCanCreateRoles(sql) {
|
|
6290
6382
|
const rows = await sql.unsafe(
|
|
6291
|
-
`SELECT rolname, rolsuper, rolcreaterole FROM pg_roles WHERE rolname = current_user`
|
|
6383
|
+
`SELECT rolname, rolsuper, rolcreaterole, rolbypassrls, rolreplication FROM pg_roles WHERE rolname = current_user`
|
|
6292
6384
|
);
|
|
6293
6385
|
return rows[0] ?? null;
|
|
6294
6386
|
}
|
|
6295
6387
|
async function schemaDeclaredTables() {
|
|
6296
6388
|
try {
|
|
6297
6389
|
const schema = await loadSchema(DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT);
|
|
6298
|
-
const json = JSON.parse((0,
|
|
6390
|
+
const json = JSON.parse((0, import_schema4.serializeSchema)(schema));
|
|
6299
6391
|
const tables = Object.entries(json.models).map(([key, model]) => model.tableName ?? key);
|
|
6300
6392
|
return tables.length > 0 ? tables : null;
|
|
6301
6393
|
} catch {
|
|
@@ -6368,7 +6460,7 @@ function alreadyConnectedElsewhere(held) {
|
|
|
6368
6460
|
const where = held.project ? `project ${held.project}, branch ${held.branch}` : `branch ${held.branch}`;
|
|
6369
6461
|
return `This database schema is already connected to ${where}. A (database, schema) binding belongs to one plane at a time.`;
|
|
6370
6462
|
}
|
|
6371
|
-
var import_wire6,
|
|
6463
|
+
var import_wire6, import_schema4;
|
|
6372
6464
|
var init_connectPreflight = __esm({
|
|
6373
6465
|
"src/connectPreflight.ts"() {
|
|
6374
6466
|
"use strict";
|
|
@@ -6377,7 +6469,7 @@ var init_connectPreflight = __esm({
|
|
|
6377
6469
|
import_wire6 = require("@abloatai/transaction/wire");
|
|
6378
6470
|
init_controlPlane();
|
|
6379
6471
|
init_push();
|
|
6380
|
-
|
|
6472
|
+
import_schema4 = require("@abloatai/transaction/schema");
|
|
6381
6473
|
init_readiness();
|
|
6382
6474
|
}
|
|
6383
6475
|
});
|
|
@@ -6709,7 +6801,16 @@ ${ambient}` : ""}`,
|
|
|
6709
6801
|
walAlreadyLogical: walReady,
|
|
6710
6802
|
provider,
|
|
6711
6803
|
existingPublication,
|
|
6712
|
-
inheritGrants
|
|
6804
|
+
inheritGrants,
|
|
6805
|
+
// Read off the connected admin rather than guessed from the hostname. A
|
|
6806
|
+
// role can only hand out an attribute it holds, and on RDS and Aurora
|
|
6807
|
+
// BYPASSRLS is reserved to `rdsadmin`, so the recipe substitutes explicit
|
|
6808
|
+
// SELECT policies for the reader.
|
|
6809
|
+
canGrantBypassRls: capability?.rolbypassrls === true,
|
|
6810
|
+
// Same rule, second attribute: RDS and Aurora keep REPLICATION on
|
|
6811
|
+
// rdsadmin and lend it as `rds_replication`, so the recipe grants that
|
|
6812
|
+
// role rather than setting an attribute this admin cannot pass on.
|
|
6813
|
+
canGrantReplication: capability?.rolreplication === true
|
|
6713
6814
|
});
|
|
6714
6815
|
const steps = buildPlan("scram-verifier");
|
|
6715
6816
|
if (pubReconcile.removed.length > 0 || pubReconcile.recreated) {
|
|
@@ -6791,7 +6892,14 @@ ${ambient}` : ""}`,
|
|
|
6791
6892
|
}
|
|
6792
6893
|
const replicationProbe = await probeAsRole(
|
|
6793
6894
|
replicationUrl,
|
|
6794
|
-
(sql) => probeReadiness(sql, {
|
|
6895
|
+
(sql) => probeReadiness(sql, {
|
|
6896
|
+
coordinatedTables,
|
|
6897
|
+
schema: args.schema,
|
|
6898
|
+
publication,
|
|
6899
|
+
// The reader may hold REPLICATION through the provider's role rather than
|
|
6900
|
+
// the attribute, which is the only shape available on RDS and Aurora.
|
|
6901
|
+
replicationGrantRole: replicationGrantRole(provider)
|
|
6902
|
+
})
|
|
6795
6903
|
);
|
|
6796
6904
|
const writeProbe = await probeAsRole(
|
|
6797
6905
|
writeUrl,
|
|
@@ -7441,7 +7549,11 @@ ${ambient}` : ""}`,
|
|
|
7441
7549
|
`);
|
|
7442
7550
|
const replication = await probeAndReport(dbUrl, "replication", {
|
|
7443
7551
|
schema: args.schema,
|
|
7444
|
-
publication
|
|
7552
|
+
publication,
|
|
7553
|
+
// Derived from the host being dialled: where the provider lends REPLICATION
|
|
7554
|
+
// as a role rather than granting the attribute, membership is what the
|
|
7555
|
+
// reader actually holds.
|
|
7556
|
+
replicationGrantRole: replicationGrantRole(detectProvider(dbUrl))
|
|
7445
7557
|
});
|
|
7446
7558
|
console.log(`
|
|
7447
7559
|
${import_picocolors12.default.bold("Direct-write role")}
|
|
@@ -7734,6 +7846,7 @@ var init_connect = __esm({
|
|
|
7734
7846
|
init_cjs_shims();
|
|
7735
7847
|
import_errors11 = require("@abloatai/transaction/errors");
|
|
7736
7848
|
import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
7849
|
+
init_dbProvider();
|
|
7737
7850
|
init_src();
|
|
7738
7851
|
import_footprint3 = require("@abloatai/transaction/footprint");
|
|
7739
7852
|
init_dbRole();
|
|
@@ -7980,7 +8093,7 @@ var require_util = __commonJS({
|
|
|
7980
8093
|
return path;
|
|
7981
8094
|
}
|
|
7982
8095
|
exports2.normalize = normalize;
|
|
7983
|
-
function
|
|
8096
|
+
function join9(aRoot, aPath) {
|
|
7984
8097
|
if (aRoot === "") {
|
|
7985
8098
|
aRoot = ".";
|
|
7986
8099
|
}
|
|
@@ -8012,7 +8125,7 @@ var require_util = __commonJS({
|
|
|
8012
8125
|
}
|
|
8013
8126
|
return joined;
|
|
8014
8127
|
}
|
|
8015
|
-
exports2.join =
|
|
8128
|
+
exports2.join = join9;
|
|
8016
8129
|
exports2.isAbsolute = function(aPath) {
|
|
8017
8130
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
8018
8131
|
};
|
|
@@ -8185,7 +8298,7 @@ var require_util = __commonJS({
|
|
|
8185
8298
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
8186
8299
|
}
|
|
8187
8300
|
}
|
|
8188
|
-
sourceURL =
|
|
8301
|
+
sourceURL = join9(urlGenerate(parsed), sourceURL);
|
|
8189
8302
|
}
|
|
8190
8303
|
return normalize(sourceURL);
|
|
8191
8304
|
}
|
|
@@ -28205,9 +28318,9 @@ ${lanes.join("\n")}
|
|
|
28205
28318
|
return getSpanOfTokenAtPosition(sourceFile, node.pos);
|
|
28206
28319
|
}
|
|
28207
28320
|
Debug.assert(!isJSDoc(errorNode));
|
|
28208
|
-
const
|
|
28209
|
-
const pos =
|
|
28210
|
-
if (
|
|
28321
|
+
const isMissing2 = nodeIsMissing(errorNode);
|
|
28322
|
+
const pos = isMissing2 || isJsxText(node) ? errorNode.pos : skipTrivia(sourceFile.text, errorNode.pos);
|
|
28323
|
+
if (isMissing2) {
|
|
28211
28324
|
Debug.assert(pos === errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
|
|
28212
28325
|
Debug.assert(pos === errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
|
|
28213
28326
|
} else {
|
|
@@ -132684,7 +132797,7 @@ ${lanes.join("\n")}
|
|
|
132684
132797
|
}
|
|
132685
132798
|
}
|
|
132686
132799
|
function createImportCallExpressionAMD(arg, containsLexicalThis) {
|
|
132687
|
-
const
|
|
132800
|
+
const resolve11 = factory2.createUniqueName("resolve");
|
|
132688
132801
|
const reject = factory2.createUniqueName("reject");
|
|
132689
132802
|
const parameters = [
|
|
132690
132803
|
factory2.createParameterDeclaration(
|
|
@@ -132693,7 +132806,7 @@ ${lanes.join("\n")}
|
|
|
132693
132806
|
/*dotDotDotToken*/
|
|
132694
132807
|
void 0,
|
|
132695
132808
|
/*name*/
|
|
132696
|
-
|
|
132809
|
+
resolve11
|
|
132697
132810
|
),
|
|
132698
132811
|
factory2.createParameterDeclaration(
|
|
132699
132812
|
/*modifiers*/
|
|
@@ -132710,7 +132823,7 @@ ${lanes.join("\n")}
|
|
|
132710
132823
|
factory2.createIdentifier("require"),
|
|
132711
132824
|
/*typeArguments*/
|
|
132712
132825
|
void 0,
|
|
132713
|
-
[factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]),
|
|
132826
|
+
[factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve11, reject]
|
|
132714
132827
|
)
|
|
132715
132828
|
)
|
|
132716
132829
|
]);
|
|
@@ -172633,9 +172746,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
172633
172746
|
const sourceFile = getValidSourceFile(fileName);
|
|
172634
172747
|
const span = createTextSpanFromBounds(start, end);
|
|
172635
172748
|
const formatContext = ts_formatting_exports.getFormatContext(formatOptions, host);
|
|
172636
|
-
return flatMap(deduplicate(errorCodes68, equateValues, compareValues), (
|
|
172749
|
+
return flatMap(deduplicate(errorCodes68, equateValues, compareValues), (errorCode2) => {
|
|
172637
172750
|
cancellationToken.throwIfCancellationRequested();
|
|
172638
|
-
return ts_codefix_exports.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences });
|
|
172751
|
+
return ts_codefix_exports.getFixes({ errorCode: errorCode2, sourceFile, span, program, host, cancellationToken, formatContext, preferences });
|
|
172639
172752
|
});
|
|
172640
172753
|
}
|
|
172641
172754
|
function getCombinedCodeFix(scope, fixId56, formatOptions, preferences = emptyOptions) {
|
|
@@ -174473,8 +174586,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174473
174586
|
fixIds: [fixId2],
|
|
174474
174587
|
errorCodes: errorCodes2,
|
|
174475
174588
|
getCodeActions: function getCodeActionsToAddMissingAsync(context) {
|
|
174476
|
-
const { sourceFile, errorCode, cancellationToken, program, span } = context;
|
|
174477
|
-
const diagnostic = find(program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span,
|
|
174589
|
+
const { sourceFile, errorCode: errorCode2, cancellationToken, program, span } = context;
|
|
174590
|
+
const diagnostic = find(program.getTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span, errorCode2));
|
|
174478
174591
|
const directSpan = diagnostic && diagnostic.relatedInformation && find(diagnostic.relatedInformation, (r2) => r2.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code);
|
|
174479
174592
|
const decl = getFixableErrorSpanDeclaration(sourceFile, directSpan);
|
|
174480
174593
|
if (!decl) {
|
|
@@ -174536,8 +174649,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174536
174649
|
});
|
|
174537
174650
|
return decl;
|
|
174538
174651
|
}
|
|
174539
|
-
function getIsMatchingAsyncError(span,
|
|
174540
|
-
return ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code ===
|
|
174652
|
+
function getIsMatchingAsyncError(span, errorCode2) {
|
|
174653
|
+
return ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode2 && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_mean_to_mark_this_function_as_async.code);
|
|
174541
174654
|
}
|
|
174542
174655
|
var fixId3 = "addMissingAwait";
|
|
174543
174656
|
var propertyAccessCode = Diagnostics.Property_0_does_not_exist_on_type_1.code;
|
|
@@ -174568,16 +174681,16 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174568
174681
|
fixIds: [fixId3],
|
|
174569
174682
|
errorCodes: errorCodes3,
|
|
174570
174683
|
getCodeActions: function getCodeActionsToAddMissingAwait(context) {
|
|
174571
|
-
const { sourceFile, errorCode, span, cancellationToken, program } = context;
|
|
174572
|
-
const expression = getAwaitErrorSpanExpression(sourceFile,
|
|
174684
|
+
const { sourceFile, errorCode: errorCode2, span, cancellationToken, program } = context;
|
|
174685
|
+
const expression = getAwaitErrorSpanExpression(sourceFile, errorCode2, span, cancellationToken, program);
|
|
174573
174686
|
if (!expression) {
|
|
174574
174687
|
return;
|
|
174575
174688
|
}
|
|
174576
174689
|
const checker = context.program.getTypeChecker();
|
|
174577
174690
|
const trackChanges = (cb) => ts_textChanges_exports.ChangeTracker.with(context, cb);
|
|
174578
174691
|
return compact([
|
|
174579
|
-
getDeclarationSiteFix(context, expression,
|
|
174580
|
-
getUseSiteFix(context, expression,
|
|
174692
|
+
getDeclarationSiteFix(context, expression, errorCode2, checker, trackChanges),
|
|
174693
|
+
getUseSiteFix(context, expression, errorCode2, checker, trackChanges)
|
|
174581
174694
|
]);
|
|
174582
174695
|
},
|
|
174583
174696
|
getAllCodeActions: (context) => {
|
|
@@ -174594,18 +174707,18 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174594
174707
|
});
|
|
174595
174708
|
}
|
|
174596
174709
|
});
|
|
174597
|
-
function getAwaitErrorSpanExpression(sourceFile,
|
|
174710
|
+
function getAwaitErrorSpanExpression(sourceFile, errorCode2, span, cancellationToken, program) {
|
|
174598
174711
|
const expression = getFixableErrorSpanExpression(sourceFile, span);
|
|
174599
|
-
return expression && isMissingAwaitError(sourceFile,
|
|
174712
|
+
return expression && isMissingAwaitError(sourceFile, errorCode2, span, cancellationToken, program) && isInsideAwaitableBody(expression) ? expression : void 0;
|
|
174600
174713
|
}
|
|
174601
|
-
function getDeclarationSiteFix(context, expression,
|
|
174714
|
+
function getDeclarationSiteFix(context, expression, errorCode2, checker, trackChanges, fixedDeclarations) {
|
|
174602
174715
|
const { sourceFile, program, cancellationToken } = context;
|
|
174603
174716
|
const awaitableInitializers = findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker);
|
|
174604
174717
|
if (awaitableInitializers) {
|
|
174605
174718
|
const initializerChanges = trackChanges((t) => {
|
|
174606
|
-
forEach(awaitableInitializers.initializers, ({ expression: expression2 }) => makeChange3(t,
|
|
174719
|
+
forEach(awaitableInitializers.initializers, ({ expression: expression2 }) => makeChange3(t, errorCode2, sourceFile, checker, expression2, fixedDeclarations));
|
|
174607
174720
|
if (fixedDeclarations && awaitableInitializers.needsSecondPassForFixAll) {
|
|
174608
|
-
makeChange3(t,
|
|
174721
|
+
makeChange3(t, errorCode2, sourceFile, checker, expression, fixedDeclarations);
|
|
174609
174722
|
}
|
|
174610
174723
|
});
|
|
174611
174724
|
return createCodeFixActionWithoutFixAll(
|
|
@@ -174615,14 +174728,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174615
174728
|
);
|
|
174616
174729
|
}
|
|
174617
174730
|
}
|
|
174618
|
-
function getUseSiteFix(context, expression,
|
|
174619
|
-
const changes = trackChanges((t) => makeChange3(t,
|
|
174731
|
+
function getUseSiteFix(context, expression, errorCode2, checker, trackChanges, fixedDeclarations) {
|
|
174732
|
+
const changes = trackChanges((t) => makeChange3(t, errorCode2, context.sourceFile, checker, expression, fixedDeclarations));
|
|
174620
174733
|
return createCodeFixAction(fixId3, changes, Diagnostics.Add_await, fixId3, Diagnostics.Fix_all_expressions_possibly_missing_await);
|
|
174621
174734
|
}
|
|
174622
|
-
function isMissingAwaitError(sourceFile,
|
|
174735
|
+
function isMissingAwaitError(sourceFile, errorCode2, span, cancellationToken, program) {
|
|
174623
174736
|
const checker = program.getTypeChecker();
|
|
174624
174737
|
const diagnostics = checker.getDiagnostics(sourceFile, cancellationToken);
|
|
174625
|
-
return some(diagnostics, ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code ===
|
|
174738
|
+
return some(diagnostics, ({ start, length: length2, relatedInformation, code }) => isNumber(start) && isNumber(length2) && textSpansEqual({ start, length: length2 }, span) && code === errorCode2 && !!relatedInformation && some(relatedInformation, (related) => related.code === Diagnostics.Did_you_forget_to_use_await.code));
|
|
174626
174739
|
}
|
|
174627
174740
|
function findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker) {
|
|
174628
174741
|
const identifiers = getIdentifiersFromErrorSpanExpression(expression, checker);
|
|
@@ -174707,7 +174820,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174707
174820
|
function isInsideAwaitableBody(node) {
|
|
174708
174821
|
return node.flags & 65536 || !!findAncestor(node, (ancestor) => ancestor.parent && isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor || isBlock(ancestor) && (ancestor.parent.kind === 262 || ancestor.parent.kind === 218 || ancestor.parent.kind === 219 || ancestor.parent.kind === 174));
|
|
174709
174822
|
}
|
|
174710
|
-
function makeChange3(changeTracker,
|
|
174823
|
+
function makeChange3(changeTracker, errorCode2, sourceFile, checker, insertionSite, fixedDeclarations) {
|
|
174711
174824
|
if (isForOfStatement(insertionSite.parent) && !insertionSite.parent.awaitModifier) {
|
|
174712
174825
|
const exprType = checker.getTypeAtLocation(insertionSite);
|
|
174713
174826
|
const asyncIter = checker.getAnyAsyncIterableType();
|
|
@@ -174732,7 +174845,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174732
174845
|
const newNode = checker.getPromisedTypeOfPromise(type) ? factory.createAwaitExpression(side) : side;
|
|
174733
174846
|
changeTracker.replaceNode(sourceFile, side, newNode);
|
|
174734
174847
|
}
|
|
174735
|
-
} else if (
|
|
174848
|
+
} else if (errorCode2 === propertyAccessCode && isPropertyAccessExpression(insertionSite.parent)) {
|
|
174736
174849
|
if (fixedDeclarations && isIdentifier2(insertionSite.parent.expression)) {
|
|
174737
174850
|
const symbol = checker.getSymbolAtLocation(insertionSite.parent.expression);
|
|
174738
174851
|
if (symbol && fixedDeclarations.has(getSymbolId(symbol))) {
|
|
@@ -174745,7 +174858,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
174745
174858
|
factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite.parent.expression))
|
|
174746
174859
|
);
|
|
174747
174860
|
insertLeadingSemicolonIfNeeded(changeTracker, insertionSite.parent.expression, sourceFile);
|
|
174748
|
-
} else if (contains(callableConstructableErrorCodes,
|
|
174861
|
+
} else if (contains(callableConstructableErrorCodes, errorCode2) && isCallOrNewExpression(insertionSite.parent)) {
|
|
174749
174862
|
if (fixedDeclarations && isIdentifier2(insertionSite)) {
|
|
174750
174863
|
const symbol = checker.getSymbolAtLocation(insertionSite);
|
|
174751
174864
|
if (symbol && fixedDeclarations.has(getSymbolId(symbol))) {
|
|
@@ -177518,10 +177631,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
177518
177631
|
registerCodeFix({
|
|
177519
177632
|
errorCodes: errorCodes19,
|
|
177520
177633
|
getCodeActions(context) {
|
|
177521
|
-
const { errorCode, preferences, sourceFile, span, program } = context;
|
|
177634
|
+
const { errorCode: errorCode2, preferences, sourceFile, span, program } = context;
|
|
177522
177635
|
const info = getFixInfos(
|
|
177523
177636
|
context,
|
|
177524
|
-
|
|
177637
|
+
errorCode2,
|
|
177525
177638
|
span.start,
|
|
177526
177639
|
/*useAutoImportProvider*/
|
|
177527
177640
|
true
|
|
@@ -178459,14 +178572,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
178459
178572
|
return { kind: 3, moduleSpecifierKind: void 0, moduleSpecifier, importKind, addAsTypeOnly, useRequire };
|
|
178460
178573
|
}
|
|
178461
178574
|
}
|
|
178462
|
-
function getFixInfos(context,
|
|
178575
|
+
function getFixInfos(context, errorCode2, pos, useAutoImportProvider) {
|
|
178463
178576
|
const symbolToken = getTokenAtPosition(context.sourceFile, pos);
|
|
178464
178577
|
let info;
|
|
178465
|
-
if (
|
|
178578
|
+
if (errorCode2 === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
|
|
178466
178579
|
info = getFixesInfoForUMDImport(context, symbolToken);
|
|
178467
178580
|
} else if (!isIdentifier2(symbolToken)) {
|
|
178468
178581
|
return void 0;
|
|
178469
|
-
} else if (
|
|
178582
|
+
} else if (errorCode2 === Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code) {
|
|
178470
178583
|
const symbolName2 = single(getSymbolNamesToImport(context.sourceFile, context.program.getTypeChecker(), symbolToken, context.program.getCompilerOptions()));
|
|
178471
178584
|
const fix = getTypeOnlyPromotionFix(context.sourceFile, symbolToken, symbolName2, context.program);
|
|
178472
178585
|
return fix && [{ fix, symbolName: symbolName2, errorIdentifierText: symbolToken.text }];
|
|
@@ -179296,11 +179409,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179296
179409
|
registerCodeFix({
|
|
179297
179410
|
errorCodes: errorCodes21,
|
|
179298
179411
|
getCodeActions: function getCodeActionsToFixOverrideModifierIssues(context) {
|
|
179299
|
-
const { errorCode, span } = context;
|
|
179300
|
-
const info = errorCodeFixIdMap[
|
|
179412
|
+
const { errorCode: errorCode2, span } = context;
|
|
179413
|
+
const info = errorCodeFixIdMap[errorCode2];
|
|
179301
179414
|
if (!info) return emptyArray;
|
|
179302
179415
|
const { descriptions, fixId: fixId56, fixAllDescriptions } = info;
|
|
179303
|
-
const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => dispatchChanges(changes2, context,
|
|
179416
|
+
const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => dispatchChanges(changes2, context, errorCode2, span.start));
|
|
179304
179417
|
return [
|
|
179305
179418
|
createCodeFixActionMaybeFixAll(fixName, changes, descriptions, fixId56, fixAllDescriptions)
|
|
179306
179419
|
];
|
|
@@ -179315,8 +179428,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179315
179428
|
dispatchChanges(changes, context, code, start);
|
|
179316
179429
|
})
|
|
179317
179430
|
});
|
|
179318
|
-
function dispatchChanges(changeTracker, context,
|
|
179319
|
-
switch (
|
|
179431
|
+
function dispatchChanges(changeTracker, context, errorCode2, pos) {
|
|
179432
|
+
switch (errorCode2) {
|
|
179320
179433
|
case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code:
|
|
179321
179434
|
case Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code:
|
|
179322
179435
|
case Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code:
|
|
@@ -179329,7 +179442,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179329
179442
|
case Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code:
|
|
179330
179443
|
return doRemoveOverrideModifierChange(changeTracker, context.sourceFile, pos);
|
|
179331
179444
|
default:
|
|
179332
|
-
Debug.fail("Unexpected error code: " +
|
|
179445
|
+
Debug.fail("Unexpected error code: " + errorCode2);
|
|
179333
179446
|
}
|
|
179334
179447
|
}
|
|
179335
179448
|
function doAddOverrideModifierChange(changeTracker, sourceFile, pos) {
|
|
@@ -179702,8 +179815,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179702
179815
|
registerCodeFix({
|
|
179703
179816
|
errorCodes: errorCodes26,
|
|
179704
179817
|
getCodeActions(context) {
|
|
179705
|
-
const { sourceFile, errorCode } = context;
|
|
179706
|
-
const info = getInfo8(sourceFile, context.span.start, context,
|
|
179818
|
+
const { sourceFile, errorCode: errorCode2 } = context;
|
|
179819
|
+
const info = getInfo8(sourceFile, context.span.start, context, errorCode2);
|
|
179707
179820
|
if (!info) return void 0;
|
|
179708
179821
|
const { node, suggestedSymbol } = info;
|
|
179709
179822
|
const target = getEmitScriptTarget(context.host.getCompilationSettings());
|
|
@@ -179717,10 +179830,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179717
179830
|
if (info) doChange18(changes, context.sourceFile, info.node, info.suggestedSymbol, target);
|
|
179718
179831
|
})
|
|
179719
179832
|
});
|
|
179720
|
-
function getInfo8(sourceFile, pos, context,
|
|
179833
|
+
function getInfo8(sourceFile, pos, context, errorCode2) {
|
|
179721
179834
|
const node = getTokenAtPosition(sourceFile, pos);
|
|
179722
179835
|
const parent2 = node.parent;
|
|
179723
|
-
if ((
|
|
179836
|
+
if ((errorCode2 === Diagnostics.No_overload_matches_this_call.code || errorCode2 === Diagnostics.Type_0_is_not_assignable_to_type_1.code) && !isJsxAttribute(parent2)) return void 0;
|
|
179724
179837
|
const checker = context.program.getTypeChecker();
|
|
179725
179838
|
let suggestedSymbol;
|
|
179726
179839
|
if (isPropertyAccessExpression(parent2) && parent2.name === node) {
|
|
@@ -179811,8 +179924,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179811
179924
|
errorCodes: errorCodes27,
|
|
179812
179925
|
fixIds: [fixIdAddReturnStatement, fixRemoveBracesFromArrowFunctionBody, fixIdWrapTheBlockWithParen],
|
|
179813
179926
|
getCodeActions: function getCodeActionsToCorrectReturnValue(context) {
|
|
179814
|
-
const { program, sourceFile, span: { start }, errorCode } = context;
|
|
179815
|
-
const info = getInfo9(program.getTypeChecker(), sourceFile, start,
|
|
179927
|
+
const { program, sourceFile, span: { start }, errorCode: errorCode2 } = context;
|
|
179928
|
+
const info = getInfo9(program.getTypeChecker(), sourceFile, start, errorCode2);
|
|
179816
179929
|
if (!info) return void 0;
|
|
179817
179930
|
if (info.kind === 0) {
|
|
179818
179931
|
return append(
|
|
@@ -179947,11 +180060,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
179947
180060
|
}
|
|
179948
180061
|
return checker.isTypeAssignableTo(exprType, type);
|
|
179949
180062
|
}
|
|
179950
|
-
function getInfo9(checker, sourceFile, position,
|
|
180063
|
+
function getInfo9(checker, sourceFile, position, errorCode2) {
|
|
179951
180064
|
const node = getTokenAtPosition(sourceFile, position);
|
|
179952
180065
|
if (!node.parent) return void 0;
|
|
179953
180066
|
const declaration = findAncestor(node.parent, isFunctionLikeDeclaration);
|
|
179954
|
-
switch (
|
|
180067
|
+
switch (errorCode2) {
|
|
179955
180068
|
case Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value.code:
|
|
179956
180069
|
if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) return void 0;
|
|
179957
180070
|
return getFixInfo(
|
|
@@ -180146,11 +180259,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
180146
180259
|
}));
|
|
180147
180260
|
}
|
|
180148
180261
|
});
|
|
180149
|
-
function getInfo10(sourceFile, tokenPos,
|
|
180262
|
+
function getInfo10(sourceFile, tokenPos, errorCode2, checker, program) {
|
|
180150
180263
|
var _a, _b;
|
|
180151
180264
|
const token = getTokenAtPosition(sourceFile, tokenPos);
|
|
180152
180265
|
const parent2 = token.parent;
|
|
180153
|
-
if (
|
|
180266
|
+
if (errorCode2 === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code) {
|
|
180154
180267
|
if (!(token.kind === 19 && isObjectLiteralExpression(parent2) && isCallExpression(parent2.parent))) return void 0;
|
|
180155
180268
|
const argIndex = findIndex(parent2.parent.arguments, (arg) => arg === parent2);
|
|
180156
180269
|
if (argIndex < 0) return void 0;
|
|
@@ -181007,10 +181120,10 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
181007
181120
|
registerCodeFix({
|
|
181008
181121
|
errorCodes: errorCodes31,
|
|
181009
181122
|
getCodeActions: function getCodeActionsToFixNotFoundModule(context) {
|
|
181010
|
-
const { host, sourceFile, span: { start }, errorCode } = context;
|
|
181011
|
-
const packageName =
|
|
181123
|
+
const { host, sourceFile, span: { start }, errorCode: errorCode2 } = context;
|
|
181124
|
+
const packageName = errorCode2 === errorCannotFindImplicitJsxImport ? getJSXImplicitImportBase(context.program.getCompilerOptions(), sourceFile) : tryGetImportedPackageName(sourceFile, start);
|
|
181012
181125
|
if (packageName === void 0) return void 0;
|
|
181013
|
-
const typesPackageName = getTypesPackageNameToInstall(packageName, host,
|
|
181126
|
+
const typesPackageName = getTypesPackageNameToInstall(packageName, host, errorCode2);
|
|
181014
181127
|
return typesPackageName === void 0 ? [] : [createCodeFixAction(
|
|
181015
181128
|
fixName2,
|
|
181016
181129
|
/*changes*/
|
|
@@ -181582,7 +181695,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
181582
181695
|
registerCodeFix({
|
|
181583
181696
|
errorCodes: errorCodes43,
|
|
181584
181697
|
getCodeActions(context) {
|
|
181585
|
-
const { errorCode, sourceFile, program, cancellationToken } = context;
|
|
181698
|
+
const { errorCode: errorCode2, sourceFile, program, cancellationToken } = context;
|
|
181586
181699
|
const checker = program.getTypeChecker();
|
|
181587
181700
|
const sourceFiles = program.getSourceFiles();
|
|
181588
181701
|
const token = getTokenAtPosition(sourceFile, context.span.start);
|
|
@@ -181658,7 +181771,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
181658
181771
|
result.push(createDeleteFix(deletion, [Diagnostics.Remove_unused_declaration_for_Colon_0, name.getText(sourceFile)]));
|
|
181659
181772
|
}
|
|
181660
181773
|
}
|
|
181661
|
-
const prefix = ts_textChanges_exports.ChangeTracker.with(context, (t) => tryPrefixDeclaration(t,
|
|
181774
|
+
const prefix = ts_textChanges_exports.ChangeTracker.with(context, (t) => tryPrefixDeclaration(t, errorCode2, sourceFile, token));
|
|
181662
181775
|
if (prefix.length) {
|
|
181663
181776
|
result.push(createCodeFixAction(fixName3, prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible));
|
|
181664
181777
|
}
|
|
@@ -181784,8 +181897,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
181784
181897
|
changes.delete(sourceFile, parent2);
|
|
181785
181898
|
}
|
|
181786
181899
|
}
|
|
181787
|
-
function tryPrefixDeclaration(changes,
|
|
181788
|
-
if (
|
|
181900
|
+
function tryPrefixDeclaration(changes, errorCode2, sourceFile, token) {
|
|
181901
|
+
if (errorCode2 === Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code) return;
|
|
181789
181902
|
if (token.kind === 140) {
|
|
181790
181903
|
token = cast(token.parent, isInferTypeNode).typeParameter.name;
|
|
181791
181904
|
}
|
|
@@ -181925,14 +182038,14 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
181925
182038
|
fixIds: [fixId34],
|
|
181926
182039
|
getAllCodeActions: (context) => codeFixAll(context, errorCodes44, (changes, diag2) => doChange27(changes, diag2.file, diag2.start, diag2.length, diag2.code))
|
|
181927
182040
|
});
|
|
181928
|
-
function doChange27(changes, sourceFile, start, length2,
|
|
182041
|
+
function doChange27(changes, sourceFile, start, length2, errorCode2) {
|
|
181929
182042
|
const token = getTokenAtPosition(sourceFile, start);
|
|
181930
182043
|
const statement = findAncestor(token, isStatement);
|
|
181931
182044
|
if (statement.getStart(sourceFile) !== token.getStart(sourceFile)) {
|
|
181932
182045
|
const logData = JSON.stringify({
|
|
181933
182046
|
statementKind: Debug.formatSyntaxKind(statement.kind),
|
|
181934
182047
|
tokenKind: Debug.formatSyntaxKind(token.kind),
|
|
181935
|
-
errorCode,
|
|
182048
|
+
errorCode: errorCode2,
|
|
181936
182049
|
start,
|
|
181937
182050
|
length: length2
|
|
181938
182051
|
});
|
|
@@ -183255,7 +183368,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183255
183368
|
registerCodeFix({
|
|
183256
183369
|
errorCodes: errorCodes51,
|
|
183257
183370
|
getCodeActions(context) {
|
|
183258
|
-
const { sourceFile, program, span: { start }, errorCode, cancellationToken, host, preferences } = context;
|
|
183371
|
+
const { sourceFile, program, span: { start }, errorCode: errorCode2, cancellationToken, host, preferences } = context;
|
|
183259
183372
|
const token = getTokenAtPosition(sourceFile, start);
|
|
183260
183373
|
let declaration;
|
|
183261
183374
|
const changes = ts_textChanges_exports.ChangeTracker.with(context, (changes2) => {
|
|
@@ -183263,7 +183376,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183263
183376
|
changes2,
|
|
183264
183377
|
sourceFile,
|
|
183265
183378
|
token,
|
|
183266
|
-
|
|
183379
|
+
errorCode2,
|
|
183267
183380
|
program,
|
|
183268
183381
|
cancellationToken,
|
|
183269
183382
|
/*markSeen*/
|
|
@@ -183273,7 +183386,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183273
183386
|
);
|
|
183274
183387
|
});
|
|
183275
183388
|
const name = declaration && getNameOfDeclaration(declaration);
|
|
183276
|
-
return !name || changes.length === 0 ? void 0 : [createCodeFixAction(fixId40, changes, [getDiagnostic(
|
|
183389
|
+
return !name || changes.length === 0 ? void 0 : [createCodeFixAction(fixId40, changes, [getDiagnostic(errorCode2, token), getTextOfNode(name)], fixId40, Diagnostics.Infer_all_types_from_usage)];
|
|
183277
183390
|
},
|
|
183278
183391
|
fixIds: [fixId40],
|
|
183279
183392
|
getAllCodeActions(context) {
|
|
@@ -183284,8 +183397,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183284
183397
|
});
|
|
183285
183398
|
}
|
|
183286
183399
|
});
|
|
183287
|
-
function getDiagnostic(
|
|
183288
|
-
switch (
|
|
183400
|
+
function getDiagnostic(errorCode2, token) {
|
|
183401
|
+
switch (errorCode2) {
|
|
183289
183402
|
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
|
|
183290
183403
|
case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
|
183291
183404
|
return isSetAccessorDeclaration(getContainingFunction(token)) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage;
|
|
@@ -183299,8 +183412,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183299
183412
|
return Diagnostics.Infer_type_of_0_from_usage;
|
|
183300
183413
|
}
|
|
183301
183414
|
}
|
|
183302
|
-
function mapSuggestionDiagnostic(
|
|
183303
|
-
switch (
|
|
183415
|
+
function mapSuggestionDiagnostic(errorCode2) {
|
|
183416
|
+
switch (errorCode2) {
|
|
183304
183417
|
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code:
|
|
183305
183418
|
return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code;
|
|
183306
183419
|
case Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
|
@@ -183318,16 +183431,16 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183318
183431
|
case Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
|
183319
183432
|
return Diagnostics.Member_0_implicitly_has_an_1_type.code;
|
|
183320
183433
|
}
|
|
183321
|
-
return
|
|
183434
|
+
return errorCode2;
|
|
183322
183435
|
}
|
|
183323
|
-
function doChange33(changes, sourceFile, token,
|
|
183436
|
+
function doChange33(changes, sourceFile, token, errorCode2, program, cancellationToken, markSeen, host, preferences) {
|
|
183324
183437
|
if (!isParameterPropertyModifier(token.kind) && token.kind !== 80 && token.kind !== 26 && token.kind !== 110) {
|
|
183325
183438
|
return void 0;
|
|
183326
183439
|
}
|
|
183327
183440
|
const { parent: parent2 } = token;
|
|
183328
183441
|
const importAdder = createImportAdder(sourceFile, program, preferences, host);
|
|
183329
|
-
|
|
183330
|
-
switch (
|
|
183442
|
+
errorCode2 = mapSuggestionDiagnostic(errorCode2);
|
|
183443
|
+
switch (errorCode2) {
|
|
183331
183444
|
// Variable and Property declarations
|
|
183332
183445
|
case Diagnostics.Member_0_implicitly_has_an_1_type.code:
|
|
183333
183446
|
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
|
|
@@ -183368,7 +183481,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183368
183481
|
return void 0;
|
|
183369
183482
|
}
|
|
183370
183483
|
let declaration;
|
|
183371
|
-
switch (
|
|
183484
|
+
switch (errorCode2) {
|
|
183372
183485
|
// Parameter declarations
|
|
183373
183486
|
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
|
|
183374
183487
|
if (isSetAccessorDeclaration(containingFunction)) {
|
|
@@ -183407,7 +183520,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
183407
183520
|
}
|
|
183408
183521
|
break;
|
|
183409
183522
|
default:
|
|
183410
|
-
return Debug.fail(String(
|
|
183523
|
+
return Debug.fail(String(errorCode2));
|
|
183411
183524
|
}
|
|
183412
183525
|
importAdder.writeFixes(changes);
|
|
183413
183526
|
return declaration;
|
|
@@ -219319,8 +219432,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
219319
219432
|
installPackage(options) {
|
|
219320
219433
|
this.packageInstallId++;
|
|
219321
219434
|
const request3 = { kind: "installPackage", ...options, id: this.packageInstallId };
|
|
219322
|
-
const promise = new Promise((
|
|
219323
|
-
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve:
|
|
219435
|
+
const promise = new Promise((resolve11, reject) => {
|
|
219436
|
+
(this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve11, reject });
|
|
219324
219437
|
});
|
|
219325
219438
|
this.installer.send(request3);
|
|
219326
219439
|
return promise;
|
|
@@ -221621,7 +221734,7 @@ var require_path_browserify = __commonJS({
|
|
|
221621
221734
|
}
|
|
221622
221735
|
var posix = {
|
|
221623
221736
|
// path.resolve([from ...], to)
|
|
221624
|
-
resolve: function
|
|
221737
|
+
resolve: function resolve11() {
|
|
221625
221738
|
var resolvedPath = "";
|
|
221626
221739
|
var resolvedAbsolute = false;
|
|
221627
221740
|
var cwd;
|
|
@@ -221668,7 +221781,7 @@ var require_path_browserify = __commonJS({
|
|
|
221668
221781
|
assertPath(path);
|
|
221669
221782
|
return path.length > 0 && path.charCodeAt(0) === 47;
|
|
221670
221783
|
},
|
|
221671
|
-
join: function
|
|
221784
|
+
join: function join9() {
|
|
221672
221785
|
if (arguments.length === 0)
|
|
221673
221786
|
return ".";
|
|
221674
221787
|
var joined;
|
|
@@ -226521,41 +226634,41 @@ var require_queue = __commonJS({
|
|
|
226521
226634
|
queue.drained = drained;
|
|
226522
226635
|
return queue;
|
|
226523
226636
|
function push2(value) {
|
|
226524
|
-
var p2 = new Promise(function(
|
|
226637
|
+
var p2 = new Promise(function(resolve11, reject) {
|
|
226525
226638
|
pushCb(value, function(err, result) {
|
|
226526
226639
|
if (err) {
|
|
226527
226640
|
reject(err);
|
|
226528
226641
|
return;
|
|
226529
226642
|
}
|
|
226530
|
-
|
|
226643
|
+
resolve11(result);
|
|
226531
226644
|
});
|
|
226532
226645
|
});
|
|
226533
226646
|
p2.catch(noop3);
|
|
226534
226647
|
return p2;
|
|
226535
226648
|
}
|
|
226536
226649
|
function unshift(value) {
|
|
226537
|
-
var p2 = new Promise(function(
|
|
226650
|
+
var p2 = new Promise(function(resolve11, reject) {
|
|
226538
226651
|
unshiftCb(value, function(err, result) {
|
|
226539
226652
|
if (err) {
|
|
226540
226653
|
reject(err);
|
|
226541
226654
|
return;
|
|
226542
226655
|
}
|
|
226543
|
-
|
|
226656
|
+
resolve11(result);
|
|
226544
226657
|
});
|
|
226545
226658
|
});
|
|
226546
226659
|
p2.catch(noop3);
|
|
226547
226660
|
return p2;
|
|
226548
226661
|
}
|
|
226549
226662
|
function drained() {
|
|
226550
|
-
var p2 = new Promise(function(
|
|
226663
|
+
var p2 = new Promise(function(resolve11) {
|
|
226551
226664
|
process.nextTick(function() {
|
|
226552
226665
|
if (queue.idle()) {
|
|
226553
|
-
|
|
226666
|
+
resolve11();
|
|
226554
226667
|
} else {
|
|
226555
226668
|
var previousDrain = queue.drain;
|
|
226556
226669
|
queue.drain = function() {
|
|
226557
226670
|
if (typeof previousDrain === "function") previousDrain();
|
|
226558
|
-
|
|
226671
|
+
resolve11();
|
|
226559
226672
|
queue.drain = previousDrain;
|
|
226560
226673
|
};
|
|
226561
226674
|
}
|
|
@@ -227052,9 +227165,9 @@ var require_stream3 = __commonJS({
|
|
|
227052
227165
|
});
|
|
227053
227166
|
}
|
|
227054
227167
|
_getStat(filepath) {
|
|
227055
|
-
return new Promise((
|
|
227168
|
+
return new Promise((resolve11, reject) => {
|
|
227056
227169
|
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
|
227057
|
-
return error === null ?
|
|
227170
|
+
return error === null ? resolve11(stats) : reject(error);
|
|
227058
227171
|
});
|
|
227059
227172
|
});
|
|
227060
227173
|
}
|
|
@@ -227079,10 +227192,10 @@ var require_async5 = __commonJS({
|
|
|
227079
227192
|
this._readerStream = new stream_1.default(this._settings);
|
|
227080
227193
|
}
|
|
227081
227194
|
dynamic(root, options) {
|
|
227082
|
-
return new Promise((
|
|
227195
|
+
return new Promise((resolve11, reject) => {
|
|
227083
227196
|
this._walkAsync(root, options, (error, entries) => {
|
|
227084
227197
|
if (error === null) {
|
|
227085
|
-
|
|
227198
|
+
resolve11(entries);
|
|
227086
227199
|
} else {
|
|
227087
227200
|
reject(error);
|
|
227088
227201
|
}
|
|
@@ -227092,10 +227205,10 @@ var require_async5 = __commonJS({
|
|
|
227092
227205
|
async static(patterns, options) {
|
|
227093
227206
|
const entries = [];
|
|
227094
227207
|
const stream = this._readerStream.static(patterns, options);
|
|
227095
|
-
return new Promise((
|
|
227208
|
+
return new Promise((resolve11, reject) => {
|
|
227096
227209
|
stream.once("error", reject);
|
|
227097
227210
|
stream.on("data", (entry) => entries.push(entry));
|
|
227098
|
-
stream.once("end", () =>
|
|
227211
|
+
stream.once("end", () => resolve11(entries));
|
|
227099
227212
|
});
|
|
227100
227213
|
}
|
|
227101
227214
|
};
|
|
@@ -260001,12 +260114,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260001
260114
|
};
|
|
260002
260115
|
var NodeRuntimeFileSystem = class {
|
|
260003
260116
|
delete(path2) {
|
|
260004
|
-
return new Promise((
|
|
260117
|
+
return new Promise((resolve11, reject) => {
|
|
260005
260118
|
fs__namespace.rm(path2, { recursive: true }, (err) => {
|
|
260006
260119
|
if (err)
|
|
260007
260120
|
reject(err);
|
|
260008
260121
|
else
|
|
260009
|
-
|
|
260122
|
+
resolve11();
|
|
260010
260123
|
});
|
|
260011
260124
|
});
|
|
260012
260125
|
}
|
|
@@ -260025,12 +260138,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260025
260138
|
}));
|
|
260026
260139
|
}
|
|
260027
260140
|
readFile(filePath, encoding = "utf-8") {
|
|
260028
|
-
return new Promise((
|
|
260141
|
+
return new Promise((resolve11, reject) => {
|
|
260029
260142
|
fs__namespace.readFile(filePath, encoding, (err, data) => {
|
|
260030
260143
|
if (err)
|
|
260031
260144
|
reject(err);
|
|
260032
260145
|
else
|
|
260033
|
-
|
|
260146
|
+
resolve11(data);
|
|
260034
260147
|
});
|
|
260035
260148
|
});
|
|
260036
260149
|
}
|
|
@@ -260038,12 +260151,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260038
260151
|
return fs__namespace.readFileSync(filePath, encoding);
|
|
260039
260152
|
}
|
|
260040
260153
|
async writeFile(filePath, fileText) {
|
|
260041
|
-
await new Promise((
|
|
260154
|
+
await new Promise((resolve11, reject) => {
|
|
260042
260155
|
fs__namespace.writeFile(filePath, fileText, (err) => {
|
|
260043
260156
|
if (err)
|
|
260044
260157
|
reject(err);
|
|
260045
260158
|
else
|
|
260046
|
-
|
|
260159
|
+
resolve11();
|
|
260047
260160
|
});
|
|
260048
260161
|
});
|
|
260049
260162
|
}
|
|
@@ -260057,12 +260170,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260057
260170
|
fs__namespace.mkdirSync(dirPath, { recursive: true });
|
|
260058
260171
|
}
|
|
260059
260172
|
move(srcPath, destPath) {
|
|
260060
|
-
return new Promise((
|
|
260173
|
+
return new Promise((resolve11, reject) => {
|
|
260061
260174
|
fs__namespace.rename(srcPath, destPath, (err) => {
|
|
260062
260175
|
if (err)
|
|
260063
260176
|
reject(err);
|
|
260064
260177
|
else
|
|
260065
|
-
|
|
260178
|
+
resolve11();
|
|
260066
260179
|
});
|
|
260067
260180
|
});
|
|
260068
260181
|
}
|
|
@@ -260070,12 +260183,12 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260070
260183
|
fs__namespace.renameSync(srcPath, destPath);
|
|
260071
260184
|
}
|
|
260072
260185
|
copy(srcPath, destPath) {
|
|
260073
|
-
return new Promise((
|
|
260186
|
+
return new Promise((resolve11, reject) => {
|
|
260074
260187
|
fs__namespace.copyFile(srcPath, destPath, (err) => {
|
|
260075
260188
|
if (err)
|
|
260076
260189
|
reject(err);
|
|
260077
260190
|
else
|
|
260078
|
-
|
|
260191
|
+
resolve11();
|
|
260079
260192
|
});
|
|
260080
260193
|
});
|
|
260081
260194
|
}
|
|
@@ -260083,15 +260196,15 @@ type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "js
|
|
|
260083
260196
|
fs__namespace.copyFileSync(srcPath, destPath);
|
|
260084
260197
|
}
|
|
260085
260198
|
stat(path2) {
|
|
260086
|
-
return new Promise((
|
|
260199
|
+
return new Promise((resolve11, reject) => {
|
|
260087
260200
|
fs__namespace.stat(path2, (err, stat) => {
|
|
260088
260201
|
if (err) {
|
|
260089
260202
|
if (err.code === "ENOENT" || err.code === "ENOTDIR")
|
|
260090
|
-
|
|
260203
|
+
resolve11(void 0);
|
|
260091
260204
|
else
|
|
260092
260205
|
reject(err);
|
|
260093
260206
|
} else {
|
|
260094
|
-
|
|
260207
|
+
resolve11(stat);
|
|
260095
260208
|
}
|
|
260096
260209
|
});
|
|
260097
260210
|
});
|
|
@@ -283768,7 +283881,7 @@ Node text: ${this.#forgottenText}`;
|
|
|
283768
283881
|
|
|
283769
283882
|
// src/index.ts
|
|
283770
283883
|
init_cjs_shims();
|
|
283771
|
-
var
|
|
283884
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
283772
283885
|
|
|
283773
283886
|
// src/migrate.ts
|
|
283774
283887
|
init_cjs_shims();
|
|
@@ -283778,7 +283891,7 @@ var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
|
283778
283891
|
var import_fs5 = require("fs");
|
|
283779
283892
|
init_src();
|
|
283780
283893
|
init_dbRole();
|
|
283781
|
-
var
|
|
283894
|
+
var import_schema2 = require("@abloatai/transaction/schema");
|
|
283782
283895
|
var import_source = require("@abloatai/transaction/source");
|
|
283783
283896
|
init_push();
|
|
283784
283897
|
var MIGRATE_USAGE = ` ablo migrate \u2014 create the tables your schema needs in your own database (DATABASE_URL)
|
|
@@ -283825,8 +283938,8 @@ function parseMigrateArgs(argv) {
|
|
|
283825
283938
|
return { schemaPath, exportName, targetSchema, dryRun, outputFile };
|
|
283826
283939
|
}
|
|
283827
283940
|
function planFor(schema, targetSchema = "public") {
|
|
283828
|
-
const schemaJson = JSON.parse((0,
|
|
283829
|
-
const plan = (0,
|
|
283941
|
+
const schemaJson = JSON.parse((0, import_schema2.serializeSchema)(schema));
|
|
283942
|
+
const plan = (0, import_schema2.generateProvisionPlan)(schemaJson, targetSchema, {
|
|
283830
283943
|
foreignKeys: targetSchema === "public"
|
|
283831
283944
|
});
|
|
283832
283945
|
const adapterTables = (0, import_source.adapterTableMigrations)().map((m2) => m2.up);
|
|
@@ -283848,8 +283961,8 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
|
|
|
283848
283961
|
} });
|
|
283849
283962
|
const total = statements.length;
|
|
283850
283963
|
const startedAt = Date.now();
|
|
283851
|
-
const lockTimeout = (0,
|
|
283852
|
-
const maxLockAttempts = (0,
|
|
283964
|
+
const lockTimeout = (0, import_schema2.resolveDdlLockTimeout)();
|
|
283965
|
+
const maxLockAttempts = (0, import_schema2.resolveDdlMaxLockAttempts)();
|
|
283853
283966
|
if (!observer.quiet) log.info("applying migration plan", { targetSchema, statements: total });
|
|
283854
283967
|
try {
|
|
283855
283968
|
for (let attempt = 1; ; attempt++) {
|
|
@@ -283863,7 +283976,7 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
|
|
|
283863
283976
|
observer.onStatement?.(index + 1, total);
|
|
283864
283977
|
} catch (err) {
|
|
283865
283978
|
const pg = err ?? {};
|
|
283866
|
-
if (pg.code ===
|
|
283979
|
+
if (pg.code === import_schema2.PG_LOCK_NOT_AVAILABLE) throw err;
|
|
283867
283980
|
log.error("migration plan failed", {
|
|
283868
283981
|
code: "migration_failed",
|
|
283869
283982
|
durationMs: Date.now() - startedAt,
|
|
@@ -283881,10 +283994,10 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [],
|
|
|
283881
283994
|
break;
|
|
283882
283995
|
} catch (err) {
|
|
283883
283996
|
const pg = err ?? {};
|
|
283884
|
-
if (pg.code ===
|
|
283885
|
-
const backoffMs = (0,
|
|
283997
|
+
if (pg.code === import_schema2.PG_LOCK_NOT_AVAILABLE && attempt < maxLockAttempts) {
|
|
283998
|
+
const backoffMs = (0, import_schema2.ddlLockRetryBackoffMs)(attempt);
|
|
283886
283999
|
log.warn("schema change blocked by a lock; backing off and retrying", { targetSchema, attempt, backoffMs });
|
|
283887
|
-
await new Promise((
|
|
284000
|
+
await new Promise((resolve11) => setTimeout(resolve11, backoffMs));
|
|
283888
284001
|
continue;
|
|
283889
284002
|
}
|
|
283890
284003
|
throw err;
|
|
@@ -284226,11 +284339,11 @@ function parseFeedbackArgs(argv) {
|
|
|
284226
284339
|
const positional2 = [];
|
|
284227
284340
|
let detail;
|
|
284228
284341
|
let command;
|
|
284229
|
-
let
|
|
284342
|
+
let errorCode2;
|
|
284230
284343
|
let from;
|
|
284231
284344
|
let yes = false;
|
|
284232
284345
|
let json = false;
|
|
284233
|
-
const
|
|
284346
|
+
const flagValue2 = (flag2, value) => {
|
|
284234
284347
|
if (value === void 0 || value.startsWith("--")) {
|
|
284235
284348
|
throw new import_errors12.AbloValidationError(`\`${flag2}\` needs a value.`, {
|
|
284236
284349
|
code: "cli_invalid_arguments"
|
|
@@ -284242,16 +284355,16 @@ function parseFeedbackArgs(argv) {
|
|
|
284242
284355
|
const arg = argv[i];
|
|
284243
284356
|
switch (arg) {
|
|
284244
284357
|
case "--detail":
|
|
284245
|
-
detail =
|
|
284358
|
+
detail = flagValue2("--detail", argv[++i]);
|
|
284246
284359
|
break;
|
|
284247
284360
|
case "--command":
|
|
284248
|
-
command =
|
|
284361
|
+
command = flagValue2("--command", argv[++i]);
|
|
284249
284362
|
break;
|
|
284250
284363
|
case "--error-code":
|
|
284251
|
-
|
|
284364
|
+
errorCode2 = flagValue2("--error-code", argv[++i]);
|
|
284252
284365
|
break;
|
|
284253
284366
|
case "--from":
|
|
284254
|
-
from =
|
|
284367
|
+
from = flagValue2("--from", argv[++i]);
|
|
284255
284368
|
break;
|
|
284256
284369
|
case "--yes":
|
|
284257
284370
|
yes = true;
|
|
@@ -284286,7 +284399,7 @@ function parseFeedbackArgs(argv) {
|
|
|
284286
284399
|
summary,
|
|
284287
284400
|
...detail !== void 0 ? { detail } : {},
|
|
284288
284401
|
...command !== void 0 ? { command } : {},
|
|
284289
|
-
...
|
|
284402
|
+
...errorCode2 !== void 0 ? { errorCode: errorCode2 } : {},
|
|
284290
284403
|
...from !== void 0 ? { from } : {},
|
|
284291
284404
|
yes,
|
|
284292
284405
|
json
|
|
@@ -284407,8 +284520,8 @@ init_controlPlane();
|
|
|
284407
284520
|
init_config();
|
|
284408
284521
|
var BRANCH_USAGE = `Usage:
|
|
284409
284522
|
ablo branch list [--json]
|
|
284410
|
-
ablo branch create <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--credential]
|
|
284411
|
-
ablo branch ensure <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--credential]
|
|
284523
|
+
ablo branch create <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--hosted] [--credential]
|
|
284524
|
+
ablo branch ensure <slug> [--from <id|slug>] [--kind dev|preview|test|long_lived] [--hosted] [--credential]
|
|
284412
284525
|
ablo branch credential <id|slug> [--ttl-hours <1-168>] [--json]
|
|
284413
284526
|
ablo branch status <branch-id|slug> [--json]
|
|
284414
284527
|
ablo branch check <branch-id|slug> [--json]
|
|
@@ -284421,7 +284534,7 @@ function requireKey2(explicit) {
|
|
|
284421
284534
|
const key = explicit ?? resolveManagementKey();
|
|
284422
284535
|
if (!key) {
|
|
284423
284536
|
throw new Error(
|
|
284424
|
-
"No project management credential. Run `npx ablo login` or set
|
|
284537
|
+
"No project management credential. Run `npx ablo login` or set ABLO_API_KEY to an mk_ credential."
|
|
284425
284538
|
);
|
|
284426
284539
|
}
|
|
284427
284540
|
return key;
|
|
@@ -284561,7 +284674,8 @@ async function create(slug, argv, idempotent, context = {}) {
|
|
|
284561
284674
|
slug: parsedSlug.data,
|
|
284562
284675
|
...parentId ? { parent_branch_id: parentId } : {},
|
|
284563
284676
|
...valueAfter(argv, "--kind") ? { kind: valueAfter(argv, "--kind") } : {},
|
|
284564
|
-
...valueAfter(argv, "--expires-at") ? { expires_at: valueAfter(argv, "--expires-at") } : {}
|
|
284677
|
+
...valueAfter(argv, "--expires-at") ? { expires_at: valueAfter(argv, "--expires-at") } : {},
|
|
284678
|
+
...argv.includes("--hosted") ? { storage: "hosted" } : {}
|
|
284565
284679
|
}
|
|
284566
284680
|
}, context);
|
|
284567
284681
|
if (response.status !== 201) {
|
|
@@ -284659,29 +284773,118 @@ async function branches(argv) {
|
|
|
284659
284773
|
|
|
284660
284774
|
// src/branchDev.ts
|
|
284661
284775
|
init_cjs_shims();
|
|
284662
|
-
var
|
|
284776
|
+
var import_node_crypto6 = require("crypto");
|
|
284663
284777
|
var import_node_child_process = require("child_process");
|
|
284664
284778
|
var import_branches2 = require("@abloatai/transaction/branches");
|
|
284665
|
-
var
|
|
284779
|
+
var import_errors15 = require("@abloatai/transaction/errors");
|
|
284666
284780
|
init_config();
|
|
284667
284781
|
init_telemetry();
|
|
284668
284782
|
|
|
284669
284783
|
// src/dev.ts
|
|
284670
284784
|
init_cjs_shims();
|
|
284671
|
-
var
|
|
284785
|
+
var import_errors14 = require("@abloatai/transaction/errors");
|
|
284672
284786
|
var import_credentialPolicy2 = require("@abloatai/transaction/auth/credentialPolicy");
|
|
284673
284787
|
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
284674
284788
|
init_dist2();
|
|
284675
284789
|
var import_fs7 = require("fs");
|
|
284676
284790
|
var import_path5 = require("path");
|
|
284677
|
-
var
|
|
284791
|
+
var import_schema5 = require("@abloatai/transaction/schema");
|
|
284678
284792
|
init_push();
|
|
284679
284793
|
init_controlPlane();
|
|
284794
|
+
var import_wire8 = require("@abloatai/transaction/wire");
|
|
284680
284795
|
init_config();
|
|
284681
284796
|
init_readiness();
|
|
284682
284797
|
init_theme();
|
|
284683
284798
|
init_dbRole();
|
|
284684
284799
|
var import_source3 = require("@abloatai/transaction/source");
|
|
284800
|
+
|
|
284801
|
+
// src/localConnectorLease.ts
|
|
284802
|
+
init_cjs_shims();
|
|
284803
|
+
var import_node_crypto5 = require("crypto");
|
|
284804
|
+
var import_node_fs3 = require("fs");
|
|
284805
|
+
var import_node_os2 = require("os");
|
|
284806
|
+
var import_node_path2 = require("path");
|
|
284807
|
+
var import_errors13 = require("@abloatai/transaction/errors");
|
|
284808
|
+
function acquireLocalConnectorLease(identity, options = {}) {
|
|
284809
|
+
const directory = options.directory ?? (0, import_node_path2.join)((0, import_node_os2.tmpdir)(), "ablo-source-connectors");
|
|
284810
|
+
const pid = options.pid ?? process.pid;
|
|
284811
|
+
const isProcessAlive = options.isProcessAlive ?? processIsAlive;
|
|
284812
|
+
const key = (0, import_node_crypto5.createHash)("sha256").update(`${(0, import_node_path2.resolve)(identity.cwd)}\0${identity.baseUrl}\0${identity.branch}`).digest("hex").slice(0, 24);
|
|
284813
|
+
const path = (0, import_node_path2.join)(directory, `${key}.lock`);
|
|
284814
|
+
const token = (0, import_node_crypto5.randomUUID)();
|
|
284815
|
+
const record = { pid, token };
|
|
284816
|
+
(0, import_node_fs3.mkdirSync)(directory, { recursive: true, mode: 448 });
|
|
284817
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
284818
|
+
try {
|
|
284819
|
+
const fd = (0, import_node_fs3.openSync)(path, "wx", 384);
|
|
284820
|
+
try {
|
|
284821
|
+
(0, import_node_fs3.writeFileSync)(fd, JSON.stringify(record));
|
|
284822
|
+
} finally {
|
|
284823
|
+
(0, import_node_fs3.closeSync)(fd);
|
|
284824
|
+
}
|
|
284825
|
+
let released = false;
|
|
284826
|
+
return {
|
|
284827
|
+
release() {
|
|
284828
|
+
if (released) return;
|
|
284829
|
+
released = true;
|
|
284830
|
+
try {
|
|
284831
|
+
const current = readLease(path);
|
|
284832
|
+
if (current?.token === token) (0, import_node_fs3.unlinkSync)(path);
|
|
284833
|
+
} catch {
|
|
284834
|
+
}
|
|
284835
|
+
}
|
|
284836
|
+
};
|
|
284837
|
+
} catch (error) {
|
|
284838
|
+
if (!isAlreadyExists(error)) throw error;
|
|
284839
|
+
const owner = readLease(path);
|
|
284840
|
+
if (owner && isProcessAlive(owner.pid)) {
|
|
284841
|
+
throw new import_errors13.AbloValidationError(
|
|
284842
|
+
`Another ablo dev --local process (PID ${owner.pid}) already owns this branch's local Data Source. Stop it before starting another connector.`,
|
|
284843
|
+
{ code: "cli_invalid_arguments" }
|
|
284844
|
+
);
|
|
284845
|
+
}
|
|
284846
|
+
try {
|
|
284847
|
+
(0, import_node_fs3.unlinkSync)(path);
|
|
284848
|
+
} catch (unlinkError) {
|
|
284849
|
+
if (!isMissing(unlinkError)) throw unlinkError;
|
|
284850
|
+
}
|
|
284851
|
+
}
|
|
284852
|
+
}
|
|
284853
|
+
throw new import_errors13.AbloValidationError(
|
|
284854
|
+
"Could not acquire this branch's local Data Source connector lease. Retry after the other connector exits.",
|
|
284855
|
+
{ code: "cli_invalid_arguments" }
|
|
284856
|
+
);
|
|
284857
|
+
}
|
|
284858
|
+
function readLease(path) {
|
|
284859
|
+
try {
|
|
284860
|
+
const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
|
|
284861
|
+
return typeof parsed.pid === "number" && typeof parsed.token === "string" ? { pid: parsed.pid, token: parsed.token } : void 0;
|
|
284862
|
+
} catch {
|
|
284863
|
+
return void 0;
|
|
284864
|
+
}
|
|
284865
|
+
}
|
|
284866
|
+
function processIsAlive(pid) {
|
|
284867
|
+
try {
|
|
284868
|
+
process.kill(pid, 0);
|
|
284869
|
+
return true;
|
|
284870
|
+
} catch (error) {
|
|
284871
|
+
return !isNoSuchProcess(error);
|
|
284872
|
+
}
|
|
284873
|
+
}
|
|
284874
|
+
function errorCode(error) {
|
|
284875
|
+
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
284876
|
+
}
|
|
284877
|
+
function isAlreadyExists(error) {
|
|
284878
|
+
return errorCode(error) === "EEXIST";
|
|
284879
|
+
}
|
|
284880
|
+
function isMissing(error) {
|
|
284881
|
+
return errorCode(error) === "ENOENT";
|
|
284882
|
+
}
|
|
284883
|
+
function isNoSuchProcess(error) {
|
|
284884
|
+
return errorCode(error) === "ESRCH";
|
|
284885
|
+
}
|
|
284886
|
+
|
|
284887
|
+
// src/dev.ts
|
|
284685
284888
|
function parseDevArgs(argv) {
|
|
284686
284889
|
let schemaPath = DEFAULT_SCHEMA_PATH;
|
|
284687
284890
|
let exportName = DEFAULT_EXPORT;
|
|
@@ -284714,7 +284917,7 @@ function parseDevArgs(argv) {
|
|
|
284714
284917
|
sourcePath = argv[++i] ?? sourcePath;
|
|
284715
284918
|
break;
|
|
284716
284919
|
default:
|
|
284717
|
-
throw new
|
|
284920
|
+
throw new import_errors14.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
284718
284921
|
}
|
|
284719
284922
|
}
|
|
284720
284923
|
url = apiBaseUrl(url);
|
|
@@ -284732,7 +284935,7 @@ function parseDevArgs(argv) {
|
|
|
284732
284935
|
async function loadLocalSourceHandler(sourcePath) {
|
|
284733
284936
|
const abs = (0, import_path5.resolve)(process.cwd(), sourcePath);
|
|
284734
284937
|
if (!(0, import_fs7.existsSync)(abs)) {
|
|
284735
|
-
throw new
|
|
284938
|
+
throw new import_errors14.AbloValidationError(
|
|
284736
284939
|
`local Data Source not found at ${import_picocolors16.default.bold(sourcePath)}. Add the signed Data Source handler described by ${import_picocolors16.default.bold("npx ablo docs data-sources")}, or pass ${import_picocolors16.default.bold("--source <path>")}.`,
|
|
284737
284940
|
{ code: "cli_invalid_arguments" }
|
|
284738
284941
|
);
|
|
@@ -284743,7 +284946,7 @@ async function loadLocalSourceHandler(sourcePath) {
|
|
|
284743
284946
|
const nested = mod.default && typeof mod.default === "object" ? mod.default : void 0;
|
|
284744
284947
|
const handler = mod.POST ?? nested?.POST;
|
|
284745
284948
|
if (typeof handler !== "function") {
|
|
284746
|
-
throw new
|
|
284949
|
+
throw new import_errors14.AbloValidationError(
|
|
284747
284950
|
`${import_picocolors16.default.bold(sourcePath)} must export a ${import_picocolors16.default.bold("POST(request)")} Data Source handler.`,
|
|
284748
284951
|
{ code: "cli_invalid_arguments" }
|
|
284749
284952
|
);
|
|
@@ -284751,27 +284954,20 @@ async function loadLocalSourceHandler(sourcePath) {
|
|
|
284751
284954
|
return handler;
|
|
284752
284955
|
}
|
|
284753
284956
|
async function registerLocalSource(args) {
|
|
284754
|
-
|
|
284957
|
+
await requestControlPlane({
|
|
284958
|
+
path: "/v1/datasources",
|
|
284755
284959
|
method: "POST",
|
|
284756
|
-
|
|
284757
|
-
|
|
284758
|
-
|
|
284759
|
-
},
|
|
284760
|
-
body: JSON.stringify({
|
|
284960
|
+
...args.apiKey ? { apiKey: args.apiKey } : {},
|
|
284961
|
+
baseUrl: args.url,
|
|
284962
|
+
body: {
|
|
284761
284963
|
connection: "endpoint",
|
|
284762
284964
|
endpoint: "http://localhost/ablo-dev/reverse-channel",
|
|
284763
284965
|
signingKey: args.apiKey,
|
|
284764
284966
|
reverseChannel: true,
|
|
284765
284967
|
metadata: { managed_by: "ablo dev --local" }
|
|
284766
|
-
}
|
|
284968
|
+
},
|
|
284969
|
+
responseSchema: import_wire8.datasourceSummarySchema
|
|
284767
284970
|
});
|
|
284768
|
-
if (!response.ok) {
|
|
284769
|
-
const body = await response.text();
|
|
284770
|
-
throw new import_errors13.AbloValidationError(
|
|
284771
|
-
`Could not register the local Data Source (${response.status}): ${body}`,
|
|
284772
|
-
{ code: "cli_invalid_arguments" }
|
|
284773
|
-
);
|
|
284774
|
-
}
|
|
284775
284971
|
}
|
|
284776
284972
|
function classifyKey(apiKey) {
|
|
284777
284973
|
if (!apiKey) {
|
|
@@ -284928,7 +285124,7 @@ async function dev(argv, runtime = {}) {
|
|
|
284928
285124
|
else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
|
|
284929
285125
|
if (runtime.branch) args.planeLabel = runtime.branch.slug;
|
|
284930
285126
|
if (args.local && !args.watch) {
|
|
284931
|
-
throw new
|
|
285127
|
+
throw new import_errors14.AbloValidationError(
|
|
284932
285128
|
`${import_picocolors16.default.bold("--local")} opens a long-lived secure connector and cannot be combined with ${import_picocolors16.default.bold("--no-watch")}.`,
|
|
284933
285129
|
{ code: "cli_invalid_arguments" }
|
|
284934
285130
|
);
|
|
@@ -284950,6 +285146,7 @@ async function dev(argv, runtime = {}) {
|
|
|
284950
285146
|
);
|
|
284951
285147
|
}
|
|
284952
285148
|
let localAbort = null;
|
|
285149
|
+
let localLease = null;
|
|
284953
285150
|
if (args.local) {
|
|
284954
285151
|
process.env.ABLO_API_KEY = args.apiKey;
|
|
284955
285152
|
if (!process.env.DATABASE_URL) {
|
|
@@ -284957,7 +285154,18 @@ async function dev(argv, runtime = {}) {
|
|
|
284957
285154
|
if (databaseUrl) process.env.DATABASE_URL = databaseUrl.value;
|
|
284958
285155
|
}
|
|
284959
285156
|
const handler = await loadLocalSourceHandler(args.sourcePath);
|
|
284960
|
-
|
|
285157
|
+
localLease = acquireLocalConnectorLease({
|
|
285158
|
+
cwd: process.cwd(),
|
|
285159
|
+
baseUrl: args.url,
|
|
285160
|
+
branch: args.planeLabel
|
|
285161
|
+
});
|
|
285162
|
+
try {
|
|
285163
|
+
await registerLocalSource(args);
|
|
285164
|
+
} catch (error) {
|
|
285165
|
+
localLease.release();
|
|
285166
|
+
localLease = null;
|
|
285167
|
+
throw error;
|
|
285168
|
+
}
|
|
284961
285169
|
localAbort = new AbortController();
|
|
284962
285170
|
const connector = (0, import_source3.createSourceConnector)({
|
|
284963
285171
|
apiKey: args.apiKey,
|
|
@@ -284975,13 +285183,16 @@ async function dev(argv, runtime = {}) {
|
|
|
284975
285183
|
});
|
|
284976
285184
|
void connector.run(localAbort.signal).catch((error) => {
|
|
284977
285185
|
console.error(import_picocolors16.default.red(` local connector stopped: ${error instanceof Error ? error.message : String(error)}`));
|
|
285186
|
+
}).finally(() => {
|
|
285187
|
+
localLease?.release();
|
|
285188
|
+
localLease = null;
|
|
284978
285189
|
});
|
|
284979
285190
|
console.log(` ${import_picocolors16.default.dim("source")} ${args.sourcePath} ${import_picocolors16.default.dim("(outbound connector; no public URL)")}`);
|
|
284980
285191
|
}
|
|
284981
285192
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
284982
285193
|
const modelCount = Object.keys(schema.models).length;
|
|
284983
285194
|
console.log(
|
|
284984
|
-
` ${import_picocolors16.default.dim("schema")} ${import_picocolors16.default.bold(args.schemaPath)} ${import_picocolors16.default.dim(`(${modelCount} models, hash ${(0,
|
|
285195
|
+
` ${import_picocolors16.default.dim("schema")} ${import_picocolors16.default.bold(args.schemaPath)} ${import_picocolors16.default.dim(`(${modelCount} models, hash ${(0, import_schema5.schemaHash)(schema)})`)}`
|
|
284985
285196
|
);
|
|
284986
285197
|
if (!runtime.branch) {
|
|
284987
285198
|
console.log(` ${import_picocolors16.default.dim("key")} ${args.apiKey.slice(0, 12)}\u2026`);
|
|
@@ -284994,6 +285205,7 @@ async function dev(argv, runtime = {}) {
|
|
|
284994
285205
|
s.stop(first.message, first.ok ? 0 : 1);
|
|
284995
285206
|
if (!first.ok) {
|
|
284996
285207
|
localAbort?.abort();
|
|
285208
|
+
localLease?.release();
|
|
284997
285209
|
process.exit(1);
|
|
284998
285210
|
}
|
|
284999
285211
|
if (runtime.branch) {
|
|
@@ -285050,6 +285262,7 @@ async function dev(argv, runtime = {}) {
|
|
|
285050
285262
|
const stop = () => {
|
|
285051
285263
|
watcher.close();
|
|
285052
285264
|
localAbort?.abort();
|
|
285265
|
+
localLease?.release();
|
|
285053
285266
|
console.log(`
|
|
285054
285267
|
${import_picocolors16.default.dim("stopped.")}`);
|
|
285055
285268
|
process.exit(0);
|
|
@@ -285079,7 +285292,7 @@ function parseBranchDevArgs(argv) {
|
|
|
285079
285292
|
const arg = argv[index];
|
|
285080
285293
|
if (!arg) continue;
|
|
285081
285294
|
if (arg === "--no-branch") {
|
|
285082
|
-
throw new
|
|
285295
|
+
throw new import_errors15.AbloValidationError(
|
|
285083
285296
|
"--no-branch was removed: development is branch-isolated. Use --branch <slug> to select explicitly.",
|
|
285084
285297
|
{ code: "cli_invalid_arguments" }
|
|
285085
285298
|
);
|
|
@@ -285087,7 +285300,7 @@ function parseBranchDevArgs(argv) {
|
|
|
285087
285300
|
if (arg === "--branch") {
|
|
285088
285301
|
branchSlug = argv[++index];
|
|
285089
285302
|
if (!branchSlug) {
|
|
285090
|
-
throw new
|
|
285303
|
+
throw new import_errors15.AbloValidationError("--branch requires a slug", {
|
|
285091
285304
|
code: "cli_invalid_arguments"
|
|
285092
285305
|
});
|
|
285093
285306
|
}
|
|
@@ -285096,7 +285309,7 @@ function parseBranchDevArgs(argv) {
|
|
|
285096
285309
|
if (arg === "--branch-ttl-hours") {
|
|
285097
285310
|
const value = Number(argv[++index]);
|
|
285098
285311
|
if (!Number.isInteger(value) || value < 1 || value > 168) {
|
|
285099
|
-
throw new
|
|
285312
|
+
throw new import_errors15.AbloValidationError("--branch-ttl-hours must be between 1 and 168", {
|
|
285100
285313
|
code: "cli_invalid_arguments"
|
|
285101
285314
|
});
|
|
285102
285315
|
}
|
|
@@ -285114,12 +285327,12 @@ function parseBranchDevArgs(argv) {
|
|
|
285114
285327
|
function branchSlugFromRef(ref) {
|
|
285115
285328
|
const base = ref.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
285116
285329
|
if (!base) {
|
|
285117
|
-
throw new
|
|
285330
|
+
throw new import_errors15.AbloValidationError(`cannot derive an Ablo branch slug from "${ref}"`, {
|
|
285118
285331
|
code: "cli_invalid_arguments"
|
|
285119
285332
|
});
|
|
285120
285333
|
}
|
|
285121
285334
|
const nonRoot = base === "production" ? "production-dev" : base;
|
|
285122
|
-
const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0,
|
|
285335
|
+
const shortened = nonRoot.length <= 40 ? nonRoot : `${nonRoot.slice(0, 31).replace(/-+$/g, "")}-${(0, import_node_crypto6.createHash)("sha256").update(nonRoot).digest("hex").slice(0, 8)}`;
|
|
285123
285336
|
return import_branches2.branchSlugSchema.parse(shortened);
|
|
285124
285337
|
}
|
|
285125
285338
|
function gitBranch() {
|
|
@@ -285136,7 +285349,7 @@ function gitBranch() {
|
|
|
285136
285349
|
function discoverBranchRef(explicit, env = process.env, readGitBranch = gitBranch) {
|
|
285137
285350
|
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();
|
|
285138
285351
|
if (!value) {
|
|
285139
|
-
throw new
|
|
285352
|
+
throw new import_errors15.AbloValidationError(
|
|
285140
285353
|
"Could not determine the Git branch. Pass --branch <slug> or set ABLO_BRANCH.",
|
|
285141
285354
|
{ code: "cli_invalid_arguments" }
|
|
285142
285355
|
);
|
|
@@ -285154,13 +285367,13 @@ async function runBranchDev(argv, dependencies = {}) {
|
|
|
285154
285367
|
const slug = branchSlugFromRef(ref);
|
|
285155
285368
|
const managementKey = dependencies.resolveManagementKey?.() ?? resolveManagementKey();
|
|
285156
285369
|
if (!managementKey) {
|
|
285157
|
-
throw new
|
|
285158
|
-
"Creating a development branch needs a project management credential. Run `npx ablo login` or set
|
|
285370
|
+
throw new import_errors15.AbloValidationError(
|
|
285371
|
+
"Creating a development branch needs a project management credential. Run `npx ablo login` or set ABLO_API_KEY to an mk_ credential.",
|
|
285159
285372
|
{ code: "cli_invalid_arguments" }
|
|
285160
285373
|
);
|
|
285161
285374
|
}
|
|
285162
285375
|
if (!managementKey.startsWith("mk_")) {
|
|
285163
|
-
throw new
|
|
285376
|
+
throw new import_errors15.AbloValidationError(
|
|
285164
285377
|
"Branch creation needs the active project management credential (mk_\u2026). Run `npx ablo login` to refresh it.",
|
|
285165
285378
|
{ code: "cli_invalid_arguments" }
|
|
285166
285379
|
);
|
|
@@ -285189,7 +285402,7 @@ async function runBranchDev(argv, dependencies = {}) {
|
|
|
285189
285402
|
// src/whoami.ts
|
|
285190
285403
|
init_cjs_shims();
|
|
285191
285404
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
285192
|
-
var
|
|
285405
|
+
var import_errors16 = require("@abloatai/transaction/errors");
|
|
285193
285406
|
init_config();
|
|
285194
285407
|
init_controlPlane();
|
|
285195
285408
|
|
|
@@ -285264,7 +285477,7 @@ function parseWhoamiArgs(argv) {
|
|
|
285264
285477
|
case "--key": {
|
|
285265
285478
|
const value = argv[++i];
|
|
285266
285479
|
if (!value || value.startsWith("--")) {
|
|
285267
|
-
throw new
|
|
285480
|
+
throw new import_errors16.AbloValidationError("`--key` needs a credential value.", {
|
|
285268
285481
|
code: "cli_invalid_arguments"
|
|
285269
285482
|
});
|
|
285270
285483
|
}
|
|
@@ -285274,12 +285487,12 @@ function parseWhoamiArgs(argv) {
|
|
|
285274
285487
|
case "--key-env": {
|
|
285275
285488
|
const value = argv[++i];
|
|
285276
285489
|
if (!value || value.startsWith("--")) {
|
|
285277
|
-
throw new
|
|
285490
|
+
throw new import_errors16.AbloValidationError("`--key-env` needs an environment variable name.", {
|
|
285278
285491
|
code: "cli_invalid_arguments"
|
|
285279
285492
|
});
|
|
285280
285493
|
}
|
|
285281
285494
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
|
285282
|
-
throw new
|
|
285495
|
+
throw new import_errors16.AbloValidationError(
|
|
285283
285496
|
`\`${value}\` is not a valid environment variable name.`,
|
|
285284
285497
|
{ code: "cli_invalid_arguments" }
|
|
285285
285498
|
);
|
|
@@ -285288,13 +285501,13 @@ function parseWhoamiArgs(argv) {
|
|
|
285288
285501
|
break;
|
|
285289
285502
|
}
|
|
285290
285503
|
default:
|
|
285291
|
-
throw new
|
|
285504
|
+
throw new import_errors16.AbloValidationError(`unknown whoami flag: ${arg}`, {
|
|
285292
285505
|
code: "cli_invalid_arguments"
|
|
285293
285506
|
});
|
|
285294
285507
|
}
|
|
285295
285508
|
}
|
|
285296
285509
|
if (key && keyEnv) {
|
|
285297
|
-
throw new
|
|
285510
|
+
throw new import_errors16.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
|
|
285298
285511
|
code: "cli_invalid_arguments"
|
|
285299
285512
|
});
|
|
285300
285513
|
}
|
|
@@ -285305,7 +285518,7 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
|
|
|
285305
285518
|
if (args.keyEnv) {
|
|
285306
285519
|
const found = readProjectEnvVariable(args.keyEnv, cwd);
|
|
285307
285520
|
if (!found) {
|
|
285308
|
-
throw new
|
|
285521
|
+
throw new import_errors16.AbloAuthenticationError(
|
|
285309
285522
|
`${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
|
|
285310
285523
|
{ code: "cli_api_key_missing" }
|
|
285311
285524
|
);
|
|
@@ -285329,12 +285542,12 @@ function selectWhoamiCredential(args, cwd = process.cwd()) {
|
|
|
285329
285542
|
if (managementKey) {
|
|
285330
285543
|
return {
|
|
285331
285544
|
key: managementKey,
|
|
285332
|
-
source:
|
|
285333
|
-
targetSource:
|
|
285545
|
+
source: "stored login",
|
|
285546
|
+
targetSource: "stored"
|
|
285334
285547
|
};
|
|
285335
285548
|
}
|
|
285336
285549
|
const ambient = ambientEnvKeyNote();
|
|
285337
|
-
throw new
|
|
285550
|
+
throw new import_errors16.AbloAuthenticationError(
|
|
285338
285551
|
`No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
|
|
285339
285552
|
|
|
285340
285553
|
${ambient}` : ""}`,
|
|
@@ -285352,7 +285565,7 @@ async function whoami(argv) {
|
|
|
285352
285565
|
});
|
|
285353
285566
|
const confirmed = target.confirmed;
|
|
285354
285567
|
if (!confirmed) {
|
|
285355
|
-
throw new
|
|
285568
|
+
throw new import_errors16.AbloAuthenticationError(
|
|
285356
285569
|
"The server did not confirm an identity for this credential.",
|
|
285357
285570
|
{ code: "identity_resolve_failed" }
|
|
285358
285571
|
);
|
|
@@ -285410,15 +285623,15 @@ init_push();
|
|
|
285410
285623
|
// src/setup/run.ts
|
|
285411
285624
|
init_cjs_shims();
|
|
285412
285625
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
285413
|
-
var
|
|
285626
|
+
var import_errors17 = require("@abloatai/transaction/errors");
|
|
285414
285627
|
init_theme();
|
|
285415
285628
|
|
|
285416
285629
|
// src/setup/discover.ts
|
|
285417
285630
|
init_cjs_shims();
|
|
285418
|
-
var
|
|
285419
|
-
var
|
|
285631
|
+
var import_node_fs4 = require("fs");
|
|
285632
|
+
var import_node_crypto7 = require("crypto");
|
|
285420
285633
|
var import_node_child_process2 = require("child_process");
|
|
285421
|
-
var
|
|
285634
|
+
var import_node_path3 = require("path");
|
|
285422
285635
|
init_controlPlane();
|
|
285423
285636
|
init_config();
|
|
285424
285637
|
|
|
@@ -286477,7 +286690,7 @@ function tryGit(cwd, args) {
|
|
|
286477
286690
|
}
|
|
286478
286691
|
}
|
|
286479
286692
|
function resolveRepositoryRoot(cwd = process.cwd()) {
|
|
286480
|
-
return (0,
|
|
286693
|
+
return (0, import_node_path3.resolve)(tryGit(cwd, ["rev-parse", "--show-toplevel"]) || cwd);
|
|
286481
286694
|
}
|
|
286482
286695
|
function walkFiles(root, maxDepth = 5) {
|
|
286483
286696
|
const files = [];
|
|
@@ -286486,13 +286699,13 @@ function walkFiles(root, maxDepth = 5) {
|
|
|
286486
286699
|
const current = stack.pop();
|
|
286487
286700
|
let entries;
|
|
286488
286701
|
try {
|
|
286489
|
-
entries = (0,
|
|
286702
|
+
entries = (0, import_node_fs4.readdirSync)(current.path, { withFileTypes: true });
|
|
286490
286703
|
} catch {
|
|
286491
286704
|
continue;
|
|
286492
286705
|
}
|
|
286493
286706
|
for (const entry of entries.slice(0, 1e4)) {
|
|
286494
286707
|
if (files.length >= MAX_DISCOVERY_FILES) break;
|
|
286495
|
-
const path = (0,
|
|
286708
|
+
const path = (0, import_node_path3.join)(current.path, entry.name);
|
|
286496
286709
|
if (entry.isDirectory()) {
|
|
286497
286710
|
if (current.depth < maxDepth && !IGNORED_DIRECTORIES.has(entry.name)) {
|
|
286498
286711
|
stack.push({ path, depth: current.depth + 1 });
|
|
@@ -286506,9 +286719,9 @@ function walkFiles(root, maxDepth = 5) {
|
|
|
286506
286719
|
}
|
|
286507
286720
|
function readManifest(path) {
|
|
286508
286721
|
try {
|
|
286509
|
-
const parsed = JSON.parse((0,
|
|
286722
|
+
const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path, "utf8"));
|
|
286510
286723
|
return {
|
|
286511
|
-
root: (0,
|
|
286724
|
+
root: (0, import_node_path3.resolve)(path, ".."),
|
|
286512
286725
|
name: typeof parsed.name === "string" ? parsed.name : null,
|
|
286513
286726
|
dependencies: { ...parsed.dependencies, ...parsed.devDependencies },
|
|
286514
286727
|
scripts: { ...parsed.scripts }
|
|
@@ -286518,14 +286731,14 @@ function readManifest(path) {
|
|
|
286518
286731
|
}
|
|
286519
286732
|
}
|
|
286520
286733
|
function packageManifests(root, files) {
|
|
286521
|
-
return files.filter((path) => (0,
|
|
286734
|
+
return files.filter((path) => (0, import_node_path3.basename)(path) === "package.json").flatMap((path) => {
|
|
286522
286735
|
const manifest = readManifest(path);
|
|
286523
286736
|
return manifest ? [manifest] : [];
|
|
286524
286737
|
}).sort((a, b4) => a.root.localeCompare(b4.root));
|
|
286525
286738
|
}
|
|
286526
286739
|
function pathInside(root, target) {
|
|
286527
|
-
const fromRoot = (0,
|
|
286528
|
-
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${
|
|
286740
|
+
const fromRoot = (0, import_node_path3.relative)(root, target);
|
|
286741
|
+
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${import_node_path3.sep}`);
|
|
286529
286742
|
}
|
|
286530
286743
|
function packageOwnedFiles(manifest, manifests, files) {
|
|
286531
286744
|
const nestedPackageRoots = manifests.filter(({ root }) => root !== manifest.root && pathInside(manifest.root, root));
|
|
@@ -286583,8 +286796,8 @@ function detectedPersistence(manifest, files) {
|
|
|
286583
286796
|
if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
|
|
286584
286797
|
let source;
|
|
286585
286798
|
try {
|
|
286586
|
-
if ((0,
|
|
286587
|
-
source = (0,
|
|
286799
|
+
if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
|
|
286800
|
+
source = (0, import_node_fs4.readFileSync)(path, "utf8");
|
|
286588
286801
|
} catch {
|
|
286589
286802
|
continue;
|
|
286590
286803
|
}
|
|
@@ -286612,17 +286825,17 @@ function coordinationAdoptionReason(disposition, persistence) {
|
|
|
286612
286825
|
}
|
|
286613
286826
|
}
|
|
286614
286827
|
function packageManager(root) {
|
|
286615
|
-
if ((0,
|
|
286616
|
-
if ((0,
|
|
286617
|
-
if ((0,
|
|
286828
|
+
if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
286829
|
+
if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "yarn.lock"))) return "yarn";
|
|
286830
|
+
if ((0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "bun.lockb")) || (0, import_node_fs4.existsSync)((0, import_node_path3.join)(root, "bun.lock"))) return "bun";
|
|
286618
286831
|
return "npm";
|
|
286619
286832
|
}
|
|
286620
286833
|
function environmentKeyNames(root) {
|
|
286621
286834
|
const names = [".env.local", ".env.development.local", ".env.development", ".env"];
|
|
286622
286835
|
return names.flatMap((name) => {
|
|
286623
|
-
const path = (0,
|
|
286624
|
-
if (!(0,
|
|
286625
|
-
const keys = (0,
|
|
286836
|
+
const path = (0, import_node_path3.join)(root, name);
|
|
286837
|
+
if (!(0, import_node_fs4.existsSync)(path)) return [];
|
|
286838
|
+
const keys = (0, import_node_fs4.readFileSync)(path, "utf8").split(/\r?\n/).flatMap((line) => {
|
|
286626
286839
|
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
|
|
286627
286840
|
return match ? [match[1]] : [];
|
|
286628
286841
|
});
|
|
@@ -286637,8 +286850,8 @@ function abloSourceFiles(root, files) {
|
|
|
286637
286850
|
return files.flatMap((path) => {
|
|
286638
286851
|
if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) return [];
|
|
286639
286852
|
try {
|
|
286640
|
-
if ((0,
|
|
286641
|
-
return (0,
|
|
286853
|
+
if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) return [];
|
|
286854
|
+
return (0, import_node_fs4.readFileSync)(path, "utf8").includes("@abloatai/") ? [(0, import_node_path3.relative)(root, path) || "."] : [];
|
|
286642
286855
|
} catch {
|
|
286643
286856
|
return [];
|
|
286644
286857
|
}
|
|
@@ -286665,12 +286878,12 @@ function discoverMutationSites(root, files) {
|
|
|
286665
286878
|
if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
|
|
286666
286879
|
let source;
|
|
286667
286880
|
try {
|
|
286668
|
-
if ((0,
|
|
286669
|
-
source = (0,
|
|
286881
|
+
if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
|
|
286882
|
+
source = (0, import_node_fs4.readFileSync)(path, "utf8");
|
|
286670
286883
|
} catch {
|
|
286671
286884
|
continue;
|
|
286672
286885
|
}
|
|
286673
|
-
const locator = (0,
|
|
286886
|
+
const locator = (0, import_node_path3.relative)(root, path) || ".";
|
|
286674
286887
|
for (const match of source.matchAll(/\b(?:(?:[A-Za-z_$][\w$]*)\.query|query|q)\s*\(\s*(?:`|['"])\s*(INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+([A-Za-z_$][\w$.[\]"`]*|"[^"]+"|`[^`]+`)/gi)) {
|
|
286675
286888
|
const rawTable = match[2] ?? "";
|
|
286676
286889
|
const modelHint = rawTable.replace(/["`\[\]]/g, "").split(".").at(-1)?.toLowerCase() || null;
|
|
@@ -286702,13 +286915,13 @@ function discoverMutationSites(root, files) {
|
|
|
286702
286915
|
return sites.sort((a, b4) => a.path.localeCompare(b4.path) || a.line - b4.line);
|
|
286703
286916
|
}
|
|
286704
286917
|
function isProductionMutationFile(root, path) {
|
|
286705
|
-
const locator = (0,
|
|
286918
|
+
const locator = (0, import_node_path3.relative)(root, path).replaceAll("\\", "/");
|
|
286706
286919
|
return !/(?:^|\/)(?:test|tests|__tests__|scripts)(?:\/|$)/.test(locator) && !/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(locator);
|
|
286707
286920
|
}
|
|
286708
286921
|
function digestFile(path) {
|
|
286709
|
-
if (!(0,
|
|
286922
|
+
if (!(0, import_node_fs4.existsSync)(path)) return null;
|
|
286710
286923
|
try {
|
|
286711
|
-
return (0,
|
|
286924
|
+
return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs4.readFileSync)(path)).digest("hex");
|
|
286712
286925
|
} catch {
|
|
286713
286926
|
return null;
|
|
286714
286927
|
}
|
|
@@ -286739,7 +286952,7 @@ function localDiscoveryStep(state) {
|
|
|
286739
286952
|
const appFiles = selected ? packageOwnedFiles(selected, state.packageManifests, files) : files.filter((path) => pathInside(envRoot, path));
|
|
286740
286953
|
const persistence = selected ? detectedPersistence(selected, appFiles) : [];
|
|
286741
286954
|
const coordinationAdoption = coordinationAdoptionDisposition(persistence);
|
|
286742
|
-
const excludedNestedPackages = selected ? state.packageManifests.filter(({ root: packageRoot2 }) => packageRoot2 !== selected.root && pathInside(selected.root, packageRoot2)).map(({ root: packageRoot2, name }) => ({ root: (0,
|
|
286955
|
+
const excludedNestedPackages = selected ? state.packageManifests.filter(({ root: packageRoot2 }) => packageRoot2 !== selected.root && pathInside(selected.root, packageRoot2)).map(({ root: packageRoot2, name }) => ({ root: (0, import_node_path3.relative)(root, packageRoot2), name })) : [];
|
|
286743
286956
|
const mutationSites = discoverMutationSites(
|
|
286744
286957
|
envRoot,
|
|
286745
286958
|
appFiles.filter((path) => isProductionMutationFile(envRoot, path))
|
|
@@ -286752,17 +286965,17 @@ function localDiscoveryStep(state) {
|
|
|
286752
286965
|
if (!SOURCE_EXTENSIONS.has(sourceExtension(path))) continue;
|
|
286753
286966
|
let source;
|
|
286754
286967
|
try {
|
|
286755
|
-
if ((0,
|
|
286756
|
-
source = (0,
|
|
286968
|
+
if ((0, import_node_fs4.lstatSync)(path).size > MAX_SOURCE_BYTES) continue;
|
|
286969
|
+
source = (0, import_node_fs4.readFileSync)(path, "utf8");
|
|
286757
286970
|
} catch {
|
|
286758
286971
|
continue;
|
|
286759
286972
|
}
|
|
286760
286973
|
databaseColumns.push(...discoverDatabaseColumnsFromSqlSource({
|
|
286761
|
-
path: (0,
|
|
286974
|
+
path: (0, import_node_path3.relative)(envRoot, path),
|
|
286762
286975
|
source
|
|
286763
286976
|
}));
|
|
286764
286977
|
transactionalRequirements.push(...discoverTransactionalRequirementsFromSqlSource({
|
|
286765
|
-
path: (0,
|
|
286978
|
+
path: (0, import_node_path3.relative)(envRoot, path),
|
|
286766
286979
|
source
|
|
286767
286980
|
}));
|
|
286768
286981
|
}
|
|
@@ -286794,8 +287007,8 @@ function localDiscoveryStep(state) {
|
|
|
286794
287007
|
"src/app/providers.tsx",
|
|
286795
287008
|
"app/api/ablo-session/route.ts",
|
|
286796
287009
|
"src/app/api/ablo-session/route.ts"
|
|
286797
|
-
].filter((path) => (0,
|
|
286798
|
-
const localSchemaPath = [(0,
|
|
287010
|
+
].filter((path) => (0, import_node_fs4.existsSync)((0, import_node_path3.join)(envRoot, path)));
|
|
287011
|
+
const localSchemaPath = [(0, import_node_path3.join)(envRoot, "ablo", "schema.ts"), (0, import_node_path3.join)(envRoot, "src", "ablo", "schema.ts")].find((path) => (0, import_node_fs4.existsSync)(path)) ?? (0, import_node_path3.join)(envRoot, "ablo", "schema.ts");
|
|
286799
287012
|
state.localSchemaDigest = digestFile(localSchemaPath);
|
|
286800
287013
|
const facts = [
|
|
286801
287014
|
fact("repository.root", root, "git", tryGit(root, ["rev-parse", "--show-toplevel"]) ? "Resolved from Git." : "No Git root was available; using the requested directory.", root),
|
|
@@ -286804,9 +287017,9 @@ function localDiscoveryStep(state) {
|
|
|
286804
287017
|
fact("repository.dirtyPathCount", dirtyEntries.length, "git", "Count from porcelain status; path names are intentionally omitted.", root),
|
|
286805
287018
|
fact("repository.scanTruncated", files.length >= MAX_DISCOVERY_FILES, "filesystem", `Scanned at most ${MAX_DISCOVERY_FILES} files to depth 5.`, root),
|
|
286806
287019
|
fact("package.manager", packageManager(root), "filesystem", "Detected from the repository lockfile.", root),
|
|
286807
|
-
fact("application.candidates", candidates.map(({ manifest, frameworks, dataAccess, runtimeEntrypoint }) => ({ root: (0,
|
|
286808
|
-
fact("application.selectedRoot", state.applicationRoot ? (0,
|
|
286809
|
-
fact("application.packageName", state.packageName, "package_manifest", "Read from the selected package manifest.", state.applicationRoot ? (0,
|
|
287020
|
+
fact("application.candidates", candidates.map(({ manifest, frameworks, dataAccess, runtimeEntrypoint }) => ({ root: (0, import_node_path3.relative)(root, manifest.root) || ".", name: manifest.name, frameworks, dataAccess, runtimeEntrypoint })), "package_manifest", `${candidates.length} runnable application candidate(s) found.`, root),
|
|
287021
|
+
fact("application.selectedRoot", state.applicationRoot ? (0, import_node_path3.relative)(root, state.applicationRoot) || "." : null, "inference", state.applicationRoot ? "Exactly one usable application root was selected." : "Application selection is ambiguous.", root, state.applicationRoot ? "high" : "low"),
|
|
287022
|
+
fact("application.packageName", state.packageName, "package_manifest", "Read from the selected package manifest.", state.applicationRoot ? (0, import_node_path3.join)((0, import_node_path3.relative)(root, state.applicationRoot), "package.json") : "package.json"),
|
|
286810
287023
|
fact("application.frameworks", selected ? selectedFrameworks : candidates.flatMap(({ frameworks }) => frameworks), "package_manifest", "Detected only from declared package dependencies.", root),
|
|
286811
287024
|
fact("application.kinds", selectedApplicationKinds, "package_manifest", "Detected from runtime scripts and declared framework or database dependencies.", root),
|
|
286812
287025
|
fact("application.excludedNestedPackages", excludedNestedPackages, "package_manifest", "Independently manifested nested packages are excluded from the selected package's lexical mutation inventory; an agent may still follow application imports across that boundary.", root),
|
|
@@ -286827,16 +287040,16 @@ function localDiscoveryStep(state) {
|
|
|
286827
287040
|
fact("application.databaseSchemaEvidence", uniqueDatabaseColumns, "filesystem", "Conservative database-column evidence derived from application-owned CREATE TABLE statements. Database catalogs remain authoritative.", envRoot, "medium"),
|
|
286828
287041
|
fact("application.transactionalRequirements", uniqueRequirements, "filesystem", "Transaction shapes whose atomic predicates or exact RETURNING rows must be preserved.", envRoot, "medium"),
|
|
286829
287042
|
fact("application.compatibilityDisposition", state.compatibility, "inference", "Compared database and transaction evidence with the current canonical Ablo contracts.", envRoot, uniqueDatabaseColumns.length > 0 ? "medium" : "low"),
|
|
286830
|
-
fact("application.localSchemaDigest", state.localSchemaDigest, "filesystem", state.localSchemaDigest ? "SHA-256 of the local schema source file." : "No local ablo/schema.ts was found.", (0,
|
|
287043
|
+
fact("application.localSchemaDigest", state.localSchemaDigest, "filesystem", state.localSchemaDigest ? "SHA-256 of the local schema source file." : "No local ablo/schema.ts was found.", (0, import_node_path3.relative)(root, localSchemaPath))
|
|
286831
287044
|
];
|
|
286832
287045
|
const applicationChoices = candidates.map(({ manifest, frameworks, dataAccess }) => ({
|
|
286833
|
-
value: (0,
|
|
286834
|
-
label: manifest.name ?? ((0,
|
|
287046
|
+
value: (0, import_node_path3.relative)(root, manifest.root) || ".",
|
|
287047
|
+
label: manifest.name ?? ((0, import_node_path3.relative)(root, manifest.root) || "."),
|
|
286835
287048
|
consequence: `Setup will modify only this ${[...frameworks, ...dataAccess].join("/")} application.`
|
|
286836
287049
|
}));
|
|
286837
|
-
if (state.applicationRoot && !applicationChoices.some(({ value }) => value === ((0,
|
|
287050
|
+
if (state.applicationRoot && !applicationChoices.some(({ value }) => value === ((0, import_node_path3.relative)(root, state.applicationRoot) || "."))) {
|
|
286838
287051
|
applicationChoices.push({
|
|
286839
|
-
value: (0,
|
|
287052
|
+
value: (0, import_node_path3.relative)(root, state.applicationRoot) || ".",
|
|
286840
287053
|
label: state.packageName ?? ".",
|
|
286841
287054
|
consequence: "Setup will treat this package as the application root; framework support remains unconfirmed."
|
|
286842
287055
|
});
|
|
@@ -286847,7 +287060,7 @@ function localDiscoveryStep(state) {
|
|
|
286847
287060
|
question: "Which application should Ablo set up?",
|
|
286848
287061
|
status: state.applicationRoot ? "resolved" : "unresolved",
|
|
286849
287062
|
choices: applicationChoices,
|
|
286850
|
-
...state.applicationRoot ? { selected: (0,
|
|
287063
|
+
...state.applicationRoot ? { selected: (0, import_node_path3.relative)(root, state.applicationRoot) || "." } : {},
|
|
286851
287064
|
reason: state.applicationRoot ? dataApplications.length === 1 ? "Exactly one runnable package owns database access, so it is the coordination boundary." : runtimeOwners.length === 1 ? "Exactly one package owns a concrete runtime entrypoint, so it is the application boundary." : "The repository has one unambiguous application target." : "More than one or no runnable application was identified."
|
|
286852
287065
|
},
|
|
286853
287066
|
{
|
|
@@ -287197,7 +287410,7 @@ function parseSetupArgs(args) {
|
|
|
287197
287410
|
if (arg === "--root") {
|
|
287198
287411
|
const next = args[index + 1];
|
|
287199
287412
|
if (!next || next.startsWith("-")) {
|
|
287200
|
-
throw new
|
|
287413
|
+
throw new import_errors17.AbloValidationError("`--root` requires a directory.", {
|
|
287201
287414
|
code: "cli_invalid_arguments"
|
|
287202
287415
|
});
|
|
287203
287416
|
}
|
|
@@ -287206,7 +287419,7 @@ function parseSetupArgs(args) {
|
|
|
287206
287419
|
continue;
|
|
287207
287420
|
}
|
|
287208
287421
|
if (!allowedFlags.has(arg)) {
|
|
287209
|
-
throw new
|
|
287422
|
+
throw new import_errors17.AbloValidationError(`Unknown setup option: ${arg}`, {
|
|
287210
287423
|
code: "cli_invalid_arguments"
|
|
287211
287424
|
});
|
|
287212
287425
|
}
|
|
@@ -287292,7 +287505,7 @@ function renderHumanPlan(plan) {
|
|
|
287292
287505
|
async function runSetup(args) {
|
|
287293
287506
|
const options = parseSetupArgs(args);
|
|
287294
287507
|
if (options.json && !options.plan) {
|
|
287295
|
-
throw new
|
|
287508
|
+
throw new import_errors17.AbloValidationError(
|
|
287296
287509
|
"`--json` is a plan renderer. Use `ablo setup --plan --json`.",
|
|
287297
287510
|
{ code: "cli_invalid_arguments" }
|
|
287298
287511
|
);
|
|
@@ -287306,11 +287519,13 @@ async function runSetup(args) {
|
|
|
287306
287519
|
}
|
|
287307
287520
|
|
|
287308
287521
|
// src/commands.ts
|
|
287522
|
+
init_theme();
|
|
287309
287523
|
var CORE_GROUPS = ["Start", "Every day", "More"];
|
|
287310
287524
|
var FULL_GROUPS = [
|
|
287311
287525
|
"Set up",
|
|
287312
287526
|
"Your database",
|
|
287313
287527
|
"Your schema",
|
|
287528
|
+
"Your writes",
|
|
287314
287529
|
"Read the docs",
|
|
287315
287530
|
"See what's happening",
|
|
287316
287531
|
"Workspace"
|
|
@@ -287349,8 +287564,8 @@ var COMMANDS = [
|
|
|
287349
287564
|
full: {
|
|
287350
287565
|
group: "Set up",
|
|
287351
287566
|
rows: [
|
|
287352
|
-
{ run: "login", does: "Authorize in your browser \u2014 stores
|
|
287353
|
-
{ run: "login --project <slug>", does: "Same,
|
|
287567
|
+
{ run: "login", does: "Authorize in your browser, pick a project \u2014 stores its mk_ management credential" },
|
|
287568
|
+
{ run: "login --project <slug>", does: "Same, without the picker \u2014 the named project becomes active" }
|
|
287354
287569
|
]
|
|
287355
287570
|
}
|
|
287356
287571
|
},
|
|
@@ -287441,6 +287656,28 @@ var COMMANDS = [
|
|
|
287441
287656
|
]
|
|
287442
287657
|
}
|
|
287443
287658
|
},
|
|
287659
|
+
{
|
|
287660
|
+
name: "claims",
|
|
287661
|
+
core: {
|
|
287662
|
+
group: "Every day",
|
|
287663
|
+
does: "Say what you are editing, so another writer waits instead of clobbering it"
|
|
287664
|
+
},
|
|
287665
|
+
full: {
|
|
287666
|
+
group: "Your writes",
|
|
287667
|
+
rows: [
|
|
287668
|
+
{ run: "claims acquire <model> <id>", does: "Take the lease on one row" },
|
|
287669
|
+
{ run: "claims acquire <model> <id> -- <cmd>", does: "Hold it only while <cmd> runs, then release" },
|
|
287670
|
+
{ run: "claims acquire <model> <id> --queue", does: "Wait in line when it is held, instead of failing" },
|
|
287671
|
+
{ run: "claims acquire <model> <id> --ttl 5m", does: "Lease length: 30s, 5m, 2h (default 60s)" },
|
|
287672
|
+
{ run: "claims acquire <model> <id> --description <t>", does: "What you are doing, shown to whoever waits" },
|
|
287673
|
+
{ run: "claims release <model> <id>", does: "Give the lease back" },
|
|
287674
|
+
{ run: "claims heartbeat <model> <id>", does: "Extend a lease you already hold" },
|
|
287675
|
+
{ run: "claims list [<model> [<id>]]", does: "Who holds what, and who waits" },
|
|
287676
|
+
{ run: "claims list --actor <id>", does: "Narrow a listing to one holder" },
|
|
287677
|
+
{ run: "claims list --json", does: "Same, machine-readable" }
|
|
287678
|
+
]
|
|
287679
|
+
}
|
|
287680
|
+
},
|
|
287444
287681
|
{
|
|
287445
287682
|
name: "generate",
|
|
287446
287683
|
full: {
|
|
@@ -287586,7 +287823,9 @@ var REDIRECTS = /* @__PURE__ */ new Map([
|
|
|
287586
287823
|
["disconnect", "connect deregister"],
|
|
287587
287824
|
["deregister", "connect deregister"],
|
|
287588
287825
|
["register", "connect register"],
|
|
287589
|
-
["rotate", "connect rotate"]
|
|
287826
|
+
["rotate", "connect rotate"],
|
|
287827
|
+
["claim", "claims acquire"],
|
|
287828
|
+
["release", "claims release"]
|
|
287590
287829
|
]);
|
|
287591
287830
|
function editDistance(a, b4) {
|
|
287592
287831
|
const cols = b4.length + 1;
|
|
@@ -287623,7 +287862,22 @@ function suggestCommand(raw) {
|
|
|
287623
287862
|
return REDIRECTS.get(best.name) ?? best.name;
|
|
287624
287863
|
}
|
|
287625
287864
|
function usageFor(name) {
|
|
287626
|
-
|
|
287865
|
+
const command = BY_NAME.get(name);
|
|
287866
|
+
if (command === void 0) return void 0;
|
|
287867
|
+
if (command.usage !== void 0) return command.usage;
|
|
287868
|
+
const rows = command.full?.rows ?? [];
|
|
287869
|
+
const described = rows.filter((row) => row.does !== void 0);
|
|
287870
|
+
if (described.length === 0) return void 0;
|
|
287871
|
+
const width = Math.max(...described.map((row) => row.run.length)) + 2;
|
|
287872
|
+
const headline = command.core?.does;
|
|
287873
|
+
return [
|
|
287874
|
+
` ${brand(`ablo ${name}`)}${headline !== void 0 ? ` \u2014 ${headline}` : ""}`,
|
|
287875
|
+
"",
|
|
287876
|
+
...rows.map(
|
|
287877
|
+
(row) => row.does === void 0 ? ` ${row.run}` : ` ablo ${row.run.padEnd(width)}${row.does}`
|
|
287878
|
+
),
|
|
287879
|
+
""
|
|
287880
|
+
].join("\n");
|
|
287627
287881
|
}
|
|
287628
287882
|
function coreRows(group) {
|
|
287629
287883
|
return ALL.filter((c) => c.core?.group === group).map((c) => ({
|
|
@@ -287636,16 +287890,16 @@ function fullRows(group) {
|
|
|
287636
287890
|
}
|
|
287637
287891
|
|
|
287638
287892
|
// src/index.ts
|
|
287639
|
-
var
|
|
287893
|
+
var import_errors26 = require("@abloatai/transaction/errors");
|
|
287640
287894
|
init_push();
|
|
287641
287895
|
|
|
287642
287896
|
// src/generate.ts
|
|
287643
287897
|
init_cjs_shims();
|
|
287644
|
-
var
|
|
287898
|
+
var import_errors18 = require("@abloatai/transaction/errors");
|
|
287645
287899
|
var import_fs8 = require("fs");
|
|
287646
287900
|
var import_path6 = require("path");
|
|
287647
287901
|
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
287648
|
-
var
|
|
287902
|
+
var import_schema6 = require("@abloatai/transaction/schema");
|
|
287649
287903
|
init_push();
|
|
287650
287904
|
var DEFAULT_SCHEMA_PATH4 = "ablo/schema.ts";
|
|
287651
287905
|
var DEFAULT_EXPORT3 = "schema";
|
|
@@ -287667,7 +287921,7 @@ function parseGenerateArgs(argv) {
|
|
|
287667
287921
|
out = argv[++i] ?? out;
|
|
287668
287922
|
break;
|
|
287669
287923
|
default:
|
|
287670
|
-
throw new
|
|
287924
|
+
throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
287671
287925
|
}
|
|
287672
287926
|
}
|
|
287673
287927
|
return { schemaPath, exportName, out };
|
|
@@ -287683,8 +287937,8 @@ async function generate(argv) {
|
|
|
287683
287937
|
let source;
|
|
287684
287938
|
try {
|
|
287685
287939
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
287686
|
-
const schemaJson = JSON.parse((0,
|
|
287687
|
-
source = (0,
|
|
287940
|
+
const schemaJson = JSON.parse((0, import_schema6.serializeSchema)(schema));
|
|
287941
|
+
source = (0, import_schema6.generateTypes)(schemaJson);
|
|
287688
287942
|
} catch (err) {
|
|
287689
287943
|
console.error(import_picocolors20.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
287690
287944
|
process.exit(1);
|
|
@@ -287700,9 +287954,10 @@ init_cjs_shims();
|
|
|
287700
287954
|
var import_child_process2 = require("child_process");
|
|
287701
287955
|
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
287702
287956
|
init_dist2();
|
|
287703
|
-
var
|
|
287704
|
-
var
|
|
287957
|
+
var import_errors19 = require("@abloatai/transaction/errors");
|
|
287958
|
+
var import_wire9 = require("@abloatai/transaction/wire");
|
|
287705
287959
|
init_config();
|
|
287960
|
+
init_projects();
|
|
287706
287961
|
init_theme();
|
|
287707
287962
|
var CLIENT_ID = "ablo-cli";
|
|
287708
287963
|
var stripSlash = (u2) => u2.replace(/\/+$/, "");
|
|
@@ -287728,11 +287983,52 @@ function parseSlugFlag(argv, flag2) {
|
|
|
287728
287983
|
const eq = argv.find((a) => a.startsWith(`${flag2}=`));
|
|
287729
287984
|
return eq ? eq.slice(flag2.length + 1) || void 0 : void 0;
|
|
287730
287985
|
}
|
|
287986
|
+
function projectSlugOrDefault(slug) {
|
|
287987
|
+
return slug === DEFAULT_PROFILE ? void 0 : slug;
|
|
287988
|
+
}
|
|
287989
|
+
async function listProjectsForSession(accessToken) {
|
|
287990
|
+
const res = await fetch(`${DASHBOARD_URL}/api/cli/projects`, {
|
|
287991
|
+
headers: { authorization: `Bearer ${accessToken}`, accept: "application/json" }
|
|
287992
|
+
}).catch(() => null);
|
|
287993
|
+
if (!res) return { ok: false, reason: `${DASHBOARD_URL} could not be reached` };
|
|
287994
|
+
return projectListResult(res.status, await res.json().catch(() => null));
|
|
287995
|
+
}
|
|
287996
|
+
async function pickProject(accessToken) {
|
|
287997
|
+
const active = getActiveProject();
|
|
287998
|
+
const s = Y2();
|
|
287999
|
+
s.start("Listing projects\u2026");
|
|
288000
|
+
const listed = await listProjectsForSession(accessToken);
|
|
288001
|
+
if (!listed.ok) {
|
|
288002
|
+
const fallback = projectSlugOrDefault(active?.slug);
|
|
288003
|
+
s.stop(
|
|
288004
|
+
`Couldn't list projects (${listed.reason}); continuing with ${fallback ? `project ${import_picocolors21.default.bold(fallback)}` : "the organization default"}.`
|
|
288005
|
+
);
|
|
288006
|
+
return fallback;
|
|
288007
|
+
}
|
|
288008
|
+
if (listed.projects.every((p2) => p2.default)) {
|
|
288009
|
+
s.stop("One project, the organization default.");
|
|
288010
|
+
return void 0;
|
|
288011
|
+
}
|
|
288012
|
+
s.stop(`${listed.projects.length} projects`);
|
|
288013
|
+
const current = active ? listed.projects.find((p2) => p2.id === active.id) : void 0;
|
|
288014
|
+
const choice = await ve({
|
|
288015
|
+
message: "Project",
|
|
288016
|
+
options: listed.projects.map((p2) => {
|
|
288017
|
+
const hint = projectDisplayName(p2) ?? (p2.default ? "organization default" : void 0);
|
|
288018
|
+
return { value: p2, label: p2.slug, ...hint ? { hint } : {} };
|
|
288019
|
+
}),
|
|
288020
|
+
...current ? { initialValue: current } : {}
|
|
288021
|
+
});
|
|
288022
|
+
if (pD(choice)) {
|
|
288023
|
+
xe("Cancelled.");
|
|
288024
|
+
process.exit(0);
|
|
288025
|
+
}
|
|
288026
|
+
return choice.default ? void 0 : choice.slug;
|
|
288027
|
+
}
|
|
287731
288028
|
async function deviceLogin(argv, deps = {}) {
|
|
287732
288029
|
const openUrl = deps.openUrl ?? openBrowser;
|
|
287733
288030
|
Ie(`${brand("ablo")} login`);
|
|
287734
|
-
const
|
|
287735
|
-
const targetProject = requested === DEFAULT_PROFILE ? void 0 : requested;
|
|
288031
|
+
const flagged = parseSlugFlag(argv, "--project");
|
|
287736
288032
|
const targetOrg = parseSlugFlag(argv, "--org");
|
|
287737
288033
|
const interactive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
287738
288034
|
let account = "login";
|
|
@@ -287811,30 +288107,33 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
|
|
|
287811
288107
|
s.stop("Timed out waiting for approval.");
|
|
287812
288108
|
process.exit(1);
|
|
287813
288109
|
}
|
|
287814
|
-
s.
|
|
288110
|
+
s.stop("Approved.");
|
|
288111
|
+
const targetProject = flagged !== void 0 ? projectSlugOrDefault(flagged) : interactive ? await pickProject(accessToken) : projectSlugOrDefault(getActiveProject()?.slug);
|
|
288112
|
+
const mint = Y2();
|
|
288113
|
+
mint.start(
|
|
287815
288114
|
targetProject ? `Provisioning project access for ${targetProject}\u2026` : "Provisioning project access\u2026"
|
|
287816
288115
|
);
|
|
287817
288116
|
const provRes = await fetch(`${DASHBOARD_URL}/api/cli/provision-key`, {
|
|
287818
288117
|
method: "POST",
|
|
287819
288118
|
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
|
|
287820
|
-
// Scope the minted keys to the chosen project
|
|
287821
|
-
//
|
|
287822
|
-
//
|
|
288119
|
+
// Scope the minted keys to the chosen project, with the device_code as a
|
|
288120
|
+
// legacy fallback for the /cli picker. Both harmless if absent →
|
|
288121
|
+
// org-default keys.
|
|
287823
288122
|
body: JSON.stringify({
|
|
287824
288123
|
device_code: code.device_code,
|
|
287825
288124
|
...targetProject ? { project_slug: targetProject } : {}
|
|
287826
288125
|
})
|
|
287827
288126
|
}).catch(() => null);
|
|
287828
288127
|
if (!provRes) {
|
|
287829
|
-
|
|
288128
|
+
mint.stop("Could not provision a key.");
|
|
287830
288129
|
M2.error(
|
|
287831
288130
|
`Could not reach ${DASHBOARD_URL} to finish the handoff. Check your connection and run \`ablo login\` again.`
|
|
287832
288131
|
);
|
|
287833
288132
|
process.exit(1);
|
|
287834
288133
|
}
|
|
287835
288134
|
if (!provRes.ok) {
|
|
287836
|
-
|
|
287837
|
-
const err = (0,
|
|
288135
|
+
mint.stop("Could not provision a key.");
|
|
288136
|
+
const err = (0, import_errors19.translateHttpError)(
|
|
287838
288137
|
provRes.status,
|
|
287839
288138
|
await provRes.json().catch(() => null),
|
|
287840
288139
|
provRes.headers.get("x-request-id") ?? void 0
|
|
@@ -287851,11 +288150,11 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
|
|
|
287851
288150
|
}
|
|
287852
288151
|
process.exit(1);
|
|
287853
288152
|
}
|
|
287854
|
-
const parsedProv =
|
|
288153
|
+
const parsedProv = import_wire9.provisionKeyResponseSchema.safeParse(
|
|
287855
288154
|
await provRes.json().catch(() => null)
|
|
287856
288155
|
);
|
|
287857
288156
|
if (!parsedProv.success) {
|
|
287858
|
-
|
|
288157
|
+
mint.stop("Could not provision a key.");
|
|
287859
288158
|
M2.error("The key handoff returned something this version does not recognize.");
|
|
287860
288159
|
M2.error(`Try again, or upgrade with ${import_picocolors21.default.bold("npm i -g @abloatai/ablo")}.`);
|
|
287861
288160
|
process.exit(1);
|
|
@@ -287880,7 +288179,7 @@ ${import_picocolors21.default.dim(url)}`, "Approve in your browser");
|
|
|
287880
288179
|
},
|
|
287881
288180
|
{ mode: "sandbox", activeProject: prov.project ?? void 0 }
|
|
287882
288181
|
);
|
|
287883
|
-
|
|
288182
|
+
mint.stop(`Saved project credential to ${path}`);
|
|
287884
288183
|
const orgLabel = prov.organizationSlug ? ` to ${import_picocolors21.default.bold(prov.organizationSlug)}` : "";
|
|
287885
288184
|
const where = prov.project ? ` ${import_picocolors21.default.dim(`(project ${prov.project.slug})`)}` : "";
|
|
287886
288185
|
Se(
|
|
@@ -287897,10 +288196,10 @@ function logout() {
|
|
|
287897
288196
|
} else {
|
|
287898
288197
|
console.log(` ${import_picocolors21.default.dim("\u25CB")} Not logged in \u2014 nothing to remove.`);
|
|
287899
288198
|
}
|
|
287900
|
-
if (process.env.
|
|
288199
|
+
if (process.env.ABLO_API_KEY?.startsWith("mk_")) {
|
|
287901
288200
|
console.log(
|
|
287902
288201
|
import_picocolors21.default.dim(
|
|
287903
|
-
` Note: ${import_picocolors21.default.bold("
|
|
288202
|
+
` Note: ${import_picocolors21.default.bold("ABLO_API_KEY")} still contains an ${import_picocolors21.default.bold("mk_")} credential in this shell and takes precedence.`
|
|
287904
288203
|
)
|
|
287905
288204
|
);
|
|
287906
288205
|
}
|
|
@@ -287916,7 +288215,6 @@ init_config();
|
|
|
287916
288215
|
init_target();
|
|
287917
288216
|
init_theme();
|
|
287918
288217
|
init_controlPlane();
|
|
287919
|
-
var import_schema8 = require("@abloatai/transaction/coordination/schema");
|
|
287920
288218
|
init_readiness();
|
|
287921
288219
|
function expiryLabel(iso) {
|
|
287922
288220
|
const ms = Date.parse(iso) - Date.now();
|
|
@@ -287939,13 +288237,6 @@ async function ping2(apiUrl3) {
|
|
|
287939
288237
|
clearTimeout(t);
|
|
287940
288238
|
}
|
|
287941
288239
|
}
|
|
287942
|
-
function formatConflict(conflict) {
|
|
287943
|
-
if (!conflict) return "";
|
|
287944
|
-
const parts = import_schema8.participantKindSchema.options.flatMap(
|
|
287945
|
-
(k3) => conflict[k3] ? [`${k3}:${conflict[k3]}`] : []
|
|
287946
|
-
);
|
|
287947
|
-
return parts.length ? `{${parts.join(",")}}` : "";
|
|
287948
|
-
}
|
|
287949
288240
|
function printTargetLines(target, localProject, storedOrganizationId, storedOrganizationSlug) {
|
|
287950
288241
|
const confirmed = target?.confirmed ?? null;
|
|
287951
288242
|
const org = confirmed?.organizationId ?? storedOrganizationId;
|
|
@@ -288166,9 +288457,7 @@ async function status(args = []) {
|
|
|
288166
288457
|
);
|
|
288167
288458
|
for (const m2 of pushed.models) {
|
|
288168
288459
|
const tn = m2.typename === m2.key ? import_picocolors22.default.dim(`typename=${m2.typename}`) : import_picocolors22.default.yellow(`typename=${m2.typename}`);
|
|
288169
|
-
|
|
288170
|
-
const conflictStr2 = conflict ? ` ${import_picocolors22.default.dim(`conflict=${conflict}`)}` : "";
|
|
288171
|
-
console.log(` ${import_picocolors22.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}${conflictStr2}`);
|
|
288460
|
+
console.log(` ${import_picocolors22.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}`);
|
|
288172
288461
|
}
|
|
288173
288462
|
} else if (pushed && !pushed.active) {
|
|
288174
288463
|
console.log(
|
|
@@ -288210,8 +288499,8 @@ async function status(args = []) {
|
|
|
288210
288499
|
|
|
288211
288500
|
// src/logs.ts
|
|
288212
288501
|
init_cjs_shims();
|
|
288213
|
-
var
|
|
288214
|
-
var
|
|
288502
|
+
var import_errors20 = require("@abloatai/transaction/errors");
|
|
288503
|
+
var import_wire10 = require("@abloatai/transaction/wire");
|
|
288215
288504
|
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
288216
288505
|
init_config();
|
|
288217
288506
|
init_theme();
|
|
@@ -288252,12 +288541,12 @@ function parseLogsArgs(argv) {
|
|
|
288252
288541
|
args.json = true;
|
|
288253
288542
|
break;
|
|
288254
288543
|
case "--mode":
|
|
288255
|
-
throw new
|
|
288544
|
+
throw new import_errors20.AbloValidationError(
|
|
288256
288545
|
"--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
|
|
288257
288546
|
{ code: "cli_invalid_arguments" }
|
|
288258
288547
|
);
|
|
288259
288548
|
default:
|
|
288260
|
-
throw new
|
|
288549
|
+
throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
288261
288550
|
}
|
|
288262
288551
|
}
|
|
288263
288552
|
return args;
|
|
@@ -288322,7 +288611,7 @@ async function logs(argv) {
|
|
|
288322
288611
|
const json = await res.json();
|
|
288323
288612
|
return {
|
|
288324
288613
|
events: json.data ?? json.events ?? [],
|
|
288325
|
-
cursor: json.next_cursor ?? (json.cursor != null ? (0,
|
|
288614
|
+
cursor: json.next_cursor ?? (json.cursor != null ? (0, import_wire10.formatFeedCursor)({ log: json.cursor, claims: 0 }) : (0, import_wire10.formatFeedCursor)(import_wire10.FEED_CURSOR_START))
|
|
288326
288615
|
};
|
|
288327
288616
|
}
|
|
288328
288617
|
if (!args.json) {
|
|
@@ -288354,9 +288643,9 @@ async function logs(argv) {
|
|
|
288354
288643
|
});
|
|
288355
288644
|
if (!page) continue;
|
|
288356
288645
|
for (const e2 of page.events) render2(e2, args.json);
|
|
288357
|
-
const prev = (0,
|
|
288358
|
-
const next = (0,
|
|
288359
|
-
if (prev && next && (0,
|
|
288646
|
+
const prev = (0, import_wire10.parseFeedCursor)(cursor);
|
|
288647
|
+
const next = (0, import_wire10.parseFeedCursor)(page.cursor);
|
|
288648
|
+
if (prev && next && (0, import_wire10.feedCursorAdvanced)(prev, next)) cursor = page.cursor;
|
|
288360
288649
|
}
|
|
288361
288650
|
}
|
|
288362
288651
|
|
|
@@ -288536,10 +288825,10 @@ async function webhooks(argv) {
|
|
|
288536
288825
|
|
|
288537
288826
|
// src/check.ts
|
|
288538
288827
|
init_cjs_shims();
|
|
288539
|
-
var
|
|
288828
|
+
var import_errors21 = require("@abloatai/transaction/errors");
|
|
288540
288829
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
288541
288830
|
init_src();
|
|
288542
|
-
var
|
|
288831
|
+
var import_schema8 = require("@abloatai/transaction/schema");
|
|
288543
288832
|
init_push();
|
|
288544
288833
|
|
|
288545
288834
|
// src/schemaIr.ts
|
|
@@ -288614,14 +288903,15 @@ function emitSchemaSource(schema, importPath) {
|
|
|
288614
288903
|
|
|
288615
288904
|
// src/schemaSource.ts
|
|
288616
288905
|
init_cjs_shims();
|
|
288906
|
+
var import_schema7 = require("@abloatai/transaction/schema");
|
|
288617
288907
|
var TENANCY_COLUMN = "organization_id";
|
|
288618
|
-
var BASE_FIELDS = /* @__PURE__ */ new Set([
|
|
288908
|
+
var BASE_FIELDS = /* @__PURE__ */ new Set([
|
|
288909
|
+
...import_schema7.BASE_FIELDS,
|
|
288910
|
+
"organizationId"
|
|
288911
|
+
]);
|
|
288619
288912
|
var BASE_COLUMNS = /* @__PURE__ */ new Set([
|
|
288620
|
-
|
|
288621
|
-
|
|
288622
|
-
"created_by",
|
|
288623
|
-
"created_at",
|
|
288624
|
-
"updated_at"
|
|
288913
|
+
...import_schema7.BASE_FIELDS.map(camelToSnake),
|
|
288914
|
+
TENANCY_COLUMN
|
|
288625
288915
|
]);
|
|
288626
288916
|
function fieldNameForColumn(column) {
|
|
288627
288917
|
const camel2 = column.replace(/_([a-z0-9])/g, (_3, c) => c.toUpperCase());
|
|
@@ -288684,7 +288974,7 @@ function parseCheckArgs(argv) {
|
|
|
288684
288974
|
appSchema = argv[++i] ?? appSchema;
|
|
288685
288975
|
break;
|
|
288686
288976
|
default:
|
|
288687
|
-
throw new
|
|
288977
|
+
throw new import_errors21.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
288688
288978
|
}
|
|
288689
288979
|
}
|
|
288690
288980
|
return { schemaPath, exportName, appSchema };
|
|
@@ -288766,7 +289056,10 @@ async function check(argv) {
|
|
|
288766
289056
|
process.exit(1);
|
|
288767
289057
|
}
|
|
288768
289058
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
288769
|
-
const schemaJson = JSON.parse((0,
|
|
289059
|
+
const schemaJson = JSON.parse((0, import_schema8.serializeSchema)(schema));
|
|
289060
|
+
const accessFindings = new Map(
|
|
289061
|
+
(0, import_schema8.auditSchemaAccessPolicies)(schemaJson).map((finding) => [finding.model, finding])
|
|
289062
|
+
);
|
|
288770
289063
|
console.log(`
|
|
288771
289064
|
${brand("ablo")} ${import_picocolors25.default.dim("check")} ${import_picocolors25.default.dim(`schema "${args.appSchema}"`)}
|
|
288772
289065
|
`);
|
|
@@ -288807,8 +289100,14 @@ async function check(argv) {
|
|
|
288807
289100
|
}
|
|
288808
289101
|
const problems = [];
|
|
288809
289102
|
const warns = [];
|
|
289103
|
+
const accessFinding = accessFindings.get(key);
|
|
289104
|
+
if (accessFinding) {
|
|
289105
|
+
problems.push(
|
|
289106
|
+
`[${accessFinding.code}] ${accessFinding.message} Fix: ${accessFinding.fix}`
|
|
289107
|
+
);
|
|
289108
|
+
}
|
|
288810
289109
|
if (!present.has("id")) problems.push('missing primary key "id"');
|
|
288811
|
-
const orgCol = (0,
|
|
289110
|
+
const orgCol = (0, import_schema8.tenancyColumn)((0, import_schema8.resolveTenancy)(model));
|
|
288812
289111
|
if (orgCol && !present.has(orgCol)) {
|
|
288813
289112
|
problems.push(
|
|
288814
289113
|
`missing "${orgCol}" \u2014 Ablo isolates tenants (RLS) and routes realtime by it, so a table without it has no safe boundary. Add the column, or use a Data Source endpoint.`
|
|
@@ -288858,9 +289157,244 @@ async function check(argv) {
|
|
|
288858
289157
|
process.exit(errors > 0 ? 1 : 0);
|
|
288859
289158
|
}
|
|
288860
289159
|
|
|
288861
|
-
// src/
|
|
289160
|
+
// src/claims.ts
|
|
288862
289161
|
init_cjs_shims();
|
|
289162
|
+
var import_node_child_process3 = require("child_process");
|
|
288863
289163
|
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
289164
|
+
var import_contract = require("@abloatai/transaction/claims/contract");
|
|
289165
|
+
var import_routes = require("@abloatai/transaction/claims/routes");
|
|
289166
|
+
init_controlPlane();
|
|
289167
|
+
init_config();
|
|
289168
|
+
function requireRuntimeKey() {
|
|
289169
|
+
const { key } = resolveRuntimeApiKey();
|
|
289170
|
+
if (!key) {
|
|
289171
|
+
console.error(
|
|
289172
|
+
import_picocolors26.default.red(" No runtime credential.") + import_picocolors26.default.dim(
|
|
289173
|
+
` Run ${import_picocolors26.default.bold("npx ablo login")}, or set ${import_picocolors26.default.bold("ABLO_API_KEY")} to a runtime key.`
|
|
289174
|
+
)
|
|
289175
|
+
);
|
|
289176
|
+
process.exit(1);
|
|
289177
|
+
}
|
|
289178
|
+
return key;
|
|
289179
|
+
}
|
|
289180
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set(["--ttl", "--description", "--actor"]);
|
|
289181
|
+
function flagValue(argv, name) {
|
|
289182
|
+
const at = argv.indexOf(`--${name}`);
|
|
289183
|
+
return at === -1 ? void 0 : argv[at + 1];
|
|
289184
|
+
}
|
|
289185
|
+
function parseFlags(argv) {
|
|
289186
|
+
return {
|
|
289187
|
+
json: argv.includes("--json") || process.env.ABLO_JSON === "1",
|
|
289188
|
+
queue: argv.includes("--queue"),
|
|
289189
|
+
ttl: flagValue(argv, "ttl"),
|
|
289190
|
+
description: flagValue(argv, "description"),
|
|
289191
|
+
actor: flagValue(argv, "actor")
|
|
289192
|
+
};
|
|
289193
|
+
}
|
|
289194
|
+
function splitAtCommand(argv) {
|
|
289195
|
+
const at = argv.indexOf("--");
|
|
289196
|
+
return at === -1 ? { args: argv, command: [] } : { args: argv.slice(0, at), command: argv.slice(at + 1) };
|
|
289197
|
+
}
|
|
289198
|
+
function positionals(args) {
|
|
289199
|
+
const out = [];
|
|
289200
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
289201
|
+
const arg = args[i];
|
|
289202
|
+
if (arg === void 0) continue;
|
|
289203
|
+
if (VALUE_FLAGS.has(arg)) {
|
|
289204
|
+
i += 1;
|
|
289205
|
+
continue;
|
|
289206
|
+
}
|
|
289207
|
+
if (arg.startsWith("-")) continue;
|
|
289208
|
+
out.push(arg);
|
|
289209
|
+
}
|
|
289210
|
+
return out;
|
|
289211
|
+
}
|
|
289212
|
+
async function acquireClaim(model, id, flags, apiKey) {
|
|
289213
|
+
return requestControlPlane({
|
|
289214
|
+
path: (0, import_routes.claimOnModelPath)({ model, id }),
|
|
289215
|
+
method: "POST",
|
|
289216
|
+
apiKey,
|
|
289217
|
+
body: {
|
|
289218
|
+
...flags.ttl !== void 0 ? { ttl: flags.ttl } : {},
|
|
289219
|
+
...flags.description !== void 0 ? { description: flags.description } : {},
|
|
289220
|
+
...flags.queue ? { queue: true } : {}
|
|
289221
|
+
},
|
|
289222
|
+
responseSchema: import_contract.claimAcquireResponseSchema
|
|
289223
|
+
});
|
|
289224
|
+
}
|
|
289225
|
+
async function releaseClaim(model, id, apiKey) {
|
|
289226
|
+
const reply = await requestControlPlane({
|
|
289227
|
+
path: (0, import_routes.claimOnModelPath)({ model, id }),
|
|
289228
|
+
method: "DELETE",
|
|
289229
|
+
apiKey,
|
|
289230
|
+
responseSchema: import_contract.claimReleaseReplySchema
|
|
289231
|
+
});
|
|
289232
|
+
return reply.released;
|
|
289233
|
+
}
|
|
289234
|
+
async function beat(model, id, ttl, apiKey) {
|
|
289235
|
+
await requestControlPlane({
|
|
289236
|
+
path: (0, import_routes.claimHeartbeatOnModelPath)({ model, id }),
|
|
289237
|
+
method: "POST",
|
|
289238
|
+
apiKey,
|
|
289239
|
+
body: ttl !== void 0 ? { ttl } : {},
|
|
289240
|
+
responseSchema: import_contract.claimHeartbeatReplySchema
|
|
289241
|
+
});
|
|
289242
|
+
}
|
|
289243
|
+
async function pollClaim(claimId, apiKey) {
|
|
289244
|
+
return requestControlPlane({
|
|
289245
|
+
path: (0, import_routes.claimByIdPath)(claimId),
|
|
289246
|
+
apiKey,
|
|
289247
|
+
responseSchema: import_contract.claimStateSchema
|
|
289248
|
+
});
|
|
289249
|
+
}
|
|
289250
|
+
async function waitForGrant(claimId, ttl, apiKey) {
|
|
289251
|
+
const everyMs = Math.max(1e3, Math.floor((0, import_contract.claimTtlMs)(ttl) / 4));
|
|
289252
|
+
for (; ; ) {
|
|
289253
|
+
await new Promise((resolve11) => setTimeout(resolve11, everyMs));
|
|
289254
|
+
const state = await pollClaim(claimId, apiKey);
|
|
289255
|
+
if (state.status === "active") return;
|
|
289256
|
+
if (state.status !== "queued") {
|
|
289257
|
+
throw new Error(`the wait ended without the lease (${state.status})`);
|
|
289258
|
+
}
|
|
289259
|
+
}
|
|
289260
|
+
}
|
|
289261
|
+
function describeAcquired(model, id, granted) {
|
|
289262
|
+
if (granted.status === "queued") {
|
|
289263
|
+
const ahead = granted.position;
|
|
289264
|
+
return ` ${import_picocolors26.default.yellow("\xB7")} Waiting for ${import_picocolors26.default.bold(`${model} ${id}`)}. ` + import_picocolors26.default.dim(ahead === 0 ? "Next in line." : `${ahead} ahead of you.`);
|
|
289265
|
+
}
|
|
289266
|
+
return ` ${import_picocolors26.default.green("\u2713")} Holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`;
|
|
289267
|
+
}
|
|
289268
|
+
async function holdWhile(model, id, flags, apiKey, command) {
|
|
289269
|
+
const granted = await acquireClaim(model, id, flags, apiKey);
|
|
289270
|
+
if (granted.status === "queued") {
|
|
289271
|
+
if (!flags.json) console.error(describeAcquired(model, id, granted));
|
|
289272
|
+
await waitForGrant(granted.id, flags.ttl, apiKey);
|
|
289273
|
+
}
|
|
289274
|
+
if (!flags.json) console.error(` ${import_picocolors26.default.green("\u2713")} Holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
|
|
289275
|
+
const everyMs = Math.max(1e3, Math.floor((0, import_contract.claimTtlMs)(flags.ttl) / 3));
|
|
289276
|
+
const timer2 = setInterval(() => {
|
|
289277
|
+
void beat(model, id, flags.ttl, apiKey).catch(() => {
|
|
289278
|
+
});
|
|
289279
|
+
}, everyMs);
|
|
289280
|
+
let released = false;
|
|
289281
|
+
const giveBack = async () => {
|
|
289282
|
+
if (released) return;
|
|
289283
|
+
released = true;
|
|
289284
|
+
clearInterval(timer2);
|
|
289285
|
+
try {
|
|
289286
|
+
await releaseClaim(model, id, apiKey);
|
|
289287
|
+
} catch {
|
|
289288
|
+
}
|
|
289289
|
+
};
|
|
289290
|
+
const [head, ...rest] = command;
|
|
289291
|
+
if (head === void 0) {
|
|
289292
|
+
await giveBack();
|
|
289293
|
+
throw new Error("no command was given after `--`");
|
|
289294
|
+
}
|
|
289295
|
+
const code = await new Promise((resolve11) => {
|
|
289296
|
+
const child = (0, import_node_child_process3.spawn)(head, rest, { stdio: "inherit" });
|
|
289297
|
+
const forward = (signal) => {
|
|
289298
|
+
child.kill(signal);
|
|
289299
|
+
};
|
|
289300
|
+
process.on("SIGINT", forward);
|
|
289301
|
+
process.on("SIGTERM", forward);
|
|
289302
|
+
child.on("error", () => {
|
|
289303
|
+
process.off("SIGINT", forward);
|
|
289304
|
+
process.off("SIGTERM", forward);
|
|
289305
|
+
resolve11(127);
|
|
289306
|
+
});
|
|
289307
|
+
child.on("close", (status2) => {
|
|
289308
|
+
process.off("SIGINT", forward);
|
|
289309
|
+
process.off("SIGTERM", forward);
|
|
289310
|
+
resolve11(status2 ?? 1);
|
|
289311
|
+
});
|
|
289312
|
+
});
|
|
289313
|
+
await giveBack();
|
|
289314
|
+
if (!flags.json) console.error(` ${import_picocolors26.default.dim("\xB7")} ${import_picocolors26.default.dim(`Released ${model} ${id}.`)}`);
|
|
289315
|
+
return code;
|
|
289316
|
+
}
|
|
289317
|
+
function renderList(rows) {
|
|
289318
|
+
if (rows.length === 0) {
|
|
289319
|
+
console.log(` ${import_picocolors26.default.dim("Nothing is held right now.")}`);
|
|
289320
|
+
return;
|
|
289321
|
+
}
|
|
289322
|
+
const held = rows.filter((row) => row.status !== "queued").length;
|
|
289323
|
+
const waiting = rows.length - held;
|
|
289324
|
+
console.log();
|
|
289325
|
+
for (const row of rows) {
|
|
289326
|
+
const where = `${row.target.model} ${row.target.id}`;
|
|
289327
|
+
const state = row.status === "queued" ? import_picocolors26.default.yellow(row.position === void 0 ? "waiting" : `waiting (${row.position} ahead)`) : import_picocolors26.default.green("held");
|
|
289328
|
+
console.log(
|
|
289329
|
+
` ${import_picocolors26.default.bold(where.padEnd(28))} ${state.padEnd(28)} ${import_picocolors26.default.dim(row.description ?? row.actor)}`
|
|
289330
|
+
);
|
|
289331
|
+
}
|
|
289332
|
+
console.log();
|
|
289333
|
+
console.log(import_picocolors26.default.dim(` ${held} held, ${waiting} waiting.`));
|
|
289334
|
+
console.log();
|
|
289335
|
+
}
|
|
289336
|
+
async function claims(argv = []) {
|
|
289337
|
+
const { args, command } = splitAtCommand(argv);
|
|
289338
|
+
const flags = parseFlags(args);
|
|
289339
|
+
const [verb, ...rest] = positionals(args);
|
|
289340
|
+
if (verb === void 0 || verb === "help" || args.includes("--help")) {
|
|
289341
|
+
console.log(usageFor("claims"));
|
|
289342
|
+
return;
|
|
289343
|
+
}
|
|
289344
|
+
const apiKey = requireRuntimeKey();
|
|
289345
|
+
if (verb === "list") {
|
|
289346
|
+
const [model2, id2] = rest;
|
|
289347
|
+
const query = new URLSearchParams();
|
|
289348
|
+
if (model2 !== void 0) query.set("model", model2);
|
|
289349
|
+
if (id2 !== void 0) query.set("id", id2);
|
|
289350
|
+
if (flags.actor !== void 0) query.set("actorId", flags.actor);
|
|
289351
|
+
const suffix = query.toString();
|
|
289352
|
+
const page = await requestControlPlane({
|
|
289353
|
+
path: `${import_routes.CLAIM_ROUTES.collection}${suffix ? `?${suffix}` : ""}`,
|
|
289354
|
+
apiKey,
|
|
289355
|
+
responseSchema: import_contract.claimListResponseSchema
|
|
289356
|
+
});
|
|
289357
|
+
if (flags.json) console.log(JSON.stringify(page, null, 2));
|
|
289358
|
+
else renderList(page.data);
|
|
289359
|
+
return;
|
|
289360
|
+
}
|
|
289361
|
+
const [model, id] = rest;
|
|
289362
|
+
if (model === void 0 || id === void 0) {
|
|
289363
|
+
console.error(` ${import_picocolors26.default.red("\u2717")} Name the row: ${import_picocolors26.default.bold(`ablo claims ${verb} <model> <id>`)}.`);
|
|
289364
|
+
process.exitCode = 1;
|
|
289365
|
+
return;
|
|
289366
|
+
}
|
|
289367
|
+
if (verb === "acquire") {
|
|
289368
|
+
if (command.length > 0) {
|
|
289369
|
+
process.exitCode = await holdWhile(model, id, flags, apiKey, command);
|
|
289370
|
+
return;
|
|
289371
|
+
}
|
|
289372
|
+
const granted = await acquireClaim(model, id, flags, apiKey);
|
|
289373
|
+
if (flags.json) console.log(JSON.stringify(granted, null, 2));
|
|
289374
|
+
else console.log(describeAcquired(model, id, granted));
|
|
289375
|
+
return;
|
|
289376
|
+
}
|
|
289377
|
+
if (verb === "release") {
|
|
289378
|
+
const released = await releaseClaim(model, id, apiKey);
|
|
289379
|
+
if (flags.json) console.log(JSON.stringify({ object: "claim_release", released }, null, 2));
|
|
289380
|
+
else if (released) console.log(` ${import_picocolors26.default.green("\u2713")} Released ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
|
|
289381
|
+
else console.log(` ${import_picocolors26.default.dim("\xB7")} ${import_picocolors26.default.dim(`You were not holding ${model} ${id}.`)}`);
|
|
289382
|
+
return;
|
|
289383
|
+
}
|
|
289384
|
+
if (verb === "heartbeat") {
|
|
289385
|
+
await beat(model, id, flags.ttl, apiKey);
|
|
289386
|
+
if (flags.json) console.log(JSON.stringify({ object: "claim_heartbeat", ok: true }, null, 2));
|
|
289387
|
+
else console.log(` ${import_picocolors26.default.green("\u2713")} Still holding ${import_picocolors26.default.bold(`${model} ${id}`)}.`);
|
|
289388
|
+
return;
|
|
289389
|
+
}
|
|
289390
|
+
console.error(` ${import_picocolors26.default.red("\u2717")} Unknown: ${import_picocolors26.default.bold(`ablo claims ${verb}`)}.`);
|
|
289391
|
+
console.error(usageFor("claims"));
|
|
289392
|
+
process.exitCode = 1;
|
|
289393
|
+
}
|
|
289394
|
+
|
|
289395
|
+
// src/upgrade.ts
|
|
289396
|
+
init_cjs_shims();
|
|
289397
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
288864
289398
|
var import_ts_morph = __toESM(require_ts_morph(), 1);
|
|
288865
289399
|
var DEFAULT_GLOBS = ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}", "ablo/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}"];
|
|
288866
289400
|
var VERB_ARGS = {
|
|
@@ -288902,12 +289436,14 @@ function verbRewrite(call, verb) {
|
|
|
288902
289436
|
const args = call.getArguments();
|
|
288903
289437
|
const first = args[0];
|
|
288904
289438
|
if (first === void 0) return null;
|
|
288905
|
-
const calleeText = call.getExpression().getText();
|
|
289439
|
+
const calleeText = verb === "retrieve" ? `${call.getExpression().getText().slice(0, -"retrieve".length)}get` : call.getExpression().getText();
|
|
288906
289440
|
if (verb === "create") {
|
|
288907
289441
|
if (import_ts_morph.Node.isObjectLiteralExpression(first) && hasKey2(first, "data")) return null;
|
|
288908
289442
|
return `${calleeText}({ data: ${first.getText()}${spreadOpts(args[1])} })`;
|
|
288909
289443
|
}
|
|
288910
|
-
if (import_ts_morph.Node.isObjectLiteralExpression(first))
|
|
289444
|
+
if (import_ts_morph.Node.isObjectLiteralExpression(first)) {
|
|
289445
|
+
return verb === "retrieve" ? `${calleeText}(${first.getText()})` : null;
|
|
289446
|
+
}
|
|
288911
289447
|
const keyed = params.map((key, i) => args[i] ? `${key}: ${args[i].getText()}` : null).filter(Boolean);
|
|
288912
289448
|
return `${calleeText}({ ${keyed.join(", ")}${spreadOpts(args[params.length])} })`;
|
|
288913
289449
|
}
|
|
@@ -288923,7 +289459,7 @@ function loadRewrite(call) {
|
|
|
288923
289459
|
if (import_ts_morph.Node.isObjectLiteralExpression(whereVal)) {
|
|
288924
289460
|
const idProp = whereVal.getProperty("id");
|
|
288925
289461
|
if (idProp && whereVal.getProperties().length === 1 && import_ts_morph.Node.isPropertyAssignment(idProp)) {
|
|
288926
|
-
return `${base}.
|
|
289462
|
+
return `${base}.get({ id: ${idProp.getInitializerOrThrow().getText()} })`;
|
|
288927
289463
|
}
|
|
288928
289464
|
}
|
|
288929
289465
|
return `${base}.list({ where: ${whereVal.getText()} })`;
|
|
@@ -288938,7 +289474,7 @@ async function upgrade(argv) {
|
|
|
288938
289474
|
project.addSourceFilesAtPaths(globs.length > 0 ? globs : DEFAULT_GLOBS);
|
|
288939
289475
|
const files = project.getSourceFiles();
|
|
288940
289476
|
if (files.length === 0) {
|
|
288941
|
-
console.log(
|
|
289477
|
+
console.log(import_picocolors27.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
|
|
288942
289478
|
return;
|
|
288943
289479
|
}
|
|
288944
289480
|
const edits = [];
|
|
@@ -288986,7 +289522,7 @@ async function upgrade(argv) {
|
|
|
288986
289522
|
} else if (method === "load") {
|
|
288987
289523
|
const next = loadRewrite(call);
|
|
288988
289524
|
if (next) {
|
|
288989
|
-
record(call, "load\
|
|
289525
|
+
record(call, "load\u2192get/list", (call.getText().split("\n")[0] ?? "").slice(0, 80), next.slice(0, 80));
|
|
288990
289526
|
call.replaceWithText(next);
|
|
288991
289527
|
}
|
|
288992
289528
|
}
|
|
@@ -289012,39 +289548,39 @@ async function upgrade(argv) {
|
|
|
289012
289548
|
const rel = (f) => f.replace(cwd + "/", "");
|
|
289013
289549
|
console.log();
|
|
289014
289550
|
if (edits.length === 0 && manual.length === 0) {
|
|
289015
|
-
console.log(
|
|
289551
|
+
console.log(import_picocolors27.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
|
|
289016
289552
|
return;
|
|
289017
289553
|
}
|
|
289018
289554
|
if (edits.length > 0) {
|
|
289019
|
-
console.log(
|
|
289555
|
+
console.log(import_picocolors27.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
|
|
289020
289556
|
for (const e2 of edits) {
|
|
289021
|
-
console.log(` ${
|
|
289022
|
-
console.log(` ${
|
|
289023
|
-
console.log(` ${
|
|
289557
|
+
console.log(` ${import_picocolors27.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors27.default.cyan(e2.rule)}`);
|
|
289558
|
+
console.log(` ${import_picocolors27.default.red("-")} ${e2.before}`);
|
|
289559
|
+
console.log(` ${import_picocolors27.default.green("+")} ${e2.after}`);
|
|
289024
289560
|
}
|
|
289025
289561
|
}
|
|
289026
289562
|
if (manual.length > 0) {
|
|
289027
289563
|
console.log();
|
|
289028
|
-
console.log(
|
|
289564
|
+
console.log(import_picocolors27.default.bold(import_picocolors27.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
|
|
289029
289565
|
for (const m2 of manual) {
|
|
289030
|
-
console.log(` ${
|
|
289031
|
-
console.log(` ${
|
|
289566
|
+
console.log(` ${import_picocolors27.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors27.default.yellow(m2.rule)}`);
|
|
289567
|
+
console.log(` ${import_picocolors27.default.dim(m2.snippet)}`);
|
|
289032
289568
|
console.log(` \u2192 ${m2.hint}`);
|
|
289033
289569
|
}
|
|
289034
289570
|
}
|
|
289035
289571
|
console.log();
|
|
289036
289572
|
if (write) {
|
|
289037
289573
|
await project.save();
|
|
289038
|
-
console.log(
|
|
289574
|
+
console.log(import_picocolors27.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
|
|
289039
289575
|
} else {
|
|
289040
|
-
console.log(
|
|
289576
|
+
console.log(import_picocolors27.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
|
|
289041
289577
|
}
|
|
289042
289578
|
}
|
|
289043
289579
|
|
|
289044
289580
|
// src/pull.ts
|
|
289045
289581
|
init_cjs_shims();
|
|
289046
|
-
var
|
|
289047
|
-
var
|
|
289582
|
+
var import_errors22 = require("@abloatai/transaction/errors");
|
|
289583
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
289048
289584
|
init_src();
|
|
289049
289585
|
var import_fs10 = require("fs");
|
|
289050
289586
|
init_theme();
|
|
@@ -289072,7 +289608,7 @@ function parsePullArgs(argv) {
|
|
|
289072
289608
|
force = true;
|
|
289073
289609
|
break;
|
|
289074
289610
|
default:
|
|
289075
|
-
throw new
|
|
289611
|
+
throw new import_errors22.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
289076
289612
|
}
|
|
289077
289613
|
}
|
|
289078
289614
|
return { out, appSchema, importPath, force };
|
|
@@ -289142,56 +289678,56 @@ async function pull(argv) {
|
|
|
289142
289678
|
try {
|
|
289143
289679
|
args = parsePullArgs(argv);
|
|
289144
289680
|
} catch (err) {
|
|
289145
|
-
console.error(
|
|
289681
|
+
console.error(import_picocolors28.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
289146
289682
|
process.exit(1);
|
|
289147
289683
|
}
|
|
289148
289684
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
289149
289685
|
if (!dbUrl) {
|
|
289150
289686
|
console.error(
|
|
289151
|
-
|
|
289687
|
+
import_picocolors28.default.red(` No database.`) + import_picocolors28.default.dim(` Set ${import_picocolors28.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
|
|
289152
289688
|
);
|
|
289153
289689
|
process.exit(1);
|
|
289154
289690
|
}
|
|
289155
289691
|
if ((0, import_fs10.existsSync)(args.out) && !args.force) {
|
|
289156
289692
|
console.error(
|
|
289157
|
-
|
|
289693
|
+
import_picocolors28.default.red(` ${args.out} already exists.`) + import_picocolors28.default.dim(` Re-run with ${import_picocolors28.default.bold("--force")} to overwrite.`)
|
|
289158
289694
|
);
|
|
289159
289695
|
process.exit(1);
|
|
289160
289696
|
}
|
|
289161
289697
|
console.log(`
|
|
289162
|
-
${brand("ablo")} ${
|
|
289698
|
+
${brand("ablo")} ${import_picocolors28.default.dim("pull")} ${import_picocolors28.default.dim(`schema "${args.appSchema}"`)}
|
|
289163
289699
|
`);
|
|
289164
289700
|
let result;
|
|
289165
289701
|
try {
|
|
289166
289702
|
result = await buildSchemaSourceFromDb({ dbUrl, appSchema: args.appSchema, importPath: args.importPath });
|
|
289167
289703
|
} catch (err) {
|
|
289168
|
-
console.error(
|
|
289704
|
+
console.error(import_picocolors28.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
|
|
289169
289705
|
process.exit(1);
|
|
289170
289706
|
}
|
|
289171
289707
|
if (result.models.length === 0) {
|
|
289172
289708
|
console.error(
|
|
289173
|
-
|
|
289709
|
+
import_picocolors28.default.yellow(` No adoptable tables found`) + import_picocolors28.default.dim(` (a model needs an ${import_picocolors28.default.bold("id")} + ${import_picocolors28.default.bold("organization_id")} column).`)
|
|
289174
289710
|
);
|
|
289175
289711
|
process.exit(1);
|
|
289176
289712
|
}
|
|
289177
289713
|
(0, import_fs10.writeFileSync)(args.out, result.source);
|
|
289178
|
-
console.log(` ${
|
|
289179
|
-
console.log(` ${
|
|
289714
|
+
console.log(` ${import_picocolors28.default.green("\u2713")} wrote ${import_picocolors28.default.bold(args.out)} ${import_picocolors28.default.dim(`(${result.models.length} models)`)}`);
|
|
289715
|
+
console.log(` ${import_picocolors28.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
289180
289716
|
if (result.skipped.length > 0) {
|
|
289181
|
-
console.log(` ${
|
|
289182
|
-
for (const s of result.skipped) console.log(` ${
|
|
289717
|
+
console.log(` ${import_picocolors28.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
|
|
289718
|
+
for (const s of result.skipped) console.log(` ${import_picocolors28.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
289183
289719
|
}
|
|
289184
289720
|
console.log(
|
|
289185
289721
|
`
|
|
289186
|
-
${
|
|
289722
|
+
${import_picocolors28.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors28.default.bold("ablo check")}.
|
|
289187
289723
|
`
|
|
289188
289724
|
);
|
|
289189
289725
|
}
|
|
289190
289726
|
|
|
289191
289727
|
// src/prismaPull.ts
|
|
289192
289728
|
init_cjs_shims();
|
|
289193
|
-
var
|
|
289194
|
-
var
|
|
289729
|
+
var import_errors23 = require("@abloatai/transaction/errors");
|
|
289730
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
289195
289731
|
var import_fs11 = require("fs");
|
|
289196
289732
|
init_theme();
|
|
289197
289733
|
var DEFAULT_SCHEMA = "prisma/schema.prisma";
|
|
@@ -289388,7 +289924,7 @@ function parsePrismaPullArgs(argv) {
|
|
|
289388
289924
|
force = true;
|
|
289389
289925
|
break;
|
|
289390
289926
|
default:
|
|
289391
|
-
if (arg.startsWith("--")) throw new
|
|
289927
|
+
if (arg.startsWith("--")) throw new import_errors23.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
289392
289928
|
schema = arg;
|
|
289393
289929
|
}
|
|
289394
289930
|
}
|
|
@@ -289399,56 +289935,56 @@ async function prismaPull(argv) {
|
|
|
289399
289935
|
try {
|
|
289400
289936
|
args = parsePrismaPullArgs(argv);
|
|
289401
289937
|
} catch (err) {
|
|
289402
|
-
console.error(
|
|
289938
|
+
console.error(import_picocolors29.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
289403
289939
|
process.exit(1);
|
|
289404
289940
|
}
|
|
289405
289941
|
if (!(0, import_fs11.existsSync)(args.schema)) {
|
|
289406
289942
|
console.error(
|
|
289407
|
-
|
|
289943
|
+
import_picocolors29.default.red(` No Prisma schema at ${import_picocolors29.default.bold(args.schema)}.`) + import_picocolors29.default.dim(` Pass a path: ${import_picocolors29.default.bold("ablo pull prisma <path>")}.`)
|
|
289408
289944
|
);
|
|
289409
289945
|
process.exit(1);
|
|
289410
289946
|
}
|
|
289411
289947
|
if ((0, import_fs11.existsSync)(args.out) && !args.force) {
|
|
289412
289948
|
console.error(
|
|
289413
|
-
|
|
289949
|
+
import_picocolors29.default.red(` ${args.out} already exists.`) + import_picocolors29.default.dim(` Re-run with ${import_picocolors29.default.bold("--force")} to overwrite.`)
|
|
289414
289950
|
);
|
|
289415
289951
|
process.exit(1);
|
|
289416
289952
|
}
|
|
289417
289953
|
console.log(`
|
|
289418
|
-
${brand("ablo")} ${
|
|
289954
|
+
${brand("ablo")} ${import_picocolors29.default.dim("pull prisma")} ${import_picocolors29.default.dim(args.schema)}
|
|
289419
289955
|
`);
|
|
289420
289956
|
let result;
|
|
289421
289957
|
try {
|
|
289422
289958
|
const src = (0, import_fs11.readFileSync)(args.schema, "utf8");
|
|
289423
289959
|
result = buildSchemaSourceFromPrisma({ src, importPath: args.importPath });
|
|
289424
289960
|
} catch (err) {
|
|
289425
|
-
console.error(
|
|
289961
|
+
console.error(import_picocolors29.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
|
|
289426
289962
|
process.exit(1);
|
|
289427
289963
|
}
|
|
289428
289964
|
if (result.models.length === 0) {
|
|
289429
289965
|
console.error(
|
|
289430
|
-
|
|
289966
|
+
import_picocolors29.default.yellow(` No adoptable models found`) + import_picocolors29.default.dim(` (a model needs an ${import_picocolors29.default.bold("id")} + ${import_picocolors29.default.bold("organizationId")} / ${import_picocolors29.default.bold("organization_id")}).`)
|
|
289431
289967
|
);
|
|
289432
289968
|
process.exit(1);
|
|
289433
289969
|
}
|
|
289434
289970
|
(0, import_fs11.writeFileSync)(args.out, result.source);
|
|
289435
|
-
console.log(` ${
|
|
289436
|
-
console.log(` ${
|
|
289971
|
+
console.log(` ${import_picocolors29.default.green("\u2713")} wrote ${import_picocolors29.default.bold(args.out)} ${import_picocolors29.default.dim(`(${result.models.length} models)`)}`);
|
|
289972
|
+
console.log(` ${import_picocolors29.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
289437
289973
|
if (result.skipped.length > 0) {
|
|
289438
|
-
console.log(` ${
|
|
289439
|
-
for (const s of result.skipped) console.log(` ${
|
|
289974
|
+
console.log(` ${import_picocolors29.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
|
|
289975
|
+
for (const s of result.skipped) console.log(` ${import_picocolors29.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
289440
289976
|
}
|
|
289441
289977
|
console.log(
|
|
289442
289978
|
`
|
|
289443
|
-
${
|
|
289979
|
+
${import_picocolors29.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors29.default.bold("ablo check")}.
|
|
289444
289980
|
`
|
|
289445
289981
|
);
|
|
289446
289982
|
}
|
|
289447
289983
|
|
|
289448
289984
|
// src/drizzlePull.ts
|
|
289449
289985
|
init_cjs_shims();
|
|
289450
|
-
var
|
|
289451
|
-
var
|
|
289986
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
289987
|
+
var import_errors24 = require("@abloatai/transaction/errors");
|
|
289452
289988
|
var import_fs12 = require("fs");
|
|
289453
289989
|
var import_path7 = require("path");
|
|
289454
289990
|
init_theme();
|
|
@@ -289555,7 +290091,7 @@ function parseDrizzlePullArgs(argv) {
|
|
|
289555
290091
|
force = true;
|
|
289556
290092
|
break;
|
|
289557
290093
|
default:
|
|
289558
|
-
if (arg.startsWith("--")) throw new
|
|
290094
|
+
if (arg.startsWith("--")) throw new import_errors24.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
289559
290095
|
schema = arg;
|
|
289560
290096
|
}
|
|
289561
290097
|
}
|
|
@@ -289572,27 +290108,27 @@ async function drizzlePull(argv) {
|
|
|
289572
290108
|
try {
|
|
289573
290109
|
args = parseDrizzlePullArgs(argv);
|
|
289574
290110
|
} catch (err) {
|
|
289575
|
-
console.error(
|
|
290111
|
+
console.error(import_picocolors30.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
289576
290112
|
process.exit(1);
|
|
289577
290113
|
}
|
|
289578
290114
|
if (!args.schema) {
|
|
289579
290115
|
console.error(
|
|
289580
|
-
|
|
290116
|
+
import_picocolors30.default.red(` No Drizzle schema given.`) + import_picocolors30.default.dim(` Pass the module: ${import_picocolors30.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
|
|
289581
290117
|
);
|
|
289582
290118
|
process.exit(1);
|
|
289583
290119
|
}
|
|
289584
290120
|
if (!(0, import_fs12.existsSync)(args.schema)) {
|
|
289585
|
-
console.error(
|
|
290121
|
+
console.error(import_picocolors30.default.red(` No file at ${import_picocolors30.default.bold(args.schema)}.`));
|
|
289586
290122
|
process.exit(1);
|
|
289587
290123
|
}
|
|
289588
290124
|
if ((0, import_fs12.existsSync)(args.out) && !args.force) {
|
|
289589
290125
|
console.error(
|
|
289590
|
-
|
|
290126
|
+
import_picocolors30.default.red(` ${args.out} already exists.`) + import_picocolors30.default.dim(` Re-run with ${import_picocolors30.default.bold("--force")} to overwrite.`)
|
|
289591
290127
|
);
|
|
289592
290128
|
process.exit(1);
|
|
289593
290129
|
}
|
|
289594
290130
|
console.log(`
|
|
289595
|
-
${brand("ablo")} ${
|
|
290131
|
+
${brand("ablo")} ${import_picocolors30.default.dim("pull drizzle")} ${import_picocolors30.default.dim(args.schema)}
|
|
289596
290132
|
`);
|
|
289597
290133
|
let result;
|
|
289598
290134
|
try {
|
|
@@ -289600,26 +290136,26 @@ async function drizzlePull(argv) {
|
|
|
289600
290136
|
result = await buildSchemaSourceFromDrizzle({ mod, importPath: args.importPath });
|
|
289601
290137
|
} catch (err) {
|
|
289602
290138
|
const msg = err instanceof Error ? err.message : String(err);
|
|
289603
|
-
const hint = msg.includes("Cannot find package 'drizzle-orm'") ?
|
|
289604
|
-
console.error(
|
|
290139
|
+
const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors30.default.dim(` (install ${import_picocolors30.default.bold("drizzle-orm")} in this project)`) : "";
|
|
290140
|
+
console.error(import_picocolors30.default.red(` Couldn't load the schema: ${msg}`) + hint);
|
|
289605
290141
|
process.exit(1);
|
|
289606
290142
|
}
|
|
289607
290143
|
if (result.models.length === 0) {
|
|
289608
290144
|
console.error(
|
|
289609
|
-
|
|
290145
|
+
import_picocolors30.default.yellow(` No adoptable tables found`) + import_picocolors30.default.dim(` (a table needs an ${import_picocolors30.default.bold("id")} + ${import_picocolors30.default.bold("organization_id")} column).`)
|
|
289610
290146
|
);
|
|
289611
290147
|
process.exit(1);
|
|
289612
290148
|
}
|
|
289613
290149
|
(0, import_fs12.writeFileSync)(args.out, result.source);
|
|
289614
|
-
console.log(` ${
|
|
289615
|
-
console.log(` ${
|
|
290150
|
+
console.log(` ${import_picocolors30.default.green("\u2713")} wrote ${import_picocolors30.default.bold(args.out)} ${import_picocolors30.default.dim(`(${result.models.length} models)`)}`);
|
|
290151
|
+
console.log(` ${import_picocolors30.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
289616
290152
|
if (result.skipped.length > 0) {
|
|
289617
|
-
console.log(` ${
|
|
289618
|
-
for (const s of result.skipped) console.log(` ${
|
|
290153
|
+
console.log(` ${import_picocolors30.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
|
|
290154
|
+
for (const s of result.skipped) console.log(` ${import_picocolors30.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
289619
290155
|
}
|
|
289620
290156
|
console.log(
|
|
289621
290157
|
`
|
|
289622
|
-
${
|
|
290158
|
+
${import_picocolors30.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors30.default.bold("ablo check")}.
|
|
289623
290159
|
`
|
|
289624
290160
|
);
|
|
289625
290161
|
}
|
|
@@ -289632,8 +290168,8 @@ init_telemetry();
|
|
|
289632
290168
|
|
|
289633
290169
|
// src/init/options.ts
|
|
289634
290170
|
init_cjs_shims();
|
|
289635
|
-
var
|
|
289636
|
-
var
|
|
290171
|
+
var import_node_fs5 = require("fs");
|
|
290172
|
+
var import_node_path4 = require("path");
|
|
289637
290173
|
var INIT_FRAMEWORKS = ["nextjs", "vite", "remix", "vanilla"];
|
|
289638
290174
|
var INIT_AUTHS = [
|
|
289639
290175
|
"apikey",
|
|
@@ -289672,7 +290208,7 @@ function parseInitArgs(args) {
|
|
|
289672
290208
|
function detectOrm(override, root = process.cwd()) {
|
|
289673
290209
|
if (override === "prisma" || override === "drizzle" || override === "none") return override;
|
|
289674
290210
|
try {
|
|
289675
|
-
const pkg = JSON.parse((0,
|
|
290211
|
+
const pkg = JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path4.resolve)(root, "package.json"), "utf8"));
|
|
289676
290212
|
const dependencies = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
289677
290213
|
if (dependencies["@prisma/client"] || dependencies.prisma) return "prisma";
|
|
289678
290214
|
if (dependencies["drizzle-orm"]) return "drizzle";
|
|
@@ -289681,24 +290217,24 @@ function detectOrm(override, root = process.cwd()) {
|
|
|
289681
290217
|
return "none";
|
|
289682
290218
|
}
|
|
289683
290219
|
function detectNextLayout(root = process.cwd()) {
|
|
289684
|
-
const useSrc = (0,
|
|
289685
|
-
return useSrc ? { appBase: (0,
|
|
290220
|
+
const useSrc = (0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "src", "app")) || !(0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "app")) && (0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "src"));
|
|
290221
|
+
return useSrc ? { appBase: (0, import_node_path4.join)("src", "app"), aliasBase: "src" } : { appBase: "app", aliasBase: "." };
|
|
289686
290222
|
}
|
|
289687
290223
|
function detectPackageManager(root = process.cwd()) {
|
|
289688
|
-
if ((0,
|
|
289689
|
-
if ((0,
|
|
289690
|
-
if ((0,
|
|
290224
|
+
if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
290225
|
+
if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "yarn.lock"))) return "yarn";
|
|
290226
|
+
if ((0, import_node_fs5.existsSync)((0, import_node_path4.resolve)(root, "bun.lockb"))) return "bun";
|
|
289691
290227
|
return "npm";
|
|
289692
290228
|
}
|
|
289693
290229
|
|
|
289694
290230
|
// src/init/run.ts
|
|
289695
290231
|
init_cjs_shims();
|
|
289696
|
-
var
|
|
289697
|
-
var
|
|
289698
|
-
var
|
|
290232
|
+
var import_node_child_process4 = require("child_process");
|
|
290233
|
+
var import_node_fs7 = require("fs");
|
|
290234
|
+
var import_node_path6 = require("path");
|
|
289699
290235
|
init_dist2();
|
|
289700
|
-
var
|
|
289701
|
-
var
|
|
290236
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
290237
|
+
var import_errors25 = require("@abloatai/transaction/errors");
|
|
289702
290238
|
init_dbRole();
|
|
289703
290239
|
init_config();
|
|
289704
290240
|
init_projects();
|
|
@@ -289751,8 +290287,21 @@ export async function POST(request: Request): Promise<Response> {
|
|
|
289751
290287
|
);
|
|
289752
290288
|
}
|
|
289753
290289
|
|
|
290290
|
+
const authorizedScope = await authorizeActiveWorkspace(user.id);
|
|
290291
|
+
if (!authorizedScope) {
|
|
290292
|
+
return Response.json(
|
|
290293
|
+
credentialEndpointErrorSchema.parse({
|
|
290294
|
+
error: { code: 'policy_denied', message: 'Workspace membership is stale or revoked' },
|
|
290295
|
+
}),
|
|
290296
|
+
{ status: 403, headers: noStore },
|
|
290297
|
+
);
|
|
290298
|
+
}
|
|
290299
|
+
|
|
289754
290300
|
const { token, expiresAt } = await sync.sessions.create({
|
|
289755
290301
|
user: { id: user.id },
|
|
290302
|
+
// These ids came from the server-side membership lookup below. Never take
|
|
290303
|
+
// organization, workspace, team, or group ids from the request body.
|
|
290304
|
+
syncGroups: authorizedScope.syncGroups,
|
|
289756
290305
|
can: { records: ['read', 'create', 'update'] },
|
|
289757
290306
|
});
|
|
289758
290307
|
return Response.json(
|
|
@@ -289776,6 +290325,27 @@ async function getCurrentUser(): Promise<{ id: string } | null> {
|
|
|
289776
290325
|
const session = await auth.api.getSession({ headers: await headers() });
|
|
289777
290326
|
return session?.user ? { id: session.user.id } : null;
|
|
289778
290327
|
}
|
|
290328
|
+
|
|
290329
|
+
type AuthorizedWorkspace = {
|
|
290330
|
+
workspaceId: string;
|
|
290331
|
+
syncGroups: readonly [\`workspace:\${string}\`, ...\`\${string}:\${string}\`[]];
|
|
290332
|
+
};
|
|
290333
|
+
|
|
290334
|
+
async function authorizeActiveWorkspace(userId: string): Promise<AuthorizedWorkspace | null> {
|
|
290335
|
+
void userId;
|
|
290336
|
+
// REQUIRED: query your membership table here, immediately before minting.
|
|
290337
|
+
// Read the active workspace from the server-side session, verify this user has
|
|
290338
|
+
// an active membership, and derive every team/group id on the server. Return
|
|
290339
|
+
// null for a stale or revoked membership. This refusal keeps a newly generated
|
|
290340
|
+
// route from turning "signed in" into workspace authorization by accident.
|
|
290341
|
+
//
|
|
290342
|
+
// Example after your membership query:
|
|
290343
|
+
// return {
|
|
290344
|
+
// workspaceId: membership.workspaceId,
|
|
290345
|
+
// syncGroups: [\`workspace:\${membership.workspaceId}\`],
|
|
290346
|
+
// };
|
|
290347
|
+
return null;
|
|
290348
|
+
}
|
|
289779
290349
|
`;
|
|
289780
290350
|
}
|
|
289781
290351
|
|
|
@@ -289808,7 +290378,7 @@ export const schema = defineSchema({
|
|
|
289808
290378
|
});
|
|
289809
290379
|
`;
|
|
289810
290380
|
}
|
|
289811
|
-
function generateSyncConfig(auth) {
|
|
290381
|
+
function generateSyncConfig(auth, options = {}) {
|
|
289812
290382
|
const authLine = auth === "apikey" ? "" : auth === "firebase" ? `
|
|
289813
290383
|
auth: async () => {
|
|
289814
290384
|
const { getAuth } = await import('firebase/auth');
|
|
@@ -289820,7 +290390,7 @@ function generateSyncConfig(auth) {
|
|
|
289820
290390
|
// auth: async () => { const { data } = await supabase.auth.getSession(); return data.session?.access_token ?? ''; },` : auth === "betterauth" ? `
|
|
289821
290391
|
// auth: async () => { const session = await authClient.getSession(); return session?.token ?? ''; },` : `
|
|
289822
290392
|
// auth: () => 'your-jwt-token', // replace with your auth provider`;
|
|
289823
|
-
return
|
|
290393
|
+
return `${options.serverOnly ? "import 'server-only';\n\n" : ""}import Ablo from '@abloatai/ablo';
|
|
289824
290394
|
import { schema } from './schema';
|
|
289825
290395
|
|
|
289826
290396
|
// SERVER-ONLY client \u2014 it holds your \`sk_\` key. Use it from server code: the
|
|
@@ -289982,7 +290552,10 @@ export async function POST(req: Request): Promise<Response> {
|
|
|
289982
290552
|
const model: unknown = Reflect.get(prisma, event.model); // prisma.record, prisma.task, \u2026
|
|
289983
290553
|
if (!isModelDelegate(model)) continue; // a model you don't mirror locally \u2014 skip it
|
|
289984
290554
|
if (event.data === null) {
|
|
289985
|
-
await model.delete({ where: { id: event.objectId } }).catch(() => {
|
|
290555
|
+
await model.delete({ where: { id: event.objectId } }).catch((error) => {
|
|
290556
|
+
// Idempotent replay: a missing local row is already the desired state.
|
|
290557
|
+
void error;
|
|
290558
|
+
});
|
|
289986
290559
|
} else {
|
|
289987
290560
|
await model.upsert({ where: { id: event.objectId }, create: event.data, update: event.data });
|
|
289988
290561
|
}
|
|
@@ -290046,12 +290619,12 @@ async function main() {
|
|
|
290046
290619
|
// Triage the urgent one to the top. We write based on the version we just
|
|
290047
290620
|
// read (\`readAt\`), so if a human edits the same row at the same moment the
|
|
290048
290621
|
// write is rejected instead of silently clobbering them.
|
|
290049
|
-
const
|
|
290622
|
+
const current = await ablo.records.read({ id: urgent.id });
|
|
290623
|
+
if (!current) throw new Error('urgent record was not found');
|
|
290050
290624
|
await ablo.records.update({
|
|
290051
290625
|
id: urgent.id,
|
|
290052
290626
|
data: { priority: 10 },
|
|
290053
|
-
|
|
290054
|
-
onStale: 'reject',
|
|
290627
|
+
reads: [current],
|
|
290055
290628
|
});
|
|
290056
290629
|
console.log('prioritized:', urgent.title);
|
|
290057
290630
|
|
|
@@ -290062,7 +290635,7 @@ async function main() {
|
|
|
290062
290635
|
main().catch((err) => {
|
|
290063
290636
|
// Ablo errors stringify to one clean line (code + message + docs link),
|
|
290064
290637
|
// never a stack/object dump \u2014 see AbloError.toString().
|
|
290065
|
-
|
|
290638
|
+
process.stderr.write(String(err) + '\\n');
|
|
290066
290639
|
process.exit(1);
|
|
290067
290640
|
});
|
|
290068
290641
|
`;
|
|
@@ -290121,9 +290694,9 @@ export function RecordList() {
|
|
|
290121
290694
|
|
|
290122
290695
|
// src/init/writer.ts
|
|
290123
290696
|
init_cjs_shims();
|
|
290124
|
-
var
|
|
290125
|
-
var
|
|
290126
|
-
var
|
|
290697
|
+
var import_node_fs6 = require("fs");
|
|
290698
|
+
var import_node_path5 = require("path");
|
|
290699
|
+
var import_node_crypto8 = require("crypto");
|
|
290127
290700
|
function projectInitWritePlan(plan) {
|
|
290128
290701
|
return setupInitPlanProjectionSchema.parse({
|
|
290129
290702
|
root: plan.root,
|
|
@@ -290137,18 +290710,18 @@ function projectInitWritePlan(plan) {
|
|
|
290137
290710
|
});
|
|
290138
290711
|
}
|
|
290139
290712
|
function absolute(root, path) {
|
|
290140
|
-
const target = (0,
|
|
290141
|
-
const fromRoot = (0,
|
|
290142
|
-
if (fromRoot === "" || fromRoot === ".." || fromRoot.startsWith(`..${
|
|
290713
|
+
const target = (0, import_node_path5.resolve)(root, path);
|
|
290714
|
+
const fromRoot = (0, import_node_path5.relative)(root, target);
|
|
290715
|
+
if (fromRoot === "" || fromRoot === ".." || fromRoot.startsWith(`..${import_node_path5.sep}`) || (0, import_node_path5.isAbsolute)(fromRoot)) {
|
|
290143
290716
|
throw new Error(`Init target must stay inside the project root: ${path}`);
|
|
290144
290717
|
}
|
|
290145
290718
|
return target;
|
|
290146
290719
|
}
|
|
290147
290720
|
function sha2562(content) {
|
|
290148
|
-
return (0,
|
|
290721
|
+
return (0, import_node_crypto8.createHash)("sha256").update(content).digest("hex");
|
|
290149
290722
|
}
|
|
290150
290723
|
function readIfPresent(path) {
|
|
290151
|
-
return (0,
|
|
290724
|
+
return (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path, "utf8") : void 0;
|
|
290152
290725
|
}
|
|
290153
290726
|
function mergeEnvironmentTemplate(existing, template) {
|
|
290154
290727
|
const assignments = template.split(/\r?\n/).map((line) => {
|
|
@@ -290172,7 +290745,7 @@ function mergeEnvironmentTemplate(existing, template) {
|
|
|
290172
290745
|
};
|
|
290173
290746
|
}
|
|
290174
290747
|
function planInitWrites(input) {
|
|
290175
|
-
const root = (0,
|
|
290748
|
+
const root = (0, import_node_path5.resolve)(input.root ?? process.cwd());
|
|
290176
290749
|
const actions = [];
|
|
290177
290750
|
const conflicts = [];
|
|
290178
290751
|
for (const file of input.files) {
|
|
@@ -290217,18 +290790,18 @@ function planInitWrites(input) {
|
|
|
290217
290790
|
return { root, actions, conflicts };
|
|
290218
290791
|
}
|
|
290219
290792
|
function writeAtomic(path, content, kind) {
|
|
290220
|
-
(0,
|
|
290221
|
-
const temporary = (0,
|
|
290222
|
-
(0,
|
|
290793
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
|
|
290794
|
+
const temporary = (0, import_node_path5.join)((0, import_node_path5.dirname)(path), `.${(0, import_node_crypto8.randomUUID)()}.ablo-init.tmp`);
|
|
290795
|
+
(0, import_node_fs6.writeFileSync)(temporary, content, { flag: "wx" });
|
|
290223
290796
|
try {
|
|
290224
290797
|
if (kind === "create") {
|
|
290225
|
-
(0,
|
|
290226
|
-
(0,
|
|
290798
|
+
(0, import_node_fs6.linkSync)(temporary, path);
|
|
290799
|
+
(0, import_node_fs6.unlinkSync)(temporary);
|
|
290227
290800
|
} else {
|
|
290228
|
-
(0,
|
|
290801
|
+
(0, import_node_fs6.renameSync)(temporary, path);
|
|
290229
290802
|
}
|
|
290230
290803
|
} catch (error) {
|
|
290231
|
-
if ((0,
|
|
290804
|
+
if ((0, import_node_fs6.existsSync)(temporary)) (0, import_node_fs6.unlinkSync)(temporary);
|
|
290232
290805
|
throw error;
|
|
290233
290806
|
}
|
|
290234
290807
|
}
|
|
@@ -290259,23 +290832,23 @@ function bailIfCancelled(value) {
|
|
|
290259
290832
|
process.exit(0);
|
|
290260
290833
|
}
|
|
290261
290834
|
}
|
|
290262
|
-
async function chooseOption(name,
|
|
290263
|
-
if (
|
|
290264
|
-
if (!allowed.includes(
|
|
290265
|
-
throw new
|
|
290266
|
-
`Invalid --${name} "${
|
|
290835
|
+
async function chooseOption(name, flagValue2, fallback, allowed, interactive, prompt) {
|
|
290836
|
+
if (flagValue2 !== void 0) {
|
|
290837
|
+
if (!allowed.includes(flagValue2)) {
|
|
290838
|
+
throw new import_errors25.AbloValidationError(
|
|
290839
|
+
`Invalid --${name} "${flagValue2}". Allowed: ${allowed.join(", ")}`,
|
|
290267
290840
|
{ code: "cli_invalid_arguments" }
|
|
290268
290841
|
);
|
|
290269
290842
|
}
|
|
290270
|
-
return
|
|
290843
|
+
return flagValue2;
|
|
290271
290844
|
}
|
|
290272
290845
|
if (!interactive) return fallback;
|
|
290273
290846
|
const value = await prompt();
|
|
290274
290847
|
bailIfCancelled(value);
|
|
290275
290848
|
return value;
|
|
290276
290849
|
}
|
|
290277
|
-
async function chooseBool(
|
|
290278
|
-
if (
|
|
290850
|
+
async function chooseBool(flagValue2, fallback, interactive, prompt) {
|
|
290851
|
+
if (flagValue2 !== void 0) return flagValue2;
|
|
290279
290852
|
if (!interactive) return fallback;
|
|
290280
290853
|
const value = await prompt();
|
|
290281
290854
|
bailIfCancelled(value);
|
|
@@ -290286,7 +290859,7 @@ async function ensureInitProject(opts) {
|
|
|
290286
290859
|
const slug = opts.project ?? projectSlugFromPackageName(
|
|
290287
290860
|
(() => {
|
|
290288
290861
|
try {
|
|
290289
|
-
return JSON.parse((0,
|
|
290862
|
+
return JSON.parse((0, import_node_fs7.readFileSync)("package.json", "utf8")).name;
|
|
290290
290863
|
} catch {
|
|
290291
290864
|
return void 0;
|
|
290292
290865
|
}
|
|
@@ -290296,7 +290869,7 @@ async function ensureInitProject(opts) {
|
|
|
290296
290869
|
const ensured = await ensureProject(slug);
|
|
290297
290870
|
if (ensured) {
|
|
290298
290871
|
console.log(
|
|
290299
|
-
` ${
|
|
290872
|
+
` ${import_picocolors31.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors31.default.bold(ensured.slug)} ${import_picocolors31.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
|
|
290300
290873
|
);
|
|
290301
290874
|
}
|
|
290302
290875
|
}
|
|
@@ -290308,16 +290881,16 @@ function renderWritePlan(actions) {
|
|
|
290308
290881
|
}
|
|
290309
290882
|
function renderAppliedWrites(actions) {
|
|
290310
290883
|
return actions.map((action) => {
|
|
290311
|
-
const status2 = action.kind === "create" ?
|
|
290312
|
-
return `${
|
|
290884
|
+
const status2 = action.kind === "create" ? import_picocolors31.default.green("created") : action.kind === "update" ? import_picocolors31.default.yellow("updated") : import_picocolors31.default.dim("unchanged");
|
|
290885
|
+
return `${import_picocolors31.default.green("\u2713")} ${action.path}${action.note ?? ""} ${import_picocolors31.default.dim(`(${status2})`)}`;
|
|
290313
290886
|
}).join("\n");
|
|
290314
290887
|
}
|
|
290315
290888
|
async function runInit(args = []) {
|
|
290316
290889
|
const opts = parseInitArgs(args);
|
|
290317
290890
|
const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
|
|
290318
|
-
Ie(`${brand("ablo")} ${
|
|
290319
|
-
if (!(0,
|
|
290320
|
-
throw new
|
|
290891
|
+
Ie(`${brand("ablo")} ${import_picocolors31.default.dim("sync engine")}`);
|
|
290892
|
+
if (!(0, import_node_fs7.existsSync)("package.json")) {
|
|
290893
|
+
throw new import_errors25.AbloValidationError("No package.json found. Run this from your project root.", {
|
|
290321
290894
|
code: "cli_invalid_arguments"
|
|
290322
290895
|
});
|
|
290323
290896
|
}
|
|
@@ -290386,14 +290959,14 @@ async function runInit(args = []) {
|
|
|
290386
290959
|
);
|
|
290387
290960
|
}
|
|
290388
290961
|
const layout = framework === "nextjs" ? detectNextLayout() : { appBase: "app", aliasBase: "." };
|
|
290389
|
-
const abloDir = (0,
|
|
290962
|
+
const abloDir = (0, import_node_path6.join)(layout.aliasBase, "ablo");
|
|
290390
290963
|
const files = [];
|
|
290391
290964
|
let schemaSource = generateSchema();
|
|
290392
290965
|
let schemaNote = "";
|
|
290393
290966
|
if (pullExisting) {
|
|
290394
290967
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
290395
290968
|
if (!dbUrl) {
|
|
290396
|
-
schemaNote =
|
|
290969
|
+
schemaNote = import_picocolors31.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
|
|
290397
290970
|
} else {
|
|
290398
290971
|
try {
|
|
290399
290972
|
const pulled = await buildSchemaSourceFromDb({
|
|
@@ -290403,56 +290976,59 @@ async function runInit(args = []) {
|
|
|
290403
290976
|
});
|
|
290404
290977
|
if (pulled.models.length > 0) {
|
|
290405
290978
|
schemaSource = pulled.source;
|
|
290406
|
-
schemaNote =
|
|
290979
|
+
schemaNote = import_picocolors31.default.dim(` (pulled ${pulled.models.length} models)`);
|
|
290407
290980
|
} else {
|
|
290408
|
-
schemaNote =
|
|
290981
|
+
schemaNote = import_picocolors31.default.dim(" (no adoptable tables \u2014 wrote starter)");
|
|
290409
290982
|
}
|
|
290410
290983
|
} catch {
|
|
290411
|
-
schemaNote =
|
|
290984
|
+
schemaNote = import_picocolors31.default.dim(" (pull failed \u2014 wrote starter)");
|
|
290412
290985
|
}
|
|
290413
290986
|
}
|
|
290414
290987
|
}
|
|
290415
|
-
files.push({ path: (0,
|
|
290416
|
-
files.push({
|
|
290417
|
-
|
|
290988
|
+
files.push({ path: (0, import_node_path6.join)(abloDir, "schema.ts"), content: schemaSource, note: schemaNote });
|
|
290989
|
+
files.push({
|
|
290990
|
+
path: (0, import_node_path6.join)(abloDir, "index.ts"),
|
|
290991
|
+
content: generateSyncConfig(auth, { serverOnly: framework === "nextjs" })
|
|
290992
|
+
});
|
|
290993
|
+
files.push({ path: (0, import_node_path6.join)(abloDir, "register.ts"), content: generateRegister() });
|
|
290418
290994
|
const orm = detectOrm(opts.orm);
|
|
290419
290995
|
if (storage === "endpoint") {
|
|
290420
290996
|
files.push({
|
|
290421
|
-
path: (0,
|
|
290997
|
+
path: (0, import_node_path6.join)(abloDir, "data-source.ts"),
|
|
290422
290998
|
content: generateDataSource(orm),
|
|
290423
290999
|
note: orm === "drizzle" ? " (Drizzle)" : " (Prisma)"
|
|
290424
291000
|
});
|
|
290425
291001
|
}
|
|
290426
291002
|
const envFile = framework === "nextjs" ? ".env.local" : ".env";
|
|
290427
291003
|
const envBody = generateEnv(storage);
|
|
290428
|
-
if (agent) files.push({ path: (0,
|
|
291004
|
+
if (agent) files.push({ path: (0, import_node_path6.join)(abloDir, "agent.ts"), content: generateAgent() });
|
|
290429
291005
|
if (framework === "nextjs") {
|
|
290430
291006
|
if (storage === "endpoint") {
|
|
290431
|
-
const webhookDir = (0,
|
|
291007
|
+
const webhookDir = (0, import_node_path6.join)(layout.appBase, "api", "ablo", "webhooks");
|
|
290432
291008
|
files.push({
|
|
290433
|
-
path: (0,
|
|
291009
|
+
path: (0, import_node_path6.join)(webhookDir, "route.ts"),
|
|
290434
291010
|
content: generateWebhookRoute(orm),
|
|
290435
291011
|
note: orm === "prisma" ? " (Prisma mirror)" : " (add your database write)"
|
|
290436
291012
|
});
|
|
290437
291013
|
}
|
|
290438
291014
|
files.push({
|
|
290439
|
-
path: (0,
|
|
291015
|
+
path: (0, import_node_path6.join)(layout.appBase, "providers.tsx"),
|
|
290440
291016
|
content: generateProviders(),
|
|
290441
|
-
note: ` (wrap ${(0,
|
|
291017
|
+
note: ` (wrap ${(0, import_node_path6.join)(layout.appBase, "layout.tsx")} in <Providers>)`
|
|
290442
291018
|
});
|
|
290443
291019
|
files.push({
|
|
290444
|
-
path: (0,
|
|
291020
|
+
path: (0, import_node_path6.join)(layout.appBase, "api", "ablo-session", "route.ts"),
|
|
290445
291021
|
content: generateSessionRoute(),
|
|
290446
291022
|
note: " (wire your auth)"
|
|
290447
291023
|
});
|
|
290448
291024
|
}
|
|
290449
291025
|
if (framework !== "vanilla") {
|
|
290450
|
-
files.push({ path: (0,
|
|
291026
|
+
files.push({ path: (0, import_node_path6.join)(abloDir, "RecordList.tsx"), content: generateComponent() });
|
|
290451
291027
|
}
|
|
290452
291028
|
const writePlan = planInitWrites({ files, environment: { path: envFile, template: envBody } });
|
|
290453
291029
|
if (writePlan.conflicts.length > 0) {
|
|
290454
291030
|
const occupied = writePlan.conflicts.map(({ path }) => ` - ${path}`).join("\n");
|
|
290455
|
-
throw new
|
|
291031
|
+
throw new import_errors25.AbloValidationError(
|
|
290456
291032
|
`Ablo init did not change any files because these application-owned paths already contain different contents:
|
|
290457
291033
|
${occupied}
|
|
290458
291034
|
|
|
@@ -290462,7 +291038,7 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
|
|
|
290462
291038
|
}
|
|
290463
291039
|
if (opts.plan) {
|
|
290464
291040
|
Me(renderWritePlan(writePlan.actions), "Plan (no files changed)");
|
|
290465
|
-
Se(`Dry run complete. Re-run without ${
|
|
291041
|
+
Se(`Dry run complete. Re-run without ${import_picocolors31.default.bold("--plan")} to apply it.`);
|
|
290466
291042
|
return setupInitResultSchema.parse({
|
|
290467
291043
|
status: "planned",
|
|
290468
291044
|
plan: projectInitWritePlan(writePlan)
|
|
@@ -290479,32 +291055,32 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
|
|
|
290479
291055
|
const progress = Y2();
|
|
290480
291056
|
progress.start("Installing @abloatai/ablo");
|
|
290481
291057
|
try {
|
|
290482
|
-
(0,
|
|
291058
|
+
(0, import_node_child_process4.execFileSync)(packageManager2, ["add", "@abloatai/ablo"], { stdio: "ignore" });
|
|
290483
291059
|
progress.stop("Installed @abloatai/ablo");
|
|
290484
291060
|
} catch {
|
|
290485
291061
|
progress.stop(
|
|
290486
|
-
`${
|
|
291062
|
+
`${import_picocolors31.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors31.default.bold(`${packageManager2} install @abloatai/ablo`)}`
|
|
290487
291063
|
);
|
|
290488
291064
|
}
|
|
290489
291065
|
}
|
|
290490
291066
|
const steps = [
|
|
290491
|
-
`Run ${
|
|
290492
|
-
`Set ${
|
|
290493
|
-
`Run ${
|
|
291067
|
+
`Run ${import_picocolors31.default.bold("npx ablo login")} to authorize branch management`,
|
|
291068
|
+
`Set ${import_picocolors31.default.bold("DATABASE_URL")} in ${import_picocolors31.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
|
|
291069
|
+
`Run ${import_picocolors31.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
|
|
290494
291070
|
...storage === "replication" ? [
|
|
290495
|
-
`Connect your database \u2014 ${
|
|
290496
|
-
`Verify it \u2014 ${
|
|
290497
|
-
`Register it \u2014 ${
|
|
291071
|
+
`Connect your database \u2014 ${import_picocolors31.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
|
|
291072
|
+
`Verify it \u2014 ${import_picocolors31.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
|
|
291073
|
+
`Register it \u2014 ${import_picocolors31.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
|
|
290498
291074
|
] : [
|
|
290499
|
-
`Provision your DB: ${
|
|
291075
|
+
`Provision your DB: ${import_picocolors31.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors31.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors31.default.bold("/api/ablo/source")}`
|
|
290500
291076
|
],
|
|
290501
291077
|
...framework === "nextjs" ? [
|
|
290502
|
-
`Wrap ${
|
|
291078
|
+
`Wrap ${import_picocolors31.default.bold((0, import_node_path6.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors31.default.bold("<Providers>")} (${(0, import_node_path6.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors31.default.bold((0, import_node_path6.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
|
|
290503
291079
|
] : [],
|
|
290504
|
-
`Run ${
|
|
291080
|
+
`Run ${import_picocolors31.default.bold(`${packageManager2} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
|
|
290505
291081
|
...agent ? [
|
|
290506
|
-
`Run ${
|
|
290507
|
-
`Run ${
|
|
291082
|
+
`Run ${import_picocolors31.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same records`,
|
|
291083
|
+
`Run ${import_picocolors31.default.bold("npx ablo logs")} to watch human + agent commits stream by`
|
|
290508
291084
|
] : []
|
|
290509
291085
|
];
|
|
290510
291086
|
Me(steps.map((step, index) => `${index + 1}. ${step}`).join("\n"), "Next steps");
|
|
@@ -290512,26 +291088,26 @@ Move them, reconcile Ablo manually, or rerun after they match the generated scaf
|
|
|
290512
291088
|
if (existingKey) {
|
|
290513
291089
|
await ensureInitProject(opts);
|
|
290514
291090
|
Se(
|
|
290515
|
-
`Already authorized ${
|
|
291091
|
+
`Already authorized ${import_picocolors31.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors31.default.bold("npx ablo dev")} next. ${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`
|
|
290516
291092
|
);
|
|
290517
291093
|
return initResult;
|
|
290518
291094
|
}
|
|
290519
291095
|
if (interactive && opts.login) {
|
|
290520
291096
|
const loginNow = await ye({ message: "Log in now? (opens your browser)", initialValue: true });
|
|
290521
291097
|
if (!pD(loginNow) && loginNow) {
|
|
290522
|
-
Se(`${
|
|
291098
|
+
Se(`${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`);
|
|
290523
291099
|
await login();
|
|
290524
291100
|
await ensureInitProject(opts);
|
|
290525
291101
|
return initResult;
|
|
290526
291102
|
}
|
|
290527
291103
|
}
|
|
290528
|
-
Se(`Run ${
|
|
291104
|
+
Se(`Run ${import_picocolors31.default.bold("npx ablo login")} when ready. ${import_picocolors31.default.dim("Docs:")} https://abloatai.com/docs`);
|
|
290529
291105
|
return initResult;
|
|
290530
291106
|
}
|
|
290531
291107
|
|
|
290532
291108
|
// src/index.ts
|
|
290533
291109
|
var LOGO = `
|
|
290534
|
-
${brand("ablo")} ${
|
|
291110
|
+
${brand("ablo")} ${import_picocolors32.default.dim("sync engine")}
|
|
290535
291111
|
`;
|
|
290536
291112
|
var HANDLERS = {
|
|
290537
291113
|
setup: (argv) => runSetup(argv),
|
|
@@ -290547,6 +291123,7 @@ var HANDLERS = {
|
|
|
290547
291123
|
whoami: (argv) => whoami([...argv]),
|
|
290548
291124
|
doctor: (argv) => doctor([...argv]),
|
|
290549
291125
|
logs: (argv) => logs([...argv]),
|
|
291126
|
+
claims: (argv) => claims([...argv]),
|
|
290550
291127
|
webhooks: (argv) => webhooks([...argv]),
|
|
290551
291128
|
check: (argv) => check([...argv]),
|
|
290552
291129
|
docs: (argv) => docs([...argv]),
|
|
@@ -290564,7 +291141,7 @@ async function runDev(argv) {
|
|
|
290564
291141
|
const devArgs = [...argv];
|
|
290565
291142
|
const oneShot = devArgs.includes("--no-watch");
|
|
290566
291143
|
console.log(
|
|
290567
|
-
|
|
291144
|
+
import_picocolors32.default.dim(
|
|
290568
291145
|
oneShot ? " `ablo dev --no-watch` prepares this Git branch and pushes once." : " `ablo dev` prepares this Git branch and watches the schema."
|
|
290569
291146
|
)
|
|
290570
291147
|
);
|
|
@@ -290582,7 +291159,7 @@ async function runPush2(argv) {
|
|
|
290582
291159
|
}
|
|
290583
291160
|
function runRenamedSchema(argv) {
|
|
290584
291161
|
const forwarded = argv.slice(1).join(" ");
|
|
290585
|
-
console.error(` ${
|
|
291162
|
+
console.error(` ${import_picocolors32.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
|
|
290586
291163
|
console.error(` Run \`ablo push${forwarded ? " " + forwarded : ""}\` instead.`);
|
|
290587
291164
|
process.exitCode = 1;
|
|
290588
291165
|
}
|
|
@@ -290592,7 +291169,7 @@ async function main() {
|
|
|
290592
291169
|
const argv = process.argv.slice(3);
|
|
290593
291170
|
if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
|
|
290594
291171
|
const suggestion = suggestCommand(raw);
|
|
290595
|
-
throw new
|
|
291172
|
+
throw new import_errors26.AbloValidationError(
|
|
290596
291173
|
`\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
|
|
290597
291174
|
{ code: "cli_invalid_arguments" }
|
|
290598
291175
|
);
|
|
@@ -290633,7 +291210,7 @@ function printCoreHelp() {
|
|
|
290633
291210
|
const width = Math.max(...rows.map((r2) => r2.run.length)) + 4;
|
|
290634
291211
|
console.log(LOGO);
|
|
290635
291212
|
for (const group of CORE_GROUPS) {
|
|
290636
|
-
console.log(` ${
|
|
291213
|
+
console.log(` ${import_picocolors32.default.bold(group)}`);
|
|
290637
291214
|
const printed = group === "More" ? [...coreRows(group), ...extra] : coreRows(group);
|
|
290638
291215
|
for (const row of printed) console.log(` npx ablo ${row.run.padEnd(width)}${row.does}`);
|
|
290639
291216
|
console.log();
|
|
@@ -290642,7 +291219,7 @@ function printCoreHelp() {
|
|
|
290642
291219
|
}
|
|
290643
291220
|
function printSchemaReminder() {
|
|
290644
291221
|
console.log(
|
|
290645
|
-
|
|
291222
|
+
import_picocolors32.default.dim(` Edit ${import_picocolors32.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors32.default.yellow("server_execute_unknown_model") + import_picocolors32.default.dim(".")
|
|
290646
291223
|
);
|
|
290647
291224
|
console.log();
|
|
290648
291225
|
}
|
|
@@ -290652,7 +291229,7 @@ function printFullHelp() {
|
|
|
290652
291229
|
) + 2;
|
|
290653
291230
|
console.log(LOGO);
|
|
290654
291231
|
for (const group of FULL_GROUPS) {
|
|
290655
|
-
console.log(` ${
|
|
291232
|
+
console.log(` ${import_picocolors32.default.bold(group)}`);
|
|
290656
291233
|
for (const row of fullRows(group)) {
|
|
290657
291234
|
console.log(row.does === void 0 ? ` ${" ".repeat(9)}${row.run}` : ` npx ablo ${row.run.padEnd(width)}${row.does}`);
|
|
290658
291235
|
}
|