@abloatai/cli 0.41.0 → 0.43.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 +998 -632
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -3047,23 +3047,28 @@ function readProjectWriteDatabaseUrl(cwd = process.cwd()) {
|
|
|
3047
3047
|
return readProjectEnvValue("ABLO_WRITE_DATABASE_URL", cwd);
|
|
3048
3048
|
}
|
|
3049
3049
|
function readProjectEnvValue(variable, cwd) {
|
|
3050
|
+
return readProjectEnvVariable(variable, cwd, false)?.value ?? null;
|
|
3051
|
+
}
|
|
3052
|
+
function readProjectEnvVariable(variable, cwd = process.cwd(), includeProcess = true) {
|
|
3053
|
+
if (includeProcess && process.env[variable]) {
|
|
3054
|
+
return { value: process.env[variable], source: "env" };
|
|
3055
|
+
}
|
|
3050
3056
|
for (const filename of [".env.local", ".env"]) {
|
|
3051
3057
|
const path = (0, import_path.resolve)(cwd, filename);
|
|
3052
3058
|
if (!(0, import_fs2.existsSync)(path)) continue;
|
|
3053
3059
|
const match = new RegExp(`^${variable}=(.+)$`, "m").exec((0, import_fs2.readFileSync)(path, "utf8"));
|
|
3054
|
-
if (match?.[1])
|
|
3060
|
+
if (match?.[1]) {
|
|
3061
|
+
return {
|
|
3062
|
+
value: match[1].trim().replace(/^["']|["']$/g, ""),
|
|
3063
|
+
source: filename
|
|
3064
|
+
};
|
|
3065
|
+
}
|
|
3055
3066
|
}
|
|
3056
3067
|
return null;
|
|
3057
3068
|
}
|
|
3058
3069
|
function readProjectApiKey(cwd = process.cwd()) {
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
const path = (0, import_path.resolve)(cwd, name);
|
|
3062
|
-
if (!(0, import_fs2.existsSync)(path)) continue;
|
|
3063
|
-
const match = /^ABLO_API_KEY=(.+)$/m.exec((0, import_fs2.readFileSync)(path, "utf8"));
|
|
3064
|
-
if (match?.[1]) return { key: match[1].trim().replace(/^["']|["']$/g, ""), source: name };
|
|
3065
|
-
}
|
|
3066
|
-
return null;
|
|
3070
|
+
const found = readProjectEnvVariable("ABLO_API_KEY", cwd);
|
|
3071
|
+
return found ? { key: found.value, source: found.source } : null;
|
|
3067
3072
|
}
|
|
3068
3073
|
var import_crypto2, import_fs2, import_path, REPLICATION_URL_VARS, ADMIN_URL_VAR;
|
|
3069
3074
|
var init_dbRole = __esm({
|
|
@@ -3308,43 +3313,16 @@ function getKeyEntry(mode) {
|
|
|
3308
3313
|
if (!cfg) return void 0;
|
|
3309
3314
|
return cfg.profiles[activeProfileName(cfg)]?.[mode];
|
|
3310
3315
|
}
|
|
3316
|
+
function getManagementKeyEntry() {
|
|
3317
|
+
const cfg = readConfig();
|
|
3318
|
+
if (!cfg) return void 0;
|
|
3319
|
+
return cfg.profiles[activeProfileName(cfg)]?.management;
|
|
3320
|
+
}
|
|
3311
3321
|
function modeFromKey(key) {
|
|
3312
3322
|
if (/^(sk|rk)_test_/.test(key)) return "sandbox";
|
|
3313
3323
|
if (/^(sk|rk)_live_/.test(key)) return "production";
|
|
3314
3324
|
return void 0;
|
|
3315
3325
|
}
|
|
3316
|
-
function prefix(key) {
|
|
3317
|
-
return key ? key.slice(0, 12) : null;
|
|
3318
|
-
}
|
|
3319
|
-
function describeEffectiveKey(activeMode, envKey, storedEntry) {
|
|
3320
|
-
const effectiveKey = envKey ?? storedEntry?.apiKey;
|
|
3321
|
-
const keySource = envKey ? "env" : storedEntry ? "stored" : null;
|
|
3322
|
-
const keyMode = effectiveKey ? modeFromKey(effectiveKey) ?? null : null;
|
|
3323
|
-
const keyMatchesActiveMode = keyMode ? keyMode === activeMode : null;
|
|
3324
|
-
const keyMatchesStoredActiveKey = envKey && storedEntry?.apiKey ? envKey === storedEntry.apiKey : null;
|
|
3325
|
-
let keyMismatch = null;
|
|
3326
|
-
if (keyMode && keyMode !== activeMode) {
|
|
3327
|
-
const sourceLabel = envKey ? "ABLO_API_KEY" : "stored active key";
|
|
3328
|
-
keyMismatch = {
|
|
3329
|
-
code: "key_mode_mismatch",
|
|
3330
|
-
message: `${sourceLabel} is a ${keyMode} key but the CLI mode is ${activeMode}. Requests use ${sourceLabel} (${prefix(effectiveKey)}...), not the active CLI mode.`
|
|
3331
|
-
};
|
|
3332
|
-
} else if (envKey && storedEntry?.apiKey && envKey !== storedEntry.apiKey) {
|
|
3333
|
-
keyMismatch = {
|
|
3334
|
-
code: "env_key_overrides_stored",
|
|
3335
|
-
message: `ABLO_API_KEY (${prefix(envKey)}...) overrides the stored ${activeMode} key (${prefix(storedEntry.apiKey)}...).`
|
|
3336
|
-
};
|
|
3337
|
-
}
|
|
3338
|
-
return {
|
|
3339
|
-
keyPrefix: prefix(effectiveKey),
|
|
3340
|
-
keySource,
|
|
3341
|
-
keyMode,
|
|
3342
|
-
storedKeyPrefix: prefix(storedEntry?.apiKey),
|
|
3343
|
-
keyMatchesActiveMode,
|
|
3344
|
-
keyMatchesStoredActiveKey,
|
|
3345
|
-
keyMismatch
|
|
3346
|
-
};
|
|
3347
|
-
}
|
|
3348
3326
|
function normalizeMode(value) {
|
|
3349
3327
|
return normalizeStoredMode(value);
|
|
3350
3328
|
}
|
|
@@ -3358,9 +3336,14 @@ function clearCredential() {
|
|
|
3358
3336
|
}
|
|
3359
3337
|
return removed;
|
|
3360
3338
|
}
|
|
3361
|
-
function
|
|
3339
|
+
function resolveMutationApiKey(modeOverride) {
|
|
3362
3340
|
return resolveKey({ purpose: "data", mode: modeOverride }).key;
|
|
3363
3341
|
}
|
|
3342
|
+
function ambientEnvKeyNote(cwd) {
|
|
3343
|
+
const ambient = readProjectApiKey(cwd);
|
|
3344
|
+
if (!ambient || ambient.source === "env") return null;
|
|
3345
|
+
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.";
|
|
3346
|
+
}
|
|
3364
3347
|
function resolveManagementKey() {
|
|
3365
3348
|
if (process.env.ABLO_MANAGEMENT_KEY) return process.env.ABLO_MANAGEMENT_KEY;
|
|
3366
3349
|
const cfg = readConfig();
|
|
@@ -3388,7 +3371,7 @@ function resolveOrgManagementKey() {
|
|
|
3388
3371
|
return void 0;
|
|
3389
3372
|
}
|
|
3390
3373
|
function guardActiveProjectKey() {
|
|
3391
|
-
const { key, source } =
|
|
3374
|
+
const { key, source } = resolveRuntimeApiKey();
|
|
3392
3375
|
if (key != null && source != null && source !== "stored") {
|
|
3393
3376
|
return { ok: true, activeProfile: DEFAULT_PROFILE, available: [] };
|
|
3394
3377
|
}
|
|
@@ -3421,16 +3404,9 @@ function resolveKey(policy) {
|
|
|
3421
3404
|
}
|
|
3422
3405
|
return { key: void 0, source: null };
|
|
3423
3406
|
}
|
|
3424
|
-
function
|
|
3407
|
+
function resolveRuntimeApiKey(modeOverride, cwd) {
|
|
3425
3408
|
return resolveKey({ purpose: "data", mode: modeOverride, scanEnvFiles: true, cwd });
|
|
3426
3409
|
}
|
|
3427
|
-
function resolvePushPlan() {
|
|
3428
|
-
const { key, source } = resolveEffectiveApiKey();
|
|
3429
|
-
if (key != null && source != null && source !== "stored") {
|
|
3430
|
-
return { flow: modeFromKey(key) ?? getMode(), apiKey: key, source };
|
|
3431
|
-
}
|
|
3432
|
-
return { flow: getMode(), apiKey: key, source };
|
|
3433
|
-
}
|
|
3434
3410
|
var import_os2, import_path2, import_fs3, DEFAULT_PROFILE;
|
|
3435
3411
|
var init_config = __esm({
|
|
3436
3412
|
"src/config.ts"() {
|
|
@@ -3767,13 +3743,14 @@ async function confirmFromServer(opts) {
|
|
|
3767
3743
|
const project = projectId ? await nameProject(projectId, identity.accountScope, opts) : null;
|
|
3768
3744
|
return {
|
|
3769
3745
|
organizationId: identity.accountScope,
|
|
3770
|
-
environment: keyEnv,
|
|
3746
|
+
environment: identity.branchRoot === void 0 ? keyEnv : identity.branchRoot ? "production" : "sandbox",
|
|
3771
3747
|
project,
|
|
3772
3748
|
projectId,
|
|
3773
3749
|
branchId: identity.branchId ?? null,
|
|
3774
3750
|
branchRoot: identity.branchRoot
|
|
3775
3751
|
};
|
|
3776
|
-
} catch {
|
|
3752
|
+
} catch (error) {
|
|
3753
|
+
if (opts.strict) throw error;
|
|
3777
3754
|
return null;
|
|
3778
3755
|
}
|
|
3779
3756
|
}
|
|
@@ -4017,6 +3994,7 @@ function parsePushArgs(argv) {
|
|
|
4017
3994
|
let force = false;
|
|
4018
3995
|
let yes = false;
|
|
4019
3996
|
let dryRun = false;
|
|
3997
|
+
let envFile;
|
|
4020
3998
|
const renames = [];
|
|
4021
3999
|
const backfills = [];
|
|
4022
4000
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -4031,6 +4009,9 @@ function parsePushArgs(argv) {
|
|
|
4031
4009
|
case "--url":
|
|
4032
4010
|
url = argv[++i] ?? url;
|
|
4033
4011
|
break;
|
|
4012
|
+
case "--env-file":
|
|
4013
|
+
envFile = argv[++i] ?? envFile;
|
|
4014
|
+
break;
|
|
4034
4015
|
case "--force":
|
|
4035
4016
|
force = true;
|
|
4036
4017
|
break;
|
|
@@ -4072,7 +4053,18 @@ function parsePushArgs(argv) {
|
|
|
4072
4053
|
}
|
|
4073
4054
|
}
|
|
4074
4055
|
url = url.replace(/\/+$/, "");
|
|
4075
|
-
return {
|
|
4056
|
+
return {
|
|
4057
|
+
schemaPath,
|
|
4058
|
+
exportName,
|
|
4059
|
+
url,
|
|
4060
|
+
apiKey: process.env.ABLO_API_KEY,
|
|
4061
|
+
...envFile ? { envFile } : {},
|
|
4062
|
+
force,
|
|
4063
|
+
renames,
|
|
4064
|
+
backfills,
|
|
4065
|
+
yes,
|
|
4066
|
+
dryRun
|
|
4067
|
+
};
|
|
4076
4068
|
}
|
|
4077
4069
|
function publicationGap(value) {
|
|
4078
4070
|
if (typeof value !== "object" || value === null) return null;
|
|
@@ -4173,8 +4165,21 @@ function printPlan(local, remote) {
|
|
|
4173
4165
|
console.log("");
|
|
4174
4166
|
}
|
|
4175
4167
|
async function confirmPush(args, target) {
|
|
4176
|
-
const
|
|
4177
|
-
const
|
|
4168
|
+
const confirmedRoot = target.confirmed?.branchRoot;
|
|
4169
|
+
const legacyEnv = target.keyEnv;
|
|
4170
|
+
if (confirmedRoot === void 0 && legacyEnv === null) {
|
|
4171
|
+
console.error(
|
|
4172
|
+
` ${import_picocolors5.default.red("\u2717")} Refusing to deploy because the server did not confirm which branch this key targets.`
|
|
4173
|
+
);
|
|
4174
|
+
console.error(
|
|
4175
|
+
import_picocolors5.default.dim(
|
|
4176
|
+
` Current ${import_picocolors5.default.bold("sk_")} keys do not encode live/test state. Check connectivity with ${import_picocolors5.default.bold("ablo whoami")} and retry; the CLI will not guess for a write.`
|
|
4177
|
+
)
|
|
4178
|
+
);
|
|
4179
|
+
process.exit(1);
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
const isProd = confirmedRoot ?? legacyEnv === "production";
|
|
4178
4183
|
const tty = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
4179
4184
|
if (isProd && !args.yes) {
|
|
4180
4185
|
if (!tty) {
|
|
@@ -4197,7 +4202,10 @@ async function confirmPush(args, target) {
|
|
|
4197
4202
|
return;
|
|
4198
4203
|
}
|
|
4199
4204
|
if (!isProd && !args.yes && tty) {
|
|
4200
|
-
const
|
|
4205
|
+
const branch = target.confirmed?.branchId;
|
|
4206
|
+
const ok = await ye({
|
|
4207
|
+
message: `Apply to development branch${branch ? ` ${import_picocolors5.default.bold(branch)}` : ""}?`
|
|
4208
|
+
});
|
|
4201
4209
|
if (pD(ok) || !ok) {
|
|
4202
4210
|
xe("Aborted.");
|
|
4203
4211
|
process.exit(1);
|
|
@@ -4206,8 +4214,7 @@ async function confirmPush(args, target) {
|
|
|
4206
4214
|
}
|
|
4207
4215
|
function printPushTarget(target, schema) {
|
|
4208
4216
|
const confirmed = target.confirmed;
|
|
4209
|
-
const
|
|
4210
|
-
const envLabel = env === "production" ? import_picocolors5.default.bold("production") : env === "sandbox" ? import_picocolors5.default.bold("sandbox") : import_picocolors5.default.yellow("unknown env");
|
|
4217
|
+
const branchLabel = confirmed?.branchRoot === true ? import_picocolors5.default.bold("production root") : confirmed?.branchId ? `${import_picocolors5.default.bold("branch")} ${import_picocolors5.default.bold(confirmed.branchId)}` : target.keyEnv === "production" ? `${import_picocolors5.default.bold("production root")} ${import_picocolors5.default.yellow("(legacy key; unconfirmed)")}` : target.keyEnv === "sandbox" ? `${import_picocolors5.default.bold("development branch")} ${import_picocolors5.default.yellow("(legacy key; unconfirmed)")}` : import_picocolors5.default.red("unknown branch");
|
|
4211
4218
|
let projectLabel;
|
|
4212
4219
|
if (confirmed?.project) {
|
|
4213
4220
|
const p2 = confirmed.project;
|
|
@@ -4220,7 +4227,7 @@ function printPushTarget(target, schema) {
|
|
|
4220
4227
|
projectLabel = `${shown} ${import_picocolors5.default.yellow("(unconfirmed \u2014 server did not answer)")}`;
|
|
4221
4228
|
}
|
|
4222
4229
|
console.log(`
|
|
4223
|
-
${brand("ablo")} ${import_picocolors5.default.dim("push")} ${import_picocolors5.default.dim("\u2192")} ${
|
|
4230
|
+
${brand("ablo")} ${import_picocolors5.default.dim("push")} ${import_picocolors5.default.dim("\u2192")} ${branchLabel}`);
|
|
4224
4231
|
if (confirmed?.organizationId) console.log(` ${import_picocolors5.default.dim("org")} ${import_picocolors5.default.dim(confirmed.organizationId)}`);
|
|
4225
4232
|
console.log(` ${import_picocolors5.default.dim("project")} ${projectLabel}`);
|
|
4226
4233
|
console.log(` ${import_picocolors5.default.dim("target")} ${import_picocolors5.default.dim(target.url)}`);
|
|
@@ -4249,6 +4256,8 @@ function describeKeySource(source) {
|
|
|
4249
4256
|
return ".env";
|
|
4250
4257
|
case "stored":
|
|
4251
4258
|
return "ablo login";
|
|
4259
|
+
case "explicit-file":
|
|
4260
|
+
return "--env-file";
|
|
4252
4261
|
}
|
|
4253
4262
|
}
|
|
4254
4263
|
async function push(argv) {
|
|
@@ -4259,16 +4268,29 @@ async function push(argv) {
|
|
|
4259
4268
|
console.error(import_picocolors5.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
4260
4269
|
process.exit(1);
|
|
4261
4270
|
}
|
|
4271
|
+
if (args.envFile) {
|
|
4272
|
+
try {
|
|
4273
|
+
process.loadEnvFile(args.envFile);
|
|
4274
|
+
} catch (error) {
|
|
4275
|
+
throw new import_errors6.AbloValidationError(
|
|
4276
|
+
`could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4277
|
+
{ code: "cli_invalid_arguments" }
|
|
4278
|
+
);
|
|
4279
|
+
}
|
|
4280
|
+
args.apiKey = process.env.ABLO_API_KEY;
|
|
4281
|
+
}
|
|
4262
4282
|
let keySource = "env";
|
|
4263
4283
|
if (!args.apiKey) {
|
|
4264
|
-
|
|
4265
|
-
args.apiKey
|
|
4266
|
-
|
|
4284
|
+
args.apiKey = resolveMutationApiKey();
|
|
4285
|
+
keySource = args.apiKey ? "stored" : "env";
|
|
4286
|
+
} else if (args.envFile) {
|
|
4287
|
+
keySource = "explicit-file";
|
|
4267
4288
|
}
|
|
4268
4289
|
if (!args.apiKey) {
|
|
4290
|
+
const ambient = ambientEnvKeyNote();
|
|
4269
4291
|
console.error(
|
|
4270
4292
|
import_picocolors5.default.red(` No API key.`) + import_picocolors5.default.dim(
|
|
4271
|
-
` Run ${import_picocolors5.default.bold("
|
|
4293
|
+
` Run ${import_picocolors5.default.bold("ablo login")}, or set ${import_picocolors5.default.bold("ABLO_API_KEY")} to a branch-bound ${import_picocolors5.default.bold("sk_")} credential.` + (ambient ? ` A project env file contains one; select it explicitly with ${import_picocolors5.default.bold("npx ablo push --env-file .env.local")}.` : "")
|
|
4272
4294
|
)
|
|
4273
4295
|
);
|
|
4274
4296
|
process.exit(1);
|
|
@@ -4405,19 +4427,19 @@ async function push(argv) {
|
|
|
4405
4427
|
} else if (code === "schema_provisioning_forbidden") {
|
|
4406
4428
|
console.error(
|
|
4407
4429
|
import_picocolors5.default.dim(
|
|
4408
|
-
` This is not a key problem \u2014 the push was authorized, but the target database refused to let the engine create tables (Postgres 42501). On the replication read path Ablo never runs DDL: register your database as a data source with ${import_picocolors5.default.bold("npx ablo connect register")}, and pushes to that
|
|
4430
|
+
` This is not a key problem \u2014 the push was authorized, but the target database refused to let the engine create tables (Postgres 42501). On the replication read path Ablo never runs DDL: register your database as a data source with ${import_picocolors5.default.bold("npx ablo connect register")}, and pushes to that branch record the schema as metadata only \u2014 no tables are created anywhere.`
|
|
4409
4431
|
)
|
|
4410
4432
|
);
|
|
4411
4433
|
} else if (args.apiKey != null && (0, import_credentialPolicy.classifyCredentialKind)(args.apiKey) === "restricted") {
|
|
4412
4434
|
console.error(
|
|
4413
4435
|
import_picocolors5.default.dim(
|
|
4414
|
-
` Schema pushes need a SECRET
|
|
4436
|
+
` Schema pushes need a branch-bound SECRET ${import_picocolors5.default.bold("sk_")} key. Use ${import_picocolors5.default.bold("ablo dev")} for a development child or ${import_picocolors5.default.bold("ablo push")} with a root-bound key for production.`
|
|
4415
4437
|
)
|
|
4416
4438
|
);
|
|
4417
4439
|
} else {
|
|
4418
4440
|
console.error(
|
|
4419
4441
|
import_picocolors5.default.dim(
|
|
4420
|
-
` This key isn't authorized to push schema (needs ${import_picocolors5.default.bold("schema:push")}). ` + (keySource === "stored" ? `
|
|
4442
|
+
` This key isn't authorized to push schema (needs ${import_picocolors5.default.bold("schema:push")}). ` + (keySource === "stored" ? `The stored login is management-only. Put a branch-bound ${import_picocolors5.default.bold("sk_")} key with ${import_picocolors5.default.bold("schema:push")} in ${import_picocolors5.default.bold(".env.local")} or ${import_picocolors5.default.bold("ABLO_API_KEY")} and retry. ` : `Use a branch-bound ${import_picocolors5.default.bold("sk_")} key with ${import_picocolors5.default.bold("schema:push")}. `) + `Manage keys at https://abloatai.com`
|
|
4421
4443
|
)
|
|
4422
4444
|
);
|
|
4423
4445
|
}
|
|
@@ -4426,7 +4448,7 @@ async function push(argv) {
|
|
|
4426
4448
|
}
|
|
4427
4449
|
process.exit(1);
|
|
4428
4450
|
}
|
|
4429
|
-
var import_picocolors5, import_errors6, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, import_schema2, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT;
|
|
4451
|
+
var import_picocolors5, import_errors6, import_credentialPolicy, import_fs4, import_path3, import_child_process, import_schema, import_schema2, DEFAULT_SCHEMA_PATH, DEFAULT_EXPORT, PUSH_USAGE;
|
|
4430
4452
|
var init_push = __esm({
|
|
4431
4453
|
"src/push.ts"() {
|
|
4432
4454
|
"use strict";
|
|
@@ -4447,6 +4469,26 @@ var init_push = __esm({
|
|
|
4447
4469
|
import_schema2 = require("@abloatai/transaction/coordination/schema");
|
|
4448
4470
|
DEFAULT_SCHEMA_PATH = "ablo/schema.ts";
|
|
4449
4471
|
DEFAULT_EXPORT = "schema";
|
|
4472
|
+
PUSH_USAGE = ` ablo push \u2014 upload a schema to one confirmed branch
|
|
4473
|
+
|
|
4474
|
+
Usage:
|
|
4475
|
+
npx ablo push
|
|
4476
|
+
npx ablo push --env-file .env.production --yes
|
|
4477
|
+
npx ablo push --dry-run
|
|
4478
|
+
|
|
4479
|
+
Credential:
|
|
4480
|
+
ABLO_API_KEY Branch-bound sk_ key from the process environment
|
|
4481
|
+
--env-file <path> Explicitly load ABLO_API_KEY from a dotenv file
|
|
4482
|
+
|
|
4483
|
+
Safety:
|
|
4484
|
+
--yes, -y Confirm non-interactively (required for the production root)
|
|
4485
|
+
--dry-run, --plan Show target and schema diff without applying
|
|
4486
|
+
--force Allow destructive schema changes
|
|
4487
|
+
--rename old:new Record a model rename
|
|
4488
|
+
--backfill m.f=value Seed existing rows for a new required field
|
|
4489
|
+
|
|
4490
|
+
The server confirms the key's project and branch. Current keys do not encode
|
|
4491
|
+
live/test state, and push never guesses a branch from their spelling.`;
|
|
4450
4492
|
}
|
|
4451
4493
|
});
|
|
4452
4494
|
|
|
@@ -4971,8 +5013,8 @@ __export(disconnect_exports, {
|
|
|
4971
5013
|
function planeLabel(target) {
|
|
4972
5014
|
const confirmed = target.confirmed;
|
|
4973
5015
|
const project = confirmed?.project?.name ?? confirmed?.project?.slug ?? confirmed?.projectId ?? "the default project";
|
|
4974
|
-
const
|
|
4975
|
-
return { project,
|
|
5016
|
+
const branch = confirmed?.branchRoot === true ? "production root" : confirmed?.branchId ? `branch ${confirmed.branchId}` : target.keyEnv === "production" ? "production root (legacy key; unconfirmed)" : target.keyEnv === "sandbox" ? "development branch (legacy key; unconfirmed)" : "unknown branch";
|
|
5017
|
+
return { project, branch };
|
|
4976
5018
|
}
|
|
4977
5019
|
async function deregisterDataSource(opts) {
|
|
4978
5020
|
try {
|
|
@@ -4989,7 +5031,7 @@ async function deregisterDataSource(opts) {
|
|
|
4989
5031
|
if (err instanceof import_errors8.AbloError && err.code === "entity_not_found") return { removed: false };
|
|
4990
5032
|
if (err instanceof import_errors8.AbloError && err.code === "forbidden") {
|
|
4991
5033
|
throw new import_errors8.AbloPermissionError(
|
|
4992
|
-
`${err.message}. Disconnecting needs a secret key (sk_\u2026)
|
|
5034
|
+
`${err.message}. Disconnecting needs a branch-bound secret key (sk_\u2026).`,
|
|
4993
5035
|
{
|
|
4994
5036
|
code: "forbidden",
|
|
4995
5037
|
...err.requestId !== void 0 ? { requestId: err.requestId } : {}
|
|
@@ -4999,7 +5041,7 @@ async function deregisterDataSource(opts) {
|
|
|
4999
5041
|
throw err;
|
|
5000
5042
|
}
|
|
5001
5043
|
}
|
|
5002
|
-
function renderDisconnected(response, project,
|
|
5044
|
+
function renderDisconnected(response, project, branchLabel) {
|
|
5003
5045
|
const parts = [];
|
|
5004
5046
|
if (response.cleared.direct) parts.push("the direct database registration");
|
|
5005
5047
|
if (response.cleared.endpoints > 0) {
|
|
@@ -5010,7 +5052,7 @@ function renderDisconnected(response, project, envLabel) {
|
|
|
5010
5052
|
const what = parts.length > 0 ? parts.join(" and ") : "the data source";
|
|
5011
5053
|
console.log(
|
|
5012
5054
|
`
|
|
5013
|
-
${import_picocolors8.default.green("\u2713")} Disconnected ${what} for ${import_picocolors8.default.bold(project)}
|
|
5055
|
+
${import_picocolors8.default.green("\u2713")} Disconnected ${what} for ${import_picocolors8.default.bold(project)} on ${branchLabel}. Reconnect with ${import_picocolors8.default.bold("ablo connect")}.
|
|
5014
5056
|
`
|
|
5015
5057
|
);
|
|
5016
5058
|
const slot = response.replication_slot;
|
|
@@ -5019,14 +5061,27 @@ function renderDisconnected(response, project, envLabel) {
|
|
|
5019
5061
|
` ${import_picocolors8.default.yellow("!")} ${slot.warning ?? `The replication slot ${import_picocolors8.default.bold(slot.slot)} is still on your database and still holding your write-ahead log. Remove it yourself \u2014 nothing will release it now.`}`
|
|
5020
5062
|
);
|
|
5021
5063
|
if (slot.detail) console.log(import_picocolors8.default.dim(` ${slot.detail}`));
|
|
5022
|
-
|
|
5064
|
+
console.log(
|
|
5065
|
+
import_picocolors8.default.dim(
|
|
5066
|
+
` Moving this database to another branch? Keep the roles and slot; run ${import_picocolors8.default.bold("ablo connect rotate --env-file .env.local --yes")} to re-key and reuse them.`
|
|
5067
|
+
)
|
|
5068
|
+
);
|
|
5069
|
+
if (slot.remove_with) {
|
|
5070
|
+
console.log(import_picocolors8.default.dim(" Not reconnecting this database? Remove the unused slot in your SQL editor:"));
|
|
5071
|
+
console.log(` ${import_picocolors8.default.bold(slot.remove_with)}`);
|
|
5072
|
+
}
|
|
5023
5073
|
console.log();
|
|
5024
5074
|
}
|
|
5025
5075
|
}
|
|
5026
5076
|
async function disconnect(argv) {
|
|
5027
5077
|
let skipConfirm = false;
|
|
5028
|
-
|
|
5078
|
+
let envFile;
|
|
5079
|
+
let keyEnv;
|
|
5080
|
+
for (let i = 0; i < argv.length; i++) {
|
|
5081
|
+
const arg = argv[i];
|
|
5029
5082
|
if (arg === "--yes" || arg === "-y") skipConfirm = true;
|
|
5083
|
+
else if (arg === "--env-file") envFile = argv[++i];
|
|
5084
|
+
else if (arg === "--key-env") keyEnv = argv[++i];
|
|
5030
5085
|
else if (arg === "--help" || arg === "-h") {
|
|
5031
5086
|
console.log(DISCONNECT_USAGE);
|
|
5032
5087
|
return;
|
|
@@ -5042,19 +5097,39 @@ async function disconnect(argv) {
|
|
|
5042
5097
|
${brand("ablo")} ${import_picocolors8.default.dim("connect deregister")} ${import_picocolors8.default.dim("remove this project's data source")}
|
|
5043
5098
|
`
|
|
5044
5099
|
);
|
|
5045
|
-
|
|
5100
|
+
if (envFile) {
|
|
5101
|
+
try {
|
|
5102
|
+
process.loadEnvFile(envFile);
|
|
5103
|
+
} catch (error) {
|
|
5104
|
+
throw new import_errors8.AbloValidationError(
|
|
5105
|
+
`could not load --env-file ${envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5106
|
+
{ code: "cli_invalid_arguments" }
|
|
5107
|
+
);
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
const selected = keyEnv ? readProjectEnvVariable(keyEnv) : null;
|
|
5111
|
+
if (keyEnv && !selected) {
|
|
5112
|
+
throw new import_errors8.AbloAuthenticationError(
|
|
5113
|
+
`No value named ${keyEnv} was found in the process environment, .env.local, or .env.`,
|
|
5114
|
+
{ code: "cli_api_key_missing" }
|
|
5115
|
+
);
|
|
5116
|
+
}
|
|
5117
|
+
const resolved = selected ? { key: selected.value, source: selected.source } : {
|
|
5118
|
+
key: resolveMutationApiKey(),
|
|
5119
|
+
source: envFile ? "explicit-file" : process.env.ABLO_API_KEY ? "env" : "stored"
|
|
5120
|
+
};
|
|
5046
5121
|
const apiKey = resolved.key;
|
|
5047
5122
|
const keySource = resolved.source ?? "stored";
|
|
5048
5123
|
if (!apiKey) {
|
|
5049
5124
|
throw new import_errors8.AbloAuthenticationError(
|
|
5050
|
-
"Disconnecting needs
|
|
5125
|
+
"Disconnecting needs a branch-bound sk_ key. Set ABLO_API_KEY, pass `--env-file .env.local`, or select a named recovery key with `--key-env <NAME>`.",
|
|
5051
5126
|
{ code: "cli_api_key_missing" }
|
|
5052
5127
|
);
|
|
5053
5128
|
}
|
|
5054
5129
|
const apiUrl3 = apiBaseUrl();
|
|
5055
5130
|
const target = await resolveTarget({ url: apiUrl3, apiKey, keySource });
|
|
5056
|
-
const { project,
|
|
5057
|
-
const
|
|
5131
|
+
const { project, branch } = planeLabel(target);
|
|
5132
|
+
const branchLabel = target.confirmed?.branchRoot ? import_picocolors8.default.yellow(branch) : import_picocolors8.default.dim(branch);
|
|
5058
5133
|
const divergence = describeMismatches(target.mismatches);
|
|
5059
5134
|
if (divergence) console.log(` ${import_picocolors8.default.yellow("\u26A0")} ${divergence}
|
|
5060
5135
|
`);
|
|
@@ -5066,7 +5141,7 @@ async function disconnect(argv) {
|
|
|
5066
5141
|
);
|
|
5067
5142
|
}
|
|
5068
5143
|
const proceed = await ye({
|
|
5069
|
-
message: `Disconnect the data source for ${import_picocolors8.default.bold(project)}
|
|
5144
|
+
message: `Disconnect the data source for ${import_picocolors8.default.bold(project)} on ${branchLabel}?`,
|
|
5070
5145
|
initialValue: true
|
|
5071
5146
|
});
|
|
5072
5147
|
if (pD(proceed) || !proceed) {
|
|
@@ -5077,11 +5152,11 @@ async function disconnect(argv) {
|
|
|
5077
5152
|
}
|
|
5078
5153
|
const outcome = await deregisterDataSource({ apiKey });
|
|
5079
5154
|
if (!outcome.removed) {
|
|
5080
|
-
console.log(import_picocolors8.default.dim(` No data source registered for ${project}
|
|
5155
|
+
console.log(import_picocolors8.default.dim(` No data source registered for ${project} on ${branch}.
|
|
5081
5156
|
`));
|
|
5082
5157
|
return;
|
|
5083
5158
|
}
|
|
5084
|
-
renderDisconnected(outcome.response, project,
|
|
5159
|
+
renderDisconnected(outcome.response, project, branchLabel);
|
|
5085
5160
|
}
|
|
5086
5161
|
var import_picocolors8, import_errors8, import_wire4, DISCONNECT_USAGE;
|
|
5087
5162
|
var init_disconnect = __esm({
|
|
@@ -5093,6 +5168,7 @@ var init_disconnect = __esm({
|
|
|
5093
5168
|
import_errors8 = require("@abloatai/transaction/errors");
|
|
5094
5169
|
import_wire4 = require("@abloatai/transaction/wire");
|
|
5095
5170
|
init_config();
|
|
5171
|
+
init_dbRole();
|
|
5096
5172
|
init_controlPlane();
|
|
5097
5173
|
init_theme();
|
|
5098
5174
|
init_target();
|
|
@@ -5101,9 +5177,10 @@ var init_disconnect = __esm({
|
|
|
5101
5177
|
Usage
|
|
5102
5178
|
npx ablo connect deregister Remove the active project's data source (confirms first)
|
|
5103
5179
|
npx ablo connect deregister --yes Skip the confirmation
|
|
5180
|
+
npx ablo connect deregister --key-env OLD_KEY_NAME --yes
|
|
5104
5181
|
|
|
5105
|
-
Acts on
|
|
5106
|
-
|
|
5182
|
+
Acts on exactly the server-confirmed project and branch bound to the key, shown
|
|
5183
|
+
before it runs. Removes the registration and
|
|
5107
5184
|
Ablo's replication state for that plane, so Ablo stops reading and writing the
|
|
5108
5185
|
database. Reconnect with ${import_picocolors8.default.bold("ablo connect")}.`;
|
|
5109
5186
|
}
|
|
@@ -5600,7 +5677,8 @@ function rotateWithoutConnection(input) {
|
|
|
5600
5677
|
return "Ablo did not accept this API key, so it cannot be told about a new password. Rotate changes the password in your database first, so running it with a key Ablo refuses would leave the database on a password nobody holds.";
|
|
5601
5678
|
}
|
|
5602
5679
|
if (!input.known || input.planeHasConnection) return null;
|
|
5603
|
-
|
|
5680
|
+
if (input.existingRoles.length > 0) return null;
|
|
5681
|
+
return "This plane has no connected database and Ablo's roles are not in this database, so there is no credential to re-key. Connecting for the first time is `ablo connect apply`, which creates the roles and registers them in one run.";
|
|
5604
5682
|
}
|
|
5605
5683
|
async function locateExistingConnection(input) {
|
|
5606
5684
|
const result = await tryControlPlane({
|
|
@@ -5678,7 +5756,7 @@ async function executePlan(sql, steps, rebuildPlaintext) {
|
|
|
5678
5756
|
async function runConnectApply(args) {
|
|
5679
5757
|
const rotating = args.rotate;
|
|
5680
5758
|
const verb = rotating ? "connect rotate" : "connect apply";
|
|
5681
|
-
|
|
5759
|
+
let adminUrl = args.url ?? readProjectAdminDatabaseUrl();
|
|
5682
5760
|
if (!adminUrl) {
|
|
5683
5761
|
throw new import_errors9.AbloValidationError(
|
|
5684
5762
|
"No admin connection string. Pass --url <admin-conn> (or set DATABASE_URL) and re-run.",
|
|
@@ -5692,15 +5770,22 @@ async function runConnectApply(args) {
|
|
|
5692
5770
|
target = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
|
|
5693
5771
|
} catch {
|
|
5694
5772
|
}
|
|
5695
|
-
const apiKey =
|
|
5773
|
+
const apiKey = resolveMutationApiKey();
|
|
5696
5774
|
if (!apiKey) {
|
|
5697
5775
|
const loggedIn = resolveManagementKey() !== void 0;
|
|
5776
|
+
const ambient = ambientEnvKeyNote();
|
|
5777
|
+
const retry = `npx ablo connect ${rotating ? "rotate" : "apply"} --env-file .env.local --yes`;
|
|
5698
5778
|
throw new import_errors9.AbloAuthenticationError(
|
|
5699
|
-
loggedIn ? `You are logged in, but
|
|
5779
|
+
loggedIn ? `You are logged in, but connect needs a branch-bound runtime key.
|
|
5780
|
+
|
|
5781
|
+
Logging in stores an mk_ management credential; it can manage branches but cannot read, write, or register a database. Set ABLO_API_KEY to the sk_ key for the exact branch this database should join. The server confirms whether that branch is the production root or a development child; the CLI does not infer it from the key spelling.${ambient ? `
|
|
5700
5782
|
|
|
5701
|
-
|
|
5783
|
+
${ambient}
|
|
5702
5784
|
|
|
5703
|
-
|
|
5785
|
+
Use it explicitly with:
|
|
5786
|
+
${retry}` : ""}` : `Not logged in, and no ABLO_API_KEY is set. Run \`ablo login\` (or set ABLO_API_KEY) so Ablo knows which project to register this database for.${ambient ? `
|
|
5787
|
+
|
|
5788
|
+
${ambient}` : ""}`,
|
|
5704
5789
|
{ code: "cli_api_key_missing" }
|
|
5705
5790
|
);
|
|
5706
5791
|
}
|
|
@@ -5715,23 +5800,39 @@ Mint a sandbox key with \`npx ablo dev\`, or set ABLO_API_KEY to the key of the
|
|
|
5715
5800
|
);
|
|
5716
5801
|
const pooledAdmin = detectPooler(adminUrl);
|
|
5717
5802
|
if (pooledAdmin?.confidence === "host") {
|
|
5718
|
-
|
|
5719
|
-
|
|
5803
|
+
if (pooledAdmin.direct) {
|
|
5804
|
+
adminUrl = pooledAdmin.direct;
|
|
5805
|
+
const pooledLabel = target;
|
|
5806
|
+
try {
|
|
5807
|
+
const parsed = new URL(adminUrl);
|
|
5808
|
+
target = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
|
|
5809
|
+
} catch {
|
|
5810
|
+
}
|
|
5811
|
+
console.log(
|
|
5812
|
+
` ${import_picocolors11.default.yellow("!")} ${import_picocolors11.default.bold(pooledLabel)} is a connection pooler, so this run uses the direct host:
|
|
5813
|
+
${import_picocolors11.default.bold(target)}
|
|
5814
|
+
` + import_picocolors11.default.dim(
|
|
5815
|
+
` A pooler terminates the session, so replication cannot run over it. Your app
|
|
5816
|
+
keeps the pooled URL; the setup needs the database itself.
|
|
5720
5817
|
`
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5818
|
+
)
|
|
5819
|
+
);
|
|
5820
|
+
} else {
|
|
5821
|
+
console.error(
|
|
5822
|
+
` ${import_picocolors11.default.yellow("!")} ${import_picocolors11.default.bold(target)} is a connection pooler, not the database.
|
|
5726
5823
|
`
|
|
5727
|
-
)
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5824
|
+
);
|
|
5825
|
+
console.error(
|
|
5826
|
+
import_picocolors11.default.dim(
|
|
5827
|
+
` A pooler terminates the session, so replication cannot run over it. Setting up
|
|
5828
|
+
through it creates roles that Ablo then cannot use to stream.
|
|
5732
5829
|
`
|
|
5733
|
-
|
|
5734
|
-
|
|
5830
|
+
)
|
|
5831
|
+
);
|
|
5832
|
+
console.error(` Re-run against the direct database host, not the pooled one.
|
|
5833
|
+
`);
|
|
5834
|
+
process.exit(1);
|
|
5835
|
+
}
|
|
5735
5836
|
}
|
|
5736
5837
|
if (pooledAdmin?.confidence === "port") {
|
|
5737
5838
|
console.log(
|
|
@@ -5771,31 +5872,31 @@ Mint a sandbox key with \`npx ablo dev\`, or set ABLO_API_KEY to the key of the
|
|
|
5771
5872
|
`);
|
|
5772
5873
|
console.error(
|
|
5773
5874
|
import_picocolors11.default.dim(` Your database is untouched.
|
|
5774
|
-
`) + ` To move it here, disconnect it there first with ${import_picocolors11.default.cyan("ablo connect deregister")}
|
|
5775
|
-
`
|
|
5875
|
+
`) + ` To move it here, disconnect it there first with ${import_picocolors11.default.cyan("ablo connect deregister")}
|
|
5876
|
+
` + import_picocolors11.default.dim(` (run with a key for that plane). Match the project id to a name with `) + import_picocolors11.default.bold("ablo projects list --json") + import_picocolors11.default.dim(".") + "\n"
|
|
5776
5877
|
);
|
|
5777
5878
|
process.exit(1);
|
|
5778
5879
|
}
|
|
5880
|
+
let rotatePlane = null;
|
|
5779
5881
|
if (rotating) {
|
|
5780
5882
|
const state = await fetchDataSourceState(apiBaseUrl(), apiKey).catch(
|
|
5781
5883
|
() => ({ kind: "unknown", detail: "unreachable" })
|
|
5782
5884
|
);
|
|
5783
|
-
|
|
5784
|
-
rotating,
|
|
5885
|
+
rotatePlane = {
|
|
5785
5886
|
planeHasConnection: state.kind === "connected",
|
|
5786
5887
|
known: state.kind !== "unknown",
|
|
5787
5888
|
// 401/403 is Ablo answering and declining the key, not a network failure.
|
|
5788
5889
|
keyRejected: state.kind === "unknown" && /HTTP 40[13]/.test(state.detail)
|
|
5789
|
-
}
|
|
5790
|
-
if (
|
|
5791
|
-
|
|
5890
|
+
};
|
|
5891
|
+
if (rotatePlane.keyRejected) {
|
|
5892
|
+
const refusal = rotateWithoutConnection({ rotating, ...rotatePlane, existingRoles: [] });
|
|
5893
|
+
if (refusal) {
|
|
5894
|
+
console.error(` ${import_picocolors11.default.yellow("!")} ${refusal}
|
|
5792
5895
|
`);
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
);
|
|
5798
|
-
process.exit(1);
|
|
5896
|
+
console.error(import_picocolors11.default.dim(` Your database is untouched.
|
|
5897
|
+
`));
|
|
5898
|
+
process.exit(1);
|
|
5899
|
+
}
|
|
5799
5900
|
}
|
|
5800
5901
|
}
|
|
5801
5902
|
const admin = src_default(adminUrl, {
|
|
@@ -5855,9 +5956,21 @@ Mint a sandbox key with \`npx ablo dev\`, or set ABLO_API_KEY to the key of the
|
|
|
5855
5956
|
const pubReconcile = reconcilePublicationPlan(existingPublication, tables);
|
|
5856
5957
|
const role = args.role && args.role.length > 0 ? args.role : import_footprint.ABLO_REPLICATION_ROLE;
|
|
5857
5958
|
const writeRole = args.writeRole && args.writeRole.length > 0 ? args.writeRole : import_footprint.ABLO_WRITE_ROLE;
|
|
5959
|
+
const existingRoles = await presentRoles(admin, [role, writeRole]).catch(() => []);
|
|
5960
|
+
if (rotatePlane) {
|
|
5961
|
+
const refusal = rotateWithoutConnection({ rotating, ...rotatePlane, existingRoles });
|
|
5962
|
+
if (refusal) {
|
|
5963
|
+
await admin.end({ timeout: 2 });
|
|
5964
|
+
console.error(` ${import_picocolors11.default.yellow("!")} ${refusal}
|
|
5965
|
+
`);
|
|
5966
|
+
console.error(import_picocolors11.default.dim(` Your database is untouched.
|
|
5967
|
+
`));
|
|
5968
|
+
process.exit(1);
|
|
5969
|
+
}
|
|
5970
|
+
}
|
|
5858
5971
|
const blocker = reapplyBlocker({
|
|
5859
5972
|
rotating,
|
|
5860
|
-
existingRoles
|
|
5973
|
+
existingRoles
|
|
5861
5974
|
});
|
|
5862
5975
|
if (blocker) {
|
|
5863
5976
|
await admin.end({ timeout: 2 });
|
|
@@ -6077,9 +6190,11 @@ function parseConnectArgs(argv) {
|
|
|
6077
6190
|
let apply = false;
|
|
6078
6191
|
let rotate = false;
|
|
6079
6192
|
let url;
|
|
6193
|
+
let envFile;
|
|
6080
6194
|
let yes = false;
|
|
6081
6195
|
let showSql = false;
|
|
6082
6196
|
let scan = false;
|
|
6197
|
+
let locate = false;
|
|
6083
6198
|
let manual = false;
|
|
6084
6199
|
let tables = [];
|
|
6085
6200
|
let role = import_footprint.ABLO_REPLICATION_ROLE;
|
|
@@ -6104,9 +6219,12 @@ function parseConnectArgs(argv) {
|
|
|
6104
6219
|
case "scan":
|
|
6105
6220
|
scan = true;
|
|
6106
6221
|
break;
|
|
6222
|
+
case "locate":
|
|
6223
|
+
locate = true;
|
|
6224
|
+
break;
|
|
6107
6225
|
default:
|
|
6108
6226
|
throw new import_errors10.AbloValidationError(
|
|
6109
|
-
`unknown connect subcommand: ${lead} (expected register, deregister, check, apply, rotate, scan)`,
|
|
6227
|
+
`unknown connect subcommand: ${lead} (expected register, deregister, check, apply, rotate, scan, locate)`,
|
|
6110
6228
|
{ code: "cli_invalid_arguments" }
|
|
6111
6229
|
);
|
|
6112
6230
|
}
|
|
@@ -6118,6 +6236,9 @@ function parseConnectArgs(argv) {
|
|
|
6118
6236
|
case "--url":
|
|
6119
6237
|
url = argv[++i] ?? url;
|
|
6120
6238
|
break;
|
|
6239
|
+
case "--env-file":
|
|
6240
|
+
envFile = argv[++i] ?? envFile;
|
|
6241
|
+
break;
|
|
6121
6242
|
case "--yes":
|
|
6122
6243
|
case "-y":
|
|
6123
6244
|
yes = true;
|
|
@@ -6165,9 +6286,11 @@ function parseConnectArgs(argv) {
|
|
|
6165
6286
|
apply,
|
|
6166
6287
|
rotate,
|
|
6167
6288
|
url,
|
|
6289
|
+
envFile,
|
|
6168
6290
|
yes,
|
|
6169
6291
|
showSql,
|
|
6170
6292
|
scan,
|
|
6293
|
+
locate,
|
|
6171
6294
|
tables,
|
|
6172
6295
|
role,
|
|
6173
6296
|
writeRole,
|
|
@@ -6463,10 +6586,13 @@ async function runCheck() {
|
|
|
6463
6586
|
${brand("ablo")} ${import_picocolors12.default.dim("connect check")} ${import_picocolors12.default.dim("direct-write + WAL readiness")}
|
|
6464
6587
|
`
|
|
6465
6588
|
);
|
|
6466
|
-
const apiKey =
|
|
6589
|
+
const apiKey = resolveRuntimeApiKey().key;
|
|
6467
6590
|
if (!apiKey) {
|
|
6591
|
+
const ambient = ambientEnvKeyNote();
|
|
6468
6592
|
throw new import_errors10.AbloAuthenticationError(
|
|
6469
|
-
|
|
6593
|
+
`No branch-bound runtime key found. Set ABLO_API_KEY to the sk_ key for the branch to check, or pass \`--env-file .env.local\` explicitly.${ambient ? `
|
|
6594
|
+
|
|
6595
|
+
${ambient}` : ""}`,
|
|
6470
6596
|
{ code: "cli_api_key_missing" }
|
|
6471
6597
|
);
|
|
6472
6598
|
}
|
|
@@ -6529,10 +6655,13 @@ async function runCheck() {
|
|
|
6529
6655
|
async function runRegister(args) {
|
|
6530
6656
|
const dbUrl = requireScopedUrl("replication", "register");
|
|
6531
6657
|
const writeDbUrl = requireScopedUrl("write", "register");
|
|
6532
|
-
const apiKey =
|
|
6658
|
+
const apiKey = resolveMutationApiKey();
|
|
6533
6659
|
if (!apiKey) {
|
|
6660
|
+
const ambient = ambientEnvKeyNote();
|
|
6534
6661
|
throw new import_errors10.AbloAuthenticationError(
|
|
6535
|
-
|
|
6662
|
+
`No branch-bound runtime key found. Set ABLO_API_KEY to the sk_ key for the branch to register, or pass \`--env-file .env.local\` explicitly.${ambient ? `
|
|
6663
|
+
|
|
6664
|
+
${ambient}` : ""}`,
|
|
6536
6665
|
{ code: "cli_api_key_missing" }
|
|
6537
6666
|
);
|
|
6538
6667
|
}
|
|
@@ -6633,6 +6762,62 @@ async function runScan() {
|
|
|
6633
6762
|
}
|
|
6634
6763
|
process.exit(retired.length > 0 ? 1 : 0);
|
|
6635
6764
|
}
|
|
6765
|
+
async function runLocate(args) {
|
|
6766
|
+
console.log(
|
|
6767
|
+
`
|
|
6768
|
+
${brand("ablo")} ${import_picocolors12.default.dim("connect locate")} ${import_picocolors12.default.dim("which plane holds this database")}
|
|
6769
|
+
`
|
|
6770
|
+
);
|
|
6771
|
+
const url = args.url ?? readProjectAdminDatabaseUrl();
|
|
6772
|
+
if (!url) {
|
|
6773
|
+
throw new import_errors10.AbloValidationError(
|
|
6774
|
+
"Locating needs a connection string to identify the database. Pass --url <conn> (or set DATABASE_URL) and re-run.",
|
|
6775
|
+
{ code: "cli_database_url_missing" }
|
|
6776
|
+
);
|
|
6777
|
+
}
|
|
6778
|
+
const apiKey = resolveRuntimeApiKey().key;
|
|
6779
|
+
if (!apiKey) {
|
|
6780
|
+
const ambient = ambientEnvKeyNote();
|
|
6781
|
+
throw new import_errors10.AbloAuthenticationError(
|
|
6782
|
+
`No branch-bound runtime key found. Set ABLO_API_KEY to a key that can inspect this project, or pass \`--env-file .env.local\` explicitly.${ambient ? `
|
|
6783
|
+
|
|
6784
|
+
${ambient}` : ""}`,
|
|
6785
|
+
{ code: "cli_api_key_missing" }
|
|
6786
|
+
);
|
|
6787
|
+
}
|
|
6788
|
+
let label = "this database";
|
|
6789
|
+
try {
|
|
6790
|
+
const parsed = new URL(url);
|
|
6791
|
+
label = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
|
|
6792
|
+
} catch {
|
|
6793
|
+
}
|
|
6794
|
+
const answer = await requestControlPlane({
|
|
6795
|
+
path: "/v1/datasources/locate",
|
|
6796
|
+
method: "POST",
|
|
6797
|
+
apiKey,
|
|
6798
|
+
body: { connectionString: url },
|
|
6799
|
+
responseSchema: import_wire7.datasourceLocationResponseSchema
|
|
6800
|
+
});
|
|
6801
|
+
if (!answer.held) {
|
|
6802
|
+
console.log(
|
|
6803
|
+
` ${import_picocolors12.default.green("\u2713")} No plane holds ${import_picocolors12.default.bold(label)} \u2014 ${import_picocolors12.default.bold("ablo connect apply")} can register it here.
|
|
6804
|
+
`
|
|
6805
|
+
);
|
|
6806
|
+
return;
|
|
6807
|
+
}
|
|
6808
|
+
console.log(
|
|
6809
|
+
` ${import_picocolors12.default.yellow("!")} ${import_picocolors12.default.bold(label)} is connected to ${answer.held.project ? `project ${import_picocolors12.default.bold(answer.held.project)}, ` : ""}branch ${import_picocolors12.default.bold(answer.held.branch)}.
|
|
6810
|
+
`
|
|
6811
|
+
);
|
|
6812
|
+
console.log(
|
|
6813
|
+
import_picocolors12.default.dim(
|
|
6814
|
+
` Ablo streams a database from one plane at a time. To move it, disconnect it there
|
|
6815
|
+
first \u2014 run `
|
|
6816
|
+
) + import_picocolors12.default.cyan("ablo connect deregister") + import_picocolors12.default.dim(` with a key for that plane, then connect here.
|
|
6817
|
+
`) + import_picocolors12.default.dim(` Confirm a candidate key first with `) + import_picocolors12.default.bold("ablo whoami --key-env <NAME>") + import_picocolors12.default.dim(`.
|
|
6818
|
+
`) + import_picocolors12.default.dim(` Match the project id to a name with `) + import_picocolors12.default.bold("ablo projects list --json") + import_picocolors12.default.dim(".") + "\n"
|
|
6819
|
+
);
|
|
6820
|
+
}
|
|
6636
6821
|
async function connect(argv) {
|
|
6637
6822
|
if (argv[0] === "deregister") {
|
|
6638
6823
|
const { disconnect: disconnect2 } = await Promise.resolve().then(() => (init_disconnect(), disconnect_exports));
|
|
@@ -6640,6 +6825,16 @@ async function connect(argv) {
|
|
|
6640
6825
|
return;
|
|
6641
6826
|
}
|
|
6642
6827
|
const args = parseConnectArgs(argv);
|
|
6828
|
+
if (args.envFile) {
|
|
6829
|
+
try {
|
|
6830
|
+
process.loadEnvFile(args.envFile);
|
|
6831
|
+
} catch (error) {
|
|
6832
|
+
throw new import_errors10.AbloValidationError(
|
|
6833
|
+
`could not load --env-file ${args.envFile}: ${error instanceof Error ? error.message : String(error)}`,
|
|
6834
|
+
{ code: "cli_invalid_arguments" }
|
|
6835
|
+
);
|
|
6836
|
+
}
|
|
6837
|
+
}
|
|
6643
6838
|
if (args.apply || args.rotate) {
|
|
6644
6839
|
const { runConnectApply: runConnectApply2 } = await Promise.resolve().then(() => (init_connectApply(), connectApply_exports));
|
|
6645
6840
|
await runConnectApply2(args);
|
|
@@ -6657,6 +6852,10 @@ async function connect(argv) {
|
|
|
6657
6852
|
await runScan();
|
|
6658
6853
|
return;
|
|
6659
6854
|
}
|
|
6855
|
+
if (args.locate) {
|
|
6856
|
+
await runLocate(args);
|
|
6857
|
+
return;
|
|
6858
|
+
}
|
|
6660
6859
|
const credentialReachable = (args.url ?? readProjectAdminDatabaseUrl()) != null;
|
|
6661
6860
|
const canConfirm = process.stdout.isTTY || args.yes;
|
|
6662
6861
|
if (!args.manual && credentialReachable && canConfirm) {
|
|
@@ -6666,7 +6865,7 @@ async function connect(argv) {
|
|
|
6666
6865
|
}
|
|
6667
6866
|
printConnectRecipe(args);
|
|
6668
6867
|
}
|
|
6669
|
-
var import_errors10, import_picocolors12, import_footprint2, FOOTPRINT_LOOKUP, CONNECT_USAGE;
|
|
6868
|
+
var import_errors10, import_picocolors12, import_footprint2, import_wire7, FOOTPRINT_LOOKUP, CONNECT_USAGE;
|
|
6670
6869
|
var init_connect = __esm({
|
|
6671
6870
|
"src/connect.ts"() {
|
|
6672
6871
|
"use strict";
|
|
@@ -6678,6 +6877,7 @@ var init_connect = __esm({
|
|
|
6678
6877
|
init_dbRole();
|
|
6679
6878
|
init_config();
|
|
6680
6879
|
init_controlPlane();
|
|
6880
|
+
import_wire7 = require("@abloatai/transaction/wire");
|
|
6681
6881
|
init_theme();
|
|
6682
6882
|
init_remoteValidation();
|
|
6683
6883
|
init_connectSetup();
|
|
@@ -6701,6 +6901,7 @@ var init_connect = __esm({
|
|
|
6701
6901
|
npx ablo connect check Confirm the connected database is ready, from Ablo's side (needs only ABLO_API_KEY)
|
|
6702
6902
|
npx ablo connect rotate New passwords for both logins, then re-register
|
|
6703
6903
|
npx ablo connect scan List anything Ablo ever set up in your database (read-only, never drops)
|
|
6904
|
+
npx ablo connect locate See which plane holds this database (read-only; nothing is changed)
|
|
6704
6905
|
|
|
6705
6906
|
Running it: bare \`ablo connect\` sets everything up for you \u2014 creating the two
|
|
6706
6907
|
scoped logins, sharing your tables, and registering \u2014 whenever it finds a
|
|
@@ -6711,6 +6912,7 @@ var init_connect = __esm({
|
|
|
6711
6912
|
|
|
6712
6913
|
Modifiers:
|
|
6713
6914
|
--url <admin-conn> Admin connection used once to set up (else DATABASE_URL); never stored
|
|
6915
|
+
--env-file <path> Explicitly load DATABASE_URL and ABLO_API_KEY from this file
|
|
6714
6916
|
--tables a,b,c Publish only these tables (default: all tables)
|
|
6715
6917
|
--role <name> Name the replication role (default: ablo_replicator)
|
|
6716
6918
|
--write-role <name> Name the DML role (default: ablo_writer)
|
|
@@ -12601,8 +12803,8 @@ var require_typescript = __commonJS({
|
|
|
12601
12803
|
function createGetCanonicalFileName(useCaseSensitiveFileNames2) {
|
|
12602
12804
|
return useCaseSensitiveFileNames2 ? identity : toFileNameLowerCase;
|
|
12603
12805
|
}
|
|
12604
|
-
function patternText({ prefix
|
|
12605
|
-
return `${
|
|
12806
|
+
function patternText({ prefix, suffix }) {
|
|
12807
|
+
return `${prefix}*${suffix}`;
|
|
12606
12808
|
}
|
|
12607
12809
|
function matchedText(pattern, candidate) {
|
|
12608
12810
|
Debug.assert(isPatternMatch(pattern, candidate));
|
|
@@ -12621,17 +12823,17 @@ var require_typescript = __commonJS({
|
|
|
12621
12823
|
}
|
|
12622
12824
|
return matchedValue;
|
|
12623
12825
|
}
|
|
12624
|
-
function startsWith(str,
|
|
12625
|
-
return ignoreCase ? equateStringsCaseInsensitive(str.slice(0,
|
|
12826
|
+
function startsWith(str, prefix, ignoreCase) {
|
|
12827
|
+
return ignoreCase ? equateStringsCaseInsensitive(str.slice(0, prefix.length), prefix) : str.lastIndexOf(prefix, 0) === 0;
|
|
12626
12828
|
}
|
|
12627
|
-
function removePrefix(str,
|
|
12628
|
-
return startsWith(str,
|
|
12829
|
+
function removePrefix(str, prefix) {
|
|
12830
|
+
return startsWith(str, prefix) ? str.substr(prefix.length) : str;
|
|
12629
12831
|
}
|
|
12630
|
-
function tryRemovePrefix(str,
|
|
12631
|
-
return startsWith(getCanonicalFileName(str), getCanonicalFileName(
|
|
12832
|
+
function tryRemovePrefix(str, prefix, getCanonicalFileName = identity) {
|
|
12833
|
+
return startsWith(getCanonicalFileName(str), getCanonicalFileName(prefix)) ? str.substring(prefix.length) : void 0;
|
|
12632
12834
|
}
|
|
12633
|
-
function isPatternMatch({ prefix
|
|
12634
|
-
return candidate.length >=
|
|
12835
|
+
function isPatternMatch({ prefix, suffix }, candidate) {
|
|
12836
|
+
return candidate.length >= prefix.length + suffix.length && startsWith(candidate, prefix) && endsWith(candidate, suffix);
|
|
12635
12837
|
}
|
|
12636
12838
|
function and(f, g2) {
|
|
12637
12839
|
return (arg) => f(arg) && g2(arg);
|
|
@@ -18405,8 +18607,8 @@ ${lanes.join("\n")}
|
|
|
18405
18607
|
);
|
|
18406
18608
|
const firstComponent = pathComponents2[0];
|
|
18407
18609
|
if (isAbsolutePathAnUrl && isRootedDiskPath(firstComponent)) {
|
|
18408
|
-
const
|
|
18409
|
-
pathComponents2[0] =
|
|
18610
|
+
const prefix = firstComponent.charAt(0) === directorySeparator ? "file://" : "file:///";
|
|
18611
|
+
pathComponents2[0] = prefix + firstComponent;
|
|
18410
18612
|
}
|
|
18411
18613
|
return getPathFromPathComponents(pathComponents2);
|
|
18412
18614
|
}
|
|
@@ -35422,12 +35624,12 @@ ${lanes.join("\n")}
|
|
|
35422
35624
|
node.symbol = void 0;
|
|
35423
35625
|
return node;
|
|
35424
35626
|
}
|
|
35425
|
-
function createBaseGeneratedIdentifier(text, autoGenerateFlags,
|
|
35627
|
+
function createBaseGeneratedIdentifier(text, autoGenerateFlags, prefix, suffix) {
|
|
35426
35628
|
const node = createBaseIdentifier(escapeLeadingUnderscores(text));
|
|
35427
35629
|
setIdentifierAutoGenerate(node, {
|
|
35428
35630
|
flags: autoGenerateFlags,
|
|
35429
35631
|
id: nextAutoGenerateId,
|
|
35430
|
-
prefix
|
|
35632
|
+
prefix,
|
|
35431
35633
|
suffix
|
|
35432
35634
|
});
|
|
35433
35635
|
nextAutoGenerateId++;
|
|
@@ -35450,10 +35652,10 @@ ${lanes.join("\n")}
|
|
|
35450
35652
|
}
|
|
35451
35653
|
return node;
|
|
35452
35654
|
}
|
|
35453
|
-
function createTempVariable(recordTempVariable, reservedInNestedScopes,
|
|
35655
|
+
function createTempVariable(recordTempVariable, reservedInNestedScopes, prefix, suffix) {
|
|
35454
35656
|
let flags2 = 1;
|
|
35455
35657
|
if (reservedInNestedScopes) flags2 |= 8;
|
|
35456
|
-
const name = createBaseGeneratedIdentifier("", flags2,
|
|
35658
|
+
const name = createBaseGeneratedIdentifier("", flags2, prefix, suffix);
|
|
35457
35659
|
if (recordTempVariable) {
|
|
35458
35660
|
recordTempVariable(name);
|
|
35459
35661
|
}
|
|
@@ -35471,23 +35673,23 @@ ${lanes.join("\n")}
|
|
|
35471
35673
|
void 0
|
|
35472
35674
|
);
|
|
35473
35675
|
}
|
|
35474
|
-
function createUniqueName(text, flags2 = 0,
|
|
35676
|
+
function createUniqueName(text, flags2 = 0, prefix, suffix) {
|
|
35475
35677
|
Debug.assert(!(flags2 & 7), "Argument out of range: flags");
|
|
35476
35678
|
Debug.assert((flags2 & (16 | 32)) !== 32, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic");
|
|
35477
|
-
return createBaseGeneratedIdentifier(text, 3 | flags2,
|
|
35679
|
+
return createBaseGeneratedIdentifier(text, 3 | flags2, prefix, suffix);
|
|
35478
35680
|
}
|
|
35479
|
-
function getGeneratedNameForNode(node, flags2 = 0,
|
|
35681
|
+
function getGeneratedNameForNode(node, flags2 = 0, prefix, suffix) {
|
|
35480
35682
|
Debug.assert(!(flags2 & 7), "Argument out of range: flags");
|
|
35481
35683
|
const text = !node ? "" : isMemberName(node) ? formatGeneratedName(
|
|
35482
35684
|
/*privateName*/
|
|
35483
35685
|
false,
|
|
35484
|
-
|
|
35686
|
+
prefix,
|
|
35485
35687
|
node,
|
|
35486
35688
|
suffix,
|
|
35487
35689
|
idText
|
|
35488
35690
|
) : `generated@${getNodeId(node)}`;
|
|
35489
|
-
if (
|
|
35490
|
-
const name = createBaseGeneratedIdentifier(text, 4 | flags2,
|
|
35691
|
+
if (prefix || suffix) flags2 |= 16;
|
|
35692
|
+
const name = createBaseGeneratedIdentifier(text, 4 | flags2, prefix, suffix);
|
|
35491
35693
|
name.original = node;
|
|
35492
35694
|
return name;
|
|
35493
35695
|
}
|
|
@@ -35504,33 +35706,33 @@ ${lanes.join("\n")}
|
|
|
35504
35706
|
if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text);
|
|
35505
35707
|
return createBasePrivateIdentifier(escapeLeadingUnderscores(text));
|
|
35506
35708
|
}
|
|
35507
|
-
function createBaseGeneratedPrivateIdentifier(text, autoGenerateFlags,
|
|
35709
|
+
function createBaseGeneratedPrivateIdentifier(text, autoGenerateFlags, prefix, suffix) {
|
|
35508
35710
|
const node = createBasePrivateIdentifier(escapeLeadingUnderscores(text));
|
|
35509
35711
|
setIdentifierAutoGenerate(node, {
|
|
35510
35712
|
flags: autoGenerateFlags,
|
|
35511
35713
|
id: nextAutoGenerateId,
|
|
35512
|
-
prefix
|
|
35714
|
+
prefix,
|
|
35513
35715
|
suffix
|
|
35514
35716
|
});
|
|
35515
35717
|
nextAutoGenerateId++;
|
|
35516
35718
|
return node;
|
|
35517
35719
|
}
|
|
35518
|
-
function createUniquePrivateName(text,
|
|
35720
|
+
function createUniquePrivateName(text, prefix, suffix) {
|
|
35519
35721
|
if (text && !startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text);
|
|
35520
35722
|
const autoGenerateFlags = 8 | (text ? 3 : 1);
|
|
35521
|
-
return createBaseGeneratedPrivateIdentifier(text ?? "", autoGenerateFlags,
|
|
35723
|
+
return createBaseGeneratedPrivateIdentifier(text ?? "", autoGenerateFlags, prefix, suffix);
|
|
35522
35724
|
}
|
|
35523
|
-
function getGeneratedPrivateNameForNode(node,
|
|
35725
|
+
function getGeneratedPrivateNameForNode(node, prefix, suffix) {
|
|
35524
35726
|
const text = isMemberName(node) ? formatGeneratedName(
|
|
35525
35727
|
/*privateName*/
|
|
35526
35728
|
true,
|
|
35527
|
-
|
|
35729
|
+
prefix,
|
|
35528
35730
|
node,
|
|
35529
35731
|
suffix,
|
|
35530
35732
|
idText
|
|
35531
35733
|
) : `#generated@${getNodeId(node)}`;
|
|
35532
|
-
const flags2 =
|
|
35533
|
-
const name = createBaseGeneratedPrivateIdentifier(text, 4 | flags2,
|
|
35734
|
+
const flags2 = prefix || suffix ? 16 : 0;
|
|
35735
|
+
const name = createBaseGeneratedPrivateIdentifier(text, 4 | flags2, prefix, suffix);
|
|
35534
35736
|
name.original = node;
|
|
35535
35737
|
return name;
|
|
35536
35738
|
}
|
|
@@ -40332,13 +40534,13 @@ ${lanes.join("\n")}
|
|
|
40332
40534
|
[expr]
|
|
40333
40535
|
);
|
|
40334
40536
|
}
|
|
40335
|
-
function createSetFunctionNameHelper(f, name,
|
|
40537
|
+
function createSetFunctionNameHelper(f, name, prefix) {
|
|
40336
40538
|
context.requestEmitHelper(setFunctionNameHelper);
|
|
40337
40539
|
return context.factory.createCallExpression(
|
|
40338
40540
|
getUnscopedHelperName("__setFunctionName"),
|
|
40339
40541
|
/*typeArguments*/
|
|
40340
40542
|
void 0,
|
|
40341
|
-
|
|
40543
|
+
prefix ? [f, name, context.factory.createStringLiteral(prefix)] : [f, name]
|
|
40342
40544
|
);
|
|
40343
40545
|
}
|
|
40344
40546
|
function createValuesHelper(expression) {
|
|
@@ -42675,11 +42877,11 @@ ${lanes.join("\n")}
|
|
|
42675
42877
|
function formatIdentifierWorker(node, generateName) {
|
|
42676
42878
|
return isGeneratedPrivateIdentifier(node) ? generateName(node).slice(1) : isGeneratedIdentifier(node) ? generateName(node) : isPrivateIdentifier(node) ? node.escapedText.slice(1) : idText(node);
|
|
42677
42879
|
}
|
|
42678
|
-
function formatGeneratedName(privateName,
|
|
42679
|
-
|
|
42880
|
+
function formatGeneratedName(privateName, prefix, baseName, suffix, generateName) {
|
|
42881
|
+
prefix = formatGeneratedNamePart(prefix, generateName);
|
|
42680
42882
|
suffix = formatGeneratedNamePart(suffix, generateName);
|
|
42681
42883
|
baseName = formatIdentifier(baseName, generateName);
|
|
42682
|
-
return `${privateName ? "#" : ""}${
|
|
42884
|
+
return `${privateName ? "#" : ""}${prefix}${baseName}${suffix}`;
|
|
42683
42885
|
}
|
|
42684
42886
|
function createAccessorPropertyBackingField(factory2, node, modifiers, initializer) {
|
|
42685
42887
|
return factory2.updatePropertyDeclaration(
|
|
@@ -62754,11 +62956,11 @@ ${lanes.join("\n")}
|
|
|
62754
62956
|
candidates.push({ ending: void 0, value: relativeToBaseUrl });
|
|
62755
62957
|
}
|
|
62756
62958
|
if (indexOfStar !== -1) {
|
|
62757
|
-
const
|
|
62959
|
+
const prefix = pattern.substring(0, indexOfStar);
|
|
62758
62960
|
const suffix = pattern.substring(indexOfStar + 1);
|
|
62759
62961
|
for (const { ending, value } of candidates) {
|
|
62760
|
-
if (value.length >=
|
|
62761
|
-
const matchedStar = value.substring(
|
|
62962
|
+
if (value.length >= prefix.length + suffix.length && startsWith(value, prefix) && endsWith(value, suffix) && validateEnding({ ending, value })) {
|
|
62963
|
+
const matchedStar = value.substring(prefix.length, value.length - suffix.length);
|
|
62762
62964
|
if (!pathIsRelative(matchedStar)) {
|
|
62763
62965
|
return replaceFirstStar(key, matchedStar);
|
|
62764
62966
|
}
|
|
@@ -82457,9 +82659,9 @@ ${lanes.join("\n")}
|
|
|
82457
82659
|
}
|
|
82458
82660
|
secondaryRootErrors.unshift([mappedMsg, args[0], args[1]]);
|
|
82459
82661
|
} else {
|
|
82460
|
-
const
|
|
82662
|
+
const prefix = msg.code === Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code || msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code ? "new " : "";
|
|
82461
82663
|
const params = msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code || msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code ? "" : "...";
|
|
82462
|
-
path = `${
|
|
82664
|
+
path = `${prefix}${path}(${params})`;
|
|
82463
82665
|
}
|
|
82464
82666
|
break;
|
|
82465
82667
|
}
|
|
@@ -117301,13 +117503,13 @@ ${lanes.join("\n")}
|
|
|
117301
117503
|
}
|
|
117302
117504
|
function createHoistedVariableForClass(name, node, suffix) {
|
|
117303
117505
|
const { className } = getPrivateIdentifierEnvironment().data;
|
|
117304
|
-
const
|
|
117305
|
-
const identifier = typeof name === "object" ? factory2.getGeneratedNameForNode(name, 16 | 8,
|
|
117506
|
+
const prefix = className ? { prefix: "_", node: className, suffix: "_" } : "_";
|
|
117507
|
+
const identifier = typeof name === "object" ? factory2.getGeneratedNameForNode(name, 16 | 8, prefix, suffix) : typeof name === "string" ? factory2.createUniqueName(name, 16, prefix, suffix) : factory2.createTempVariable(
|
|
117306
117508
|
/*recordTempVariable*/
|
|
117307
117509
|
void 0,
|
|
117308
117510
|
/*reservedInNestedScopes*/
|
|
117309
117511
|
true,
|
|
117310
|
-
|
|
117512
|
+
prefix,
|
|
117311
117513
|
suffix
|
|
117312
117514
|
);
|
|
117313
117515
|
if (resolver.hasNodeCheckFlag(
|
|
@@ -118380,7 +118582,7 @@ ${lanes.join("\n")}
|
|
|
118380
118582
|
if (!decoratorExpressions) {
|
|
118381
118583
|
return void 0;
|
|
118382
118584
|
}
|
|
118383
|
-
const
|
|
118585
|
+
const prefix = getClassMemberPrefix(node, member);
|
|
118384
118586
|
const memberName = getExpressionForPropertyName(
|
|
118385
118587
|
member,
|
|
118386
118588
|
/*generateNameForComputedPropertyName*/
|
|
@@ -118393,7 +118595,7 @@ ${lanes.join("\n")}
|
|
|
118393
118595
|
const descriptor = isPropertyDeclaration(member) && !hasAccessorModifier(member) ? factory2.createVoidZero() : factory2.createNull();
|
|
118394
118596
|
const helper = emitHelpers().createDecorateHelper(
|
|
118395
118597
|
decoratorExpressions,
|
|
118396
|
-
|
|
118598
|
+
prefix,
|
|
118397
118599
|
memberName,
|
|
118398
118600
|
descriptor
|
|
118399
118601
|
);
|
|
@@ -120296,13 +120498,13 @@ ${lanes.join("\n")}
|
|
|
120296
120498
|
3072
|
|
120297
120499
|
/* NoComments */
|
|
120298
120500
|
);
|
|
120299
|
-
const
|
|
120501
|
+
const prefix = kind === "get" || kind === "set" ? kind : void 0;
|
|
120300
120502
|
const functionName = factory2.createStringLiteralFromNode(
|
|
120301
120503
|
name,
|
|
120302
120504
|
/*isSingleQuote*/
|
|
120303
120505
|
void 0
|
|
120304
120506
|
);
|
|
120305
|
-
const namedFunction = emitHelpers().createSetFunctionNameHelper(func, functionName,
|
|
120507
|
+
const namedFunction = emitHelpers().createSetFunctionNameHelper(func, functionName, prefix);
|
|
120306
120508
|
const method = factory2.createPropertyAssignment(factory2.createIdentifier(kind), namedFunction);
|
|
120307
120509
|
setOriginalNode(method, original);
|
|
120308
120510
|
setSourceMapRange(method, moveRangePastDecorators(original));
|
|
@@ -141082,9 +141284,9 @@ ${lanes.join("\n")}
|
|
|
141082
141284
|
emitExpression(node, parenthesizerRule);
|
|
141083
141285
|
}
|
|
141084
141286
|
}
|
|
141085
|
-
function emitNodeWithPrefix(
|
|
141287
|
+
function emitNodeWithPrefix(prefix, prefixWriter, node, emit2) {
|
|
141086
141288
|
if (node) {
|
|
141087
|
-
prefixWriter(
|
|
141289
|
+
prefixWriter(prefix);
|
|
141088
141290
|
emit2(node);
|
|
141089
141291
|
}
|
|
141090
141292
|
}
|
|
@@ -141822,10 +142024,10 @@ ${lanes.join("\n")}
|
|
|
141822
142024
|
return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name));
|
|
141823
142025
|
}
|
|
141824
142026
|
}
|
|
141825
|
-
function generateNameCached(node, privateName, flags,
|
|
142027
|
+
function generateNameCached(node, privateName, flags, prefix, suffix) {
|
|
141826
142028
|
const nodeId = getNodeId(node);
|
|
141827
142029
|
const cache = privateName ? nodeIdToGeneratedPrivateName : nodeIdToGeneratedName;
|
|
141828
|
-
return cache[nodeId] || (cache[nodeId] = generateNameForNode(node, privateName, flags ?? 0, formatGeneratedNamePart(
|
|
142030
|
+
return cache[nodeId] || (cache[nodeId] = generateNameForNode(node, privateName, flags ?? 0, formatGeneratedNamePart(prefix, generateName), formatGeneratedNamePart(suffix)));
|
|
141829
142031
|
}
|
|
141830
142032
|
function isUniqueName(name, privateName) {
|
|
141831
142033
|
return isFileLevelUniqueNameInCurrentFile(name, privateName) && !isReservedName(name, privateName) && !generatedNames.has(name);
|
|
@@ -141892,15 +142094,15 @@ ${lanes.join("\n")}
|
|
|
141892
142094
|
break;
|
|
141893
142095
|
}
|
|
141894
142096
|
}
|
|
141895
|
-
function makeTempVariableName(flags, reservedInNestedScopes, privateName,
|
|
141896
|
-
if (
|
|
141897
|
-
|
|
142097
|
+
function makeTempVariableName(flags, reservedInNestedScopes, privateName, prefix, suffix) {
|
|
142098
|
+
if (prefix.length > 0 && prefix.charCodeAt(0) === 35) {
|
|
142099
|
+
prefix = prefix.slice(1);
|
|
141898
142100
|
}
|
|
141899
|
-
const key = formatGeneratedName(privateName,
|
|
142101
|
+
const key = formatGeneratedName(privateName, prefix, "", suffix);
|
|
141900
142102
|
let tempFlags2 = getTempFlags(key);
|
|
141901
142103
|
if (flags && !(tempFlags2 & flags)) {
|
|
141902
142104
|
const name = flags === 268435456 ? "_i" : "_n";
|
|
141903
|
-
const fullName = formatGeneratedName(privateName,
|
|
142105
|
+
const fullName = formatGeneratedName(privateName, prefix, name, suffix);
|
|
141904
142106
|
if (isUniqueName(fullName, privateName)) {
|
|
141905
142107
|
tempFlags2 |= flags;
|
|
141906
142108
|
if (privateName) {
|
|
@@ -141917,7 +142119,7 @@ ${lanes.join("\n")}
|
|
|
141917
142119
|
tempFlags2++;
|
|
141918
142120
|
if (count !== 8 && count !== 13) {
|
|
141919
142121
|
const name = count < 26 ? "_" + String.fromCharCode(97 + count) : "_" + (count - 26);
|
|
141920
|
-
const fullName = formatGeneratedName(privateName,
|
|
142122
|
+
const fullName = formatGeneratedName(privateName, prefix, name, suffix);
|
|
141921
142123
|
if (isUniqueName(fullName, privateName)) {
|
|
141922
142124
|
if (privateName) {
|
|
141923
142125
|
reservePrivateNameInNestedScopes(fullName);
|
|
@@ -141930,15 +142132,15 @@ ${lanes.join("\n")}
|
|
|
141930
142132
|
}
|
|
141931
142133
|
}
|
|
141932
142134
|
}
|
|
141933
|
-
function makeUniqueName2(baseName, checkFn = isUniqueName, optimistic, scoped, privateName,
|
|
142135
|
+
function makeUniqueName2(baseName, checkFn = isUniqueName, optimistic, scoped, privateName, prefix, suffix) {
|
|
141934
142136
|
if (baseName.length > 0 && baseName.charCodeAt(0) === 35) {
|
|
141935
142137
|
baseName = baseName.slice(1);
|
|
141936
142138
|
}
|
|
141937
|
-
if (
|
|
141938
|
-
|
|
142139
|
+
if (prefix.length > 0 && prefix.charCodeAt(0) === 35) {
|
|
142140
|
+
prefix = prefix.slice(1);
|
|
141939
142141
|
}
|
|
141940
142142
|
if (optimistic) {
|
|
141941
|
-
const fullName = formatGeneratedName(privateName,
|
|
142143
|
+
const fullName = formatGeneratedName(privateName, prefix, baseName, suffix);
|
|
141942
142144
|
if (checkFn(fullName, privateName)) {
|
|
141943
142145
|
if (privateName) {
|
|
141944
142146
|
reservePrivateNameInNestedScopes(fullName);
|
|
@@ -141955,7 +142157,7 @@ ${lanes.join("\n")}
|
|
|
141955
142157
|
}
|
|
141956
142158
|
let i = 1;
|
|
141957
142159
|
while (true) {
|
|
141958
|
-
const fullName = formatGeneratedName(privateName,
|
|
142160
|
+
const fullName = formatGeneratedName(privateName, prefix, baseName + i, suffix);
|
|
141959
142161
|
if (checkFn(fullName, privateName)) {
|
|
141960
142162
|
if (privateName) {
|
|
141961
142163
|
reservePrivateNameInNestedScopes(fullName);
|
|
@@ -142052,7 +142254,7 @@ ${lanes.join("\n")}
|
|
|
142052
142254
|
""
|
|
142053
142255
|
);
|
|
142054
142256
|
}
|
|
142055
|
-
function generateNameForMethodOrAccessor(node, privateName,
|
|
142257
|
+
function generateNameForMethodOrAccessor(node, privateName, prefix, suffix) {
|
|
142056
142258
|
if (isIdentifier2(node.name)) {
|
|
142057
142259
|
return generateNameCached(node.name, privateName);
|
|
142058
142260
|
}
|
|
@@ -142061,11 +142263,11 @@ ${lanes.join("\n")}
|
|
|
142061
142263
|
/*reservedInNestedScopes*/
|
|
142062
142264
|
false,
|
|
142063
142265
|
privateName,
|
|
142064
|
-
|
|
142266
|
+
prefix,
|
|
142065
142267
|
suffix
|
|
142066
142268
|
);
|
|
142067
142269
|
}
|
|
142068
|
-
function generateNameForNode(node, privateName, flags,
|
|
142270
|
+
function generateNameForNode(node, privateName, flags, prefix, suffix) {
|
|
142069
142271
|
switch (node.kind) {
|
|
142070
142272
|
case 80:
|
|
142071
142273
|
case 81:
|
|
@@ -142075,20 +142277,20 @@ ${lanes.join("\n")}
|
|
|
142075
142277
|
!!(flags & 16),
|
|
142076
142278
|
!!(flags & 8),
|
|
142077
142279
|
privateName,
|
|
142078
|
-
|
|
142280
|
+
prefix,
|
|
142079
142281
|
suffix
|
|
142080
142282
|
);
|
|
142081
142283
|
case 267:
|
|
142082
142284
|
case 266:
|
|
142083
|
-
Debug.assert(!
|
|
142285
|
+
Debug.assert(!prefix && !suffix && !privateName);
|
|
142084
142286
|
return generateNameForModuleOrEnum(node);
|
|
142085
142287
|
case 272:
|
|
142086
142288
|
case 278:
|
|
142087
|
-
Debug.assert(!
|
|
142289
|
+
Debug.assert(!prefix && !suffix && !privateName);
|
|
142088
142290
|
return generateNameForImportOrExportDeclaration(node);
|
|
142089
142291
|
case 262:
|
|
142090
142292
|
case 263: {
|
|
142091
|
-
Debug.assert(!
|
|
142293
|
+
Debug.assert(!prefix && !suffix && !privateName);
|
|
142092
142294
|
const name = node.name;
|
|
142093
142295
|
if (name && !isGeneratedIdentifier(name)) {
|
|
142094
142296
|
return generateNameForNode(
|
|
@@ -142096,29 +142298,29 @@ ${lanes.join("\n")}
|
|
|
142096
142298
|
/*privateName*/
|
|
142097
142299
|
false,
|
|
142098
142300
|
flags,
|
|
142099
|
-
|
|
142301
|
+
prefix,
|
|
142100
142302
|
suffix
|
|
142101
142303
|
);
|
|
142102
142304
|
}
|
|
142103
142305
|
return generateNameForExportDefault();
|
|
142104
142306
|
}
|
|
142105
142307
|
case 277:
|
|
142106
|
-
Debug.assert(!
|
|
142308
|
+
Debug.assert(!prefix && !suffix && !privateName);
|
|
142107
142309
|
return generateNameForExportDefault();
|
|
142108
142310
|
case 231:
|
|
142109
|
-
Debug.assert(!
|
|
142311
|
+
Debug.assert(!prefix && !suffix && !privateName);
|
|
142110
142312
|
return generateNameForClassExpression();
|
|
142111
142313
|
case 174:
|
|
142112
142314
|
case 177:
|
|
142113
142315
|
case 178:
|
|
142114
|
-
return generateNameForMethodOrAccessor(node, privateName,
|
|
142316
|
+
return generateNameForMethodOrAccessor(node, privateName, prefix, suffix);
|
|
142115
142317
|
case 167:
|
|
142116
142318
|
return makeTempVariableName(
|
|
142117
142319
|
0,
|
|
142118
142320
|
/*reservedInNestedScopes*/
|
|
142119
142321
|
true,
|
|
142120
142322
|
privateName,
|
|
142121
|
-
|
|
142323
|
+
prefix,
|
|
142122
142324
|
suffix
|
|
142123
142325
|
);
|
|
142124
142326
|
default:
|
|
@@ -142127,18 +142329,18 @@ ${lanes.join("\n")}
|
|
|
142127
142329
|
/*reservedInNestedScopes*/
|
|
142128
142330
|
false,
|
|
142129
142331
|
privateName,
|
|
142130
|
-
|
|
142332
|
+
prefix,
|
|
142131
142333
|
suffix
|
|
142132
142334
|
);
|
|
142133
142335
|
}
|
|
142134
142336
|
}
|
|
142135
142337
|
function makeName(name) {
|
|
142136
142338
|
const autoGenerate = name.emitNode.autoGenerate;
|
|
142137
|
-
const
|
|
142339
|
+
const prefix = formatGeneratedNamePart(autoGenerate.prefix, generateName);
|
|
142138
142340
|
const suffix = formatGeneratedNamePart(autoGenerate.suffix);
|
|
142139
142341
|
switch (autoGenerate.flags & 7) {
|
|
142140
142342
|
case 1:
|
|
142141
|
-
return makeTempVariableName(0, !!(autoGenerate.flags & 8), isPrivateIdentifier(name),
|
|
142343
|
+
return makeTempVariableName(0, !!(autoGenerate.flags & 8), isPrivateIdentifier(name), prefix, suffix);
|
|
142142
142344
|
case 2:
|
|
142143
142345
|
Debug.assertNode(name, isIdentifier2);
|
|
142144
142346
|
return makeTempVariableName(
|
|
@@ -142146,7 +142348,7 @@ ${lanes.join("\n")}
|
|
|
142146
142348
|
!!(autoGenerate.flags & 8),
|
|
142147
142349
|
/*privateName*/
|
|
142148
142350
|
false,
|
|
142149
|
-
|
|
142351
|
+
prefix,
|
|
142150
142352
|
suffix
|
|
142151
142353
|
);
|
|
142152
142354
|
case 3:
|
|
@@ -142156,7 +142358,7 @@ ${lanes.join("\n")}
|
|
|
142156
142358
|
!!(autoGenerate.flags & 16),
|
|
142157
142359
|
!!(autoGenerate.flags & 8),
|
|
142158
142360
|
isPrivateIdentifier(name),
|
|
142159
|
-
|
|
142361
|
+
prefix,
|
|
142160
142362
|
suffix
|
|
142161
142363
|
);
|
|
142162
142364
|
}
|
|
@@ -158712,8 +158914,8 @@ ${lanes.join("\n")}
|
|
|
158712
158914
|
}
|
|
158713
158915
|
function buildLinkParts(link, checker) {
|
|
158714
158916
|
var _a;
|
|
158715
|
-
const
|
|
158716
|
-
const parts = [linkPart(`{@${
|
|
158917
|
+
const prefix = isJSDocLink(link) ? "link" : isJSDocLinkCode(link) ? "linkcode" : "linkplain";
|
|
158918
|
+
const parts = [linkPart(`{@${prefix} `)];
|
|
158717
158919
|
if (!link.name) {
|
|
158718
158920
|
if (link.text) {
|
|
158719
158921
|
parts.push(linkTextPart(link.text));
|
|
@@ -160186,9 +160388,9 @@ ${lanes.join("\n")}
|
|
|
160186
160388
|
let token = 0;
|
|
160187
160389
|
let lastNonTriviaToken = 0;
|
|
160188
160390
|
const templateStack = [];
|
|
160189
|
-
const { prefix
|
|
160190
|
-
text =
|
|
160191
|
-
const offset =
|
|
160391
|
+
const { prefix, pushTemplate } = getPrefixFromLexState(lexState);
|
|
160392
|
+
text = prefix + text;
|
|
160393
|
+
const offset = prefix.length;
|
|
160192
160394
|
if (pushTemplate) {
|
|
160193
160395
|
templateStack.push(
|
|
160194
160396
|
16
|
|
@@ -169346,11 +169548,11 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
169346
169548
|
if (decls && decls.some((d3) => d3.parent === scopeDecl)) {
|
|
169347
169549
|
return factory.createIdentifier(symbol.name);
|
|
169348
169550
|
}
|
|
169349
|
-
const
|
|
169350
|
-
if (
|
|
169551
|
+
const prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode2);
|
|
169552
|
+
if (prefix === void 0) {
|
|
169351
169553
|
return void 0;
|
|
169352
169554
|
}
|
|
169353
|
-
return isTypeNode2 ? factory.createQualifiedName(
|
|
169555
|
+
return isTypeNode2 ? factory.createQualifiedName(prefix, factory.createIdentifier(symbol.name)) : factory.createPropertyAccessExpression(prefix, symbol.name);
|
|
169354
169556
|
}
|
|
169355
169557
|
}
|
|
169356
169558
|
function getExtractableParent(node) {
|
|
@@ -170665,13 +170867,13 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
170665
170867
|
if (textChangeRange) {
|
|
170666
170868
|
if (version2 !== sourceFile.version) {
|
|
170667
170869
|
let newText;
|
|
170668
|
-
const
|
|
170870
|
+
const prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : "";
|
|
170669
170871
|
const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : "";
|
|
170670
170872
|
if (textChangeRange.newLength === 0) {
|
|
170671
|
-
newText =
|
|
170873
|
+
newText = prefix && suffix ? prefix + suffix : prefix || suffix;
|
|
170672
170874
|
} else {
|
|
170673
170875
|
const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength);
|
|
170674
|
-
newText =
|
|
170876
|
+
newText = prefix && suffix ? prefix + changedText + suffix : prefix ? prefix + changedText : changedText + suffix;
|
|
170675
170877
|
}
|
|
170676
170878
|
const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
|
|
170677
170879
|
setSourceFileFields(newSourceFile, scriptSnapshot, version2);
|
|
@@ -172801,8 +173003,8 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
172801
173003
|
const end = pos + 6;
|
|
172802
173004
|
const typeChecker = program.getTypeChecker();
|
|
172803
173005
|
const symbol = typeChecker.getSymbolAtLocation(node.parent);
|
|
172804
|
-
const
|
|
172805
|
-
return { text: `${
|
|
173006
|
+
const prefix = symbol ? `${typeChecker.symbolToString(symbol, node.parent)} ` : "";
|
|
173007
|
+
return { text: `${prefix}static {}`, pos, end };
|
|
172806
173008
|
}
|
|
172807
173009
|
const declName = isAssignedExpression(node) ? node.parent.name : Debug.checkDefined(getNameOfDeclaration(node), "Expected call hierarchy item to have a name");
|
|
172808
173010
|
let text = isIdentifier2(declName) ? idText(declName) : isStringOrNumericLiteralLike(declName) ? declName.text : isComputedPropertyName(declName) ? isStringOrNumericLiteralLike(declName.expression) ? declName.expression.text : void 0 : void 0;
|
|
@@ -176148,18 +176350,18 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
176148
176350
|
const commentNode = node.parent;
|
|
176149
176351
|
const { leftSibling, rightSibling } = getLeftAndRightSiblings(node);
|
|
176150
176352
|
let pos = commentNode.getStart();
|
|
176151
|
-
let
|
|
176353
|
+
let prefix = "";
|
|
176152
176354
|
if (!leftSibling && commentNode.comment) {
|
|
176153
176355
|
pos = findEndOfTextBetween(commentNode, commentNode.getStart(), node.getStart());
|
|
176154
|
-
|
|
176356
|
+
prefix = `${newLine} */${newLine}`;
|
|
176155
176357
|
}
|
|
176156
176358
|
if (leftSibling) {
|
|
176157
176359
|
if (fixAll && isJSDocTypedefTag(leftSibling)) {
|
|
176158
176360
|
pos = node.getStart();
|
|
176159
|
-
|
|
176361
|
+
prefix = "";
|
|
176160
176362
|
} else {
|
|
176161
176363
|
pos = findEndOfTextBetween(commentNode, leftSibling.getStart(), node.getStart());
|
|
176162
|
-
|
|
176364
|
+
prefix = `${newLine} */${newLine}`;
|
|
176163
176365
|
}
|
|
176164
176366
|
}
|
|
176165
176367
|
let end = commentNode.getEnd();
|
|
@@ -176173,7 +176375,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
176173
176375
|
suffix = `${newLine}/**${newLine} * `;
|
|
176174
176376
|
}
|
|
176175
176377
|
}
|
|
176176
|
-
changes.replaceRange(sourceFile, { pos, end }, declaration, { prefix
|
|
176378
|
+
changes.replaceRange(sourceFile, { pos, end }, declaration, { prefix, suffix });
|
|
176177
176379
|
}
|
|
176178
176380
|
function getLeftAndRightSiblings(typedefNode) {
|
|
176179
176381
|
const commentNode = typedefNode.parent;
|
|
@@ -180591,9 +180793,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
180591
180793
|
result.push(createDeleteFix(deletion, [Diagnostics.Remove_unused_declaration_for_Colon_0, name.getText(sourceFile)]));
|
|
180592
180794
|
}
|
|
180593
180795
|
}
|
|
180594
|
-
const
|
|
180595
|
-
if (
|
|
180596
|
-
result.push(createCodeFixAction(fixName3,
|
|
180796
|
+
const prefix = ts_textChanges_exports.ChangeTracker.with(context, (t) => tryPrefixDeclaration(t, errorCode, sourceFile, token));
|
|
180797
|
+
if (prefix.length) {
|
|
180798
|
+
result.push(createCodeFixAction(fixName3, prefix, [Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, Diagnostics.Prefix_all_unused_declarations_with_where_possible));
|
|
180597
180799
|
}
|
|
180598
180800
|
return result;
|
|
180599
180801
|
},
|
|
@@ -190294,9 +190496,9 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
190294
190496
|
function getDirectoryMatches(directoryName) {
|
|
190295
190497
|
return mapDefined(tryGetDirectories(host, directoryName), (dir) => dir === "node_modules" ? void 0 : directoryResult(dir));
|
|
190296
190498
|
}
|
|
190297
|
-
function trimPrefixAndSuffix(path,
|
|
190499
|
+
function trimPrefixAndSuffix(path, prefix) {
|
|
190298
190500
|
return firstDefined(matchingSuffixes, (suffix) => {
|
|
190299
|
-
const inner = withoutStartAndEnd(normalizePath(path),
|
|
190501
|
+
const inner = withoutStartAndEnd(normalizePath(path), prefix, suffix);
|
|
190300
190502
|
return inner === void 0 ? void 0 : removeLeadingDirectorySeparator(inner);
|
|
190301
190503
|
});
|
|
190302
190504
|
}
|
|
@@ -190329,7 +190531,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
190329
190531
|
if (!match) {
|
|
190330
190532
|
return void 0;
|
|
190331
190533
|
}
|
|
190332
|
-
const [,
|
|
190534
|
+
const [, prefix, kind, toComplete] = match;
|
|
190333
190535
|
const scriptPath = getDirectoryPath(sourceFile.path);
|
|
190334
190536
|
const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(
|
|
190335
190537
|
toComplete,
|
|
@@ -190342,7 +190544,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
|
|
|
190342
190544
|
true,
|
|
190343
190545
|
sourceFile.path
|
|
190344
190546
|
) : kind === "types" ? getCompletionEntriesFromTypings(program, host, moduleSpecifierResolutionHost, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, 1, sourceFile)) : Debug.fail();
|
|
190345
|
-
return addReplacementSpans(toComplete, range.pos +
|
|
190547
|
+
return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values()));
|
|
190346
190548
|
}
|
|
190347
190549
|
function getCompletionEntriesFromTypings(program, host, moduleSpecifierResolutionHost, scriptPath, fragmentDirectory, extensionOptions, result = createNameAndKindSet()) {
|
|
190348
190550
|
const options = program.getCompilerOptions();
|
|
@@ -196693,8 +196895,8 @@ ${content}
|
|
|
196693
196895
|
), spacePart()];
|
|
196694
196896
|
function getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, checker, enclosingDeclaration, sourceFile) {
|
|
196695
196897
|
const infos = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile);
|
|
196696
|
-
return map(infos, ({ isVariadic, parameters, prefix
|
|
196697
|
-
const prefixDisplayParts = [...callTargetDisplayParts, ...
|
|
196898
|
+
return map(infos, ({ isVariadic, parameters, prefix, suffix }) => {
|
|
196899
|
+
const prefixDisplayParts = [...callTargetDisplayParts, ...prefix];
|
|
196698
196900
|
const suffixDisplayParts = [...suffix, ...returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker)];
|
|
196699
196901
|
const documentation = candidateSignature.getDocumentationComment(checker);
|
|
196700
196902
|
const tags = candidateSignature.getJsDocTags();
|
|
@@ -198781,11 +198983,11 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
198781
198983
|
const noIndent = options.indentation !== void 0 || getLineStartPositionForPosition(pos, targetSourceFile) === pos ? text : text.replace(/^\s+/, "");
|
|
198782
198984
|
return (options.prefix || "") + noIndent + (!options.suffix || endsWith(noIndent, options.suffix) ? "" : options.suffix);
|
|
198783
198985
|
}
|
|
198784
|
-
function getFormattedTextOfNode(nodeIn, targetSourceFile, sourceFile, pos, { indentation, prefix
|
|
198986
|
+
function getFormattedTextOfNode(nodeIn, targetSourceFile, sourceFile, pos, { indentation, prefix, delta }, newLineCharacter, formatContext, validate) {
|
|
198785
198987
|
const { node, text } = getNonformattedText(nodeIn, targetSourceFile, newLineCharacter);
|
|
198786
198988
|
if (validate) validate(node, text);
|
|
198787
198989
|
const formatOptions = getFormatCodeSettingsForWriting(formatContext, targetSourceFile);
|
|
198788
|
-
const initialIndentation = indentation !== void 0 ? indentation : ts_formatting_exports.SmartIndenter.getIndentation(pos, sourceFile, formatOptions,
|
|
198990
|
+
const initialIndentation = indentation !== void 0 ? indentation : ts_formatting_exports.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || getLineStartPositionForPosition(pos, targetSourceFile) === pos);
|
|
198789
198991
|
if (delta === void 0) {
|
|
198790
198992
|
delta = ts_formatting_exports.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? formatOptions.indentSize || 0 : 0;
|
|
198791
198993
|
}
|
|
@@ -216510,9 +216712,9 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter
|
|
|
216510
216712
|
);
|
|
216511
216713
|
if (completions === void 0) return void 0;
|
|
216512
216714
|
if (kind === "completions-full") return completions;
|
|
216513
|
-
const
|
|
216715
|
+
const prefix = args.prefix || "";
|
|
216514
216716
|
const entries = mapDefined(completions.entries, (entry) => {
|
|
216515
|
-
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(),
|
|
216717
|
+
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
|
|
216516
216718
|
const convertedSpan = entry.replacementSpan ? toProtocolTextSpan(entry.replacementSpan, scriptInfo) : void 0;
|
|
216517
216719
|
return {
|
|
216518
216720
|
...entry,
|
|
@@ -221457,15 +221659,15 @@ var require_to_regex_range = __commonJS({
|
|
|
221457
221659
|
}
|
|
221458
221660
|
return tokens;
|
|
221459
221661
|
}
|
|
221460
|
-
function filterPatterns(arr, comparison,
|
|
221662
|
+
function filterPatterns(arr, comparison, prefix, intersection, options) {
|
|
221461
221663
|
let result = [];
|
|
221462
221664
|
for (let ele of arr) {
|
|
221463
221665
|
let { string } = ele;
|
|
221464
221666
|
if (!intersection && !contains(comparison, "string", string)) {
|
|
221465
|
-
result.push(
|
|
221667
|
+
result.push(prefix + string);
|
|
221466
221668
|
}
|
|
221467
221669
|
if (intersection && contains(comparison, "string", string)) {
|
|
221468
|
-
result.push(
|
|
221670
|
+
result.push(prefix + string);
|
|
221469
221671
|
}
|
|
221470
221672
|
}
|
|
221471
221673
|
return result;
|
|
@@ -221576,7 +221778,7 @@ var require_fill_range = __commonJS({
|
|
|
221576
221778
|
var toSequence = (parts, options, maxLen) => {
|
|
221577
221779
|
parts.negatives.sort((a, b4) => a < b4 ? -1 : a > b4 ? 1 : 0);
|
|
221578
221780
|
parts.positives.sort((a, b4) => a < b4 ? -1 : a > b4 ? 1 : 0);
|
|
221579
|
-
let
|
|
221781
|
+
let prefix = options.capture ? "" : "?:";
|
|
221580
221782
|
let positives = "";
|
|
221581
221783
|
let negatives = "";
|
|
221582
221784
|
let result;
|
|
@@ -221584,7 +221786,7 @@ var require_fill_range = __commonJS({
|
|
|
221584
221786
|
positives = parts.positives.map((v2) => toMaxLen(String(v2), maxLen)).join("|");
|
|
221585
221787
|
}
|
|
221586
221788
|
if (parts.negatives.length) {
|
|
221587
|
-
negatives = `-(${
|
|
221789
|
+
negatives = `-(${prefix}${parts.negatives.map((v2) => toMaxLen(String(v2), maxLen)).join("|")})`;
|
|
221588
221790
|
}
|
|
221589
221791
|
if (positives && negatives) {
|
|
221590
221792
|
result = `${positives}|${negatives}`;
|
|
@@ -221592,7 +221794,7 @@ var require_fill_range = __commonJS({
|
|
|
221592
221794
|
result = positives || negatives;
|
|
221593
221795
|
}
|
|
221594
221796
|
if (options.wrap) {
|
|
221595
|
-
return `(${
|
|
221797
|
+
return `(${prefix}${result})`;
|
|
221596
221798
|
}
|
|
221597
221799
|
return result;
|
|
221598
221800
|
};
|
|
@@ -221608,8 +221810,8 @@ var require_fill_range = __commonJS({
|
|
|
221608
221810
|
var toRegex = (start, end, options) => {
|
|
221609
221811
|
if (Array.isArray(start)) {
|
|
221610
221812
|
let wrap = options.wrap === true;
|
|
221611
|
-
let
|
|
221612
|
-
return wrap ? `(${
|
|
221813
|
+
let prefix = options.capture ? "" : "?:";
|
|
221814
|
+
return wrap ? `(${prefix}${start.join("|")})` : start.join("|");
|
|
221613
221815
|
}
|
|
221614
221816
|
return toRegexRange(start, end, options);
|
|
221615
221817
|
};
|
|
@@ -221731,20 +221933,20 @@ var require_compile = __commonJS({
|
|
|
221731
221933
|
const invalidBlock = utils.isInvalidBrace(parent);
|
|
221732
221934
|
const invalidNode = node.invalid === true && options.escapeInvalid === true;
|
|
221733
221935
|
const invalid = invalidBlock === true || invalidNode === true;
|
|
221734
|
-
const
|
|
221936
|
+
const prefix = options.escapeInvalid === true ? "\\" : "";
|
|
221735
221937
|
let output = "";
|
|
221736
221938
|
if (node.isOpen === true) {
|
|
221737
|
-
return
|
|
221939
|
+
return prefix + node.value;
|
|
221738
221940
|
}
|
|
221739
221941
|
if (node.isClose === true) {
|
|
221740
|
-
console.log("node.isClose",
|
|
221741
|
-
return
|
|
221942
|
+
console.log("node.isClose", prefix, node.value);
|
|
221943
|
+
return prefix + node.value;
|
|
221742
221944
|
}
|
|
221743
221945
|
if (node.type === "open") {
|
|
221744
|
-
return invalid ?
|
|
221946
|
+
return invalid ? prefix + node.value : "(";
|
|
221745
221947
|
}
|
|
221746
221948
|
if (node.type === "close") {
|
|
221747
|
-
return invalid ?
|
|
221949
|
+
return invalid ? prefix + node.value : ")";
|
|
221748
221950
|
}
|
|
221749
221951
|
if (node.type === "comma") {
|
|
221750
221952
|
return node.prev.type === "comma" ? "" : invalid ? node.value : "|";
|
|
@@ -222780,10 +222982,10 @@ var require_scan = __commonJS({
|
|
|
222780
222982
|
isGlob = false;
|
|
222781
222983
|
}
|
|
222782
222984
|
let base = str;
|
|
222783
|
-
let
|
|
222985
|
+
let prefix = "";
|
|
222784
222986
|
let glob = "";
|
|
222785
222987
|
if (start > 0) {
|
|
222786
|
-
|
|
222988
|
+
prefix = str.slice(0, start);
|
|
222787
222989
|
str = str.slice(start);
|
|
222788
222990
|
lastIndex -= start;
|
|
222789
222991
|
}
|
|
@@ -222808,7 +223010,7 @@ var require_scan = __commonJS({
|
|
|
222808
223010
|
}
|
|
222809
223011
|
}
|
|
222810
223012
|
const state = {
|
|
222811
|
-
prefix
|
|
223013
|
+
prefix,
|
|
222812
223014
|
input,
|
|
222813
223015
|
start,
|
|
222814
223016
|
base,
|
|
@@ -222837,7 +223039,7 @@ var require_scan = __commonJS({
|
|
|
222837
223039
|
if (opts.tokens) {
|
|
222838
223040
|
if (idx === 0 && start !== 0) {
|
|
222839
223041
|
tokens[idx].isPrefix = true;
|
|
222840
|
-
tokens[idx].value =
|
|
223042
|
+
tokens[idx].value = prefix;
|
|
222841
223043
|
} else {
|
|
222842
223044
|
tokens[idx].value = value;
|
|
222843
223045
|
}
|
|
@@ -227055,8 +227257,8 @@ ${nodeLocation}` : message2;
|
|
|
227055
227257
|
errors.ArgumentTypeError = ArgumentTypeError;
|
|
227056
227258
|
class PathNotFoundError extends BaseError {
|
|
227057
227259
|
path;
|
|
227058
|
-
constructor(path2,
|
|
227059
|
-
super(`${
|
|
227260
|
+
constructor(path2, prefix = "Path") {
|
|
227261
|
+
super(`${prefix} not found: ${path2}`);
|
|
227060
227262
|
this.path = path2;
|
|
227061
227263
|
}
|
|
227062
227264
|
code = "ENOENT";
|
|
@@ -282702,7 +282904,7 @@ Node text: ${this.#forgottenText}`;
|
|
|
282702
282904
|
// src/index.ts
|
|
282703
282905
|
init_cjs_shims();
|
|
282704
282906
|
init_dist2();
|
|
282705
|
-
var
|
|
282907
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
282706
282908
|
var import_fs13 = require("fs");
|
|
282707
282909
|
var import_path8 = require("path");
|
|
282708
282910
|
var import_child_process3 = require("child_process");
|
|
@@ -283374,32 +283576,26 @@ function parseDevArgs(argv) {
|
|
|
283374
283576
|
url,
|
|
283375
283577
|
apiKey: process.env.ABLO_API_KEY,
|
|
283376
283578
|
watch: watchEnabled,
|
|
283377
|
-
planeLabel: "
|
|
283579
|
+
planeLabel: "branch"
|
|
283378
283580
|
};
|
|
283379
283581
|
}
|
|
283380
283582
|
function classifyKey(apiKey) {
|
|
283381
283583
|
if (!apiKey) {
|
|
283382
283584
|
return {
|
|
283383
283585
|
ok: false,
|
|
283384
|
-
reason: `No API key. Run ${import_picocolors15.default.bold("npx ablo login")}, or set ${import_picocolors15.default.bold("ABLO_API_KEY")}
|
|
283385
|
-
};
|
|
283386
|
-
}
|
|
283387
|
-
if (apiKey.startsWith("sk_test_")) return { ok: true };
|
|
283388
|
-
if (apiKey.startsWith("sk_live_")) {
|
|
283389
|
-
return {
|
|
283390
|
-
ok: false,
|
|
283391
|
-
reason: `A ${import_picocolors15.default.bold("sk_live_")} key deploys production schema in one reviewed step: ${import_picocolors15.default.bold("npx ablo push")}. The ${import_picocolors15.default.bold("--watch")} loop runs on a ${import_picocolors15.default.bold("sk_test_")} key, which reaches the same API and the same schema over its own rows.`
|
|
283586
|
+
reason: `No API key. Run ${import_picocolors15.default.bold("npx ablo login")}, or set a branch-bound ${import_picocolors15.default.bold("ABLO_API_KEY")}. ${import_picocolors15.default.bold("npx ablo dev")} prepares a development branch.`
|
|
283392
283587
|
};
|
|
283393
283588
|
}
|
|
283589
|
+
if ((0, import_credentialPolicy2.classifyCredentialKind)(apiKey) === "secret") return { ok: true };
|
|
283394
283590
|
if ((0, import_credentialPolicy2.classifyCredentialKind)(apiKey) === "restricted") {
|
|
283395
283591
|
return {
|
|
283396
283592
|
ok: false,
|
|
283397
|
-
reason: `Authoring schema needs a secret
|
|
283593
|
+
reason: `Authoring schema needs a branch-bound secret ${import_picocolors15.default.bold("sk_")} key. ${import_picocolors15.default.bold("npx ablo dev")} prepares a development branch. A restricted ${import_picocolors15.default.bold("rk_")} key carries only the scopes it was minted with.`
|
|
283398
283594
|
};
|
|
283399
283595
|
}
|
|
283400
283596
|
return {
|
|
283401
283597
|
ok: false,
|
|
283402
|
-
reason: `${import_picocolors15.default.bold("ABLO_API_KEY")} is not
|
|
283598
|
+
reason: `${import_picocolors15.default.bold("ABLO_API_KEY")} is not a secret Ablo key. Expected a branch-bound ${import_picocolors15.default.bold("sk_\u2026")} credential. Run ${import_picocolors15.default.bold("npx ablo dev")} to prepare a development branch.`
|
|
283403
283599
|
};
|
|
283404
283600
|
}
|
|
283405
283601
|
function wireEnvLocal(apiKey, cwd = process.cwd()) {
|
|
@@ -283494,7 +283690,7 @@ async function runPush(schema, args) {
|
|
|
283494
283690
|
}
|
|
283495
283691
|
if (status2 === 403) {
|
|
283496
283692
|
const serverSays = body.message ?? body.reason;
|
|
283497
|
-
const hint = body.code === "database_role_cannot_enforce_rls" ? `Run ${import_picocolors15.default.bold("npx ablo migrate")} \u2014 it creates the scoped role for you (your DB credential never leaves this machine).` : `Schema authoring needs a ${import_picocolors15.default.bold("
|
|
283693
|
+
const hint = body.code === "database_role_cannot_enforce_rls" ? `Run ${import_picocolors15.default.bold("npx ablo migrate")} \u2014 it creates the scoped role for you (your DB credential never leaves this machine).` : `Schema authoring needs a branch-bound ${import_picocolors15.default.bold("sk_")} key with ${import_picocolors15.default.bold("schema:push")} \u2014 manage keys at ${import_picocolors15.default.cyan("https://abloatai.com")}.`;
|
|
283498
283694
|
return {
|
|
283499
283695
|
ok: false,
|
|
283500
283696
|
message: `${serverSays ?? "This key can't author schema (missing schema:push scope)."}
|
|
@@ -283520,7 +283716,7 @@ async function dev(argv, runtime = {}) {
|
|
|
283520
283716
|
process.exit(1);
|
|
283521
283717
|
}
|
|
283522
283718
|
if (runtime.apiKey) args.apiKey = runtime.apiKey;
|
|
283523
|
-
else if (!args.apiKey) args.apiKey =
|
|
283719
|
+
else if (!args.apiKey) args.apiKey = resolveRuntimeApiKey("sandbox").key;
|
|
283524
283720
|
if (runtime.branch) args.planeLabel = runtime.branch.slug;
|
|
283525
283721
|
const key = classifyKey(args.apiKey);
|
|
283526
283722
|
if (!key.ok) {
|
|
@@ -283549,7 +283745,7 @@ async function dev(argv, runtime = {}) {
|
|
|
283549
283745
|
console.log(` ${import_picocolors15.default.dim("api")} ${args.url}
|
|
283550
283746
|
`);
|
|
283551
283747
|
const s = Y2();
|
|
283552
|
-
s.start("Pushing schema definition (
|
|
283748
|
+
s.start("Pushing schema definition (development branch)");
|
|
283553
283749
|
const first = await runPush(schema, args);
|
|
283554
283750
|
s.stop(first.message, first.ok ? 0 : 1);
|
|
283555
283751
|
if (!first.ok) process.exit(1);
|
|
@@ -283574,7 +283770,7 @@ async function dev(argv, runtime = {}) {
|
|
|
283574
283770
|
${import_picocolors15.default.green("\u2713")} ${wireEnvLocal(args.apiKey)}`);
|
|
283575
283771
|
console.log(` ${import_picocolors15.default.dim("Frameworks load it automatically; plain Node: node --env-file=.env.local app.ts")}`);
|
|
283576
283772
|
}
|
|
283577
|
-
console.log(` Your app is wired for ${runtime.branch ? `branch ${runtime.branch.slug}` : "
|
|
283773
|
+
console.log(` Your app is wired for ${runtime.branch ? `branch ${runtime.branch.slug}` : "this branch"}.`);
|
|
283578
283774
|
if (!args.watch) return;
|
|
283579
283775
|
const abs = (0, import_path5.resolve)(process.cwd(), args.schemaPath);
|
|
283580
283776
|
console.log(` ${import_picocolors15.default.dim(`watching ${args.schemaPath} \u2026 (Ctrl-C to stop)`)}
|
|
@@ -283736,7 +283932,226 @@ async function runBranchDev(argv, dependencies = {}) {
|
|
|
283736
283932
|
});
|
|
283737
283933
|
}
|
|
283738
283934
|
|
|
283935
|
+
// src/whoami.ts
|
|
283936
|
+
init_cjs_shims();
|
|
283937
|
+
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
283938
|
+
var import_errors13 = require("@abloatai/transaction/errors");
|
|
283939
|
+
init_config();
|
|
283940
|
+
init_controlPlane();
|
|
283941
|
+
|
|
283942
|
+
// src/credentialCapability.ts
|
|
283943
|
+
init_cjs_shims();
|
|
283944
|
+
var import_credentialPolicy3 = require("@abloatai/transaction/auth/credentialPolicy");
|
|
283945
|
+
function secretCounterpart(key) {
|
|
283946
|
+
void key;
|
|
283947
|
+
return "sk_";
|
|
283948
|
+
}
|
|
283949
|
+
function credentialCapability(key) {
|
|
283950
|
+
const kind = key ? (0, import_credentialPolicy3.classifyCredentialKind)(key) : null;
|
|
283951
|
+
if (!key || kind === null) return { kind, label: "", note: null };
|
|
283952
|
+
const secret = `${secretCounterpart(key)}\u2026`;
|
|
283953
|
+
switch (kind) {
|
|
283954
|
+
case "secret":
|
|
283955
|
+
return { kind, label: "", note: null };
|
|
283956
|
+
case "restricted":
|
|
283957
|
+
return {
|
|
283958
|
+
kind,
|
|
283959
|
+
label: "scoped",
|
|
283960
|
+
note: `A scoped key does exactly what it was minted for. Authoring schema requires a branch-bound secret ${secret} key with schema:push.`
|
|
283961
|
+
};
|
|
283962
|
+
case "publishable":
|
|
283963
|
+
return {
|
|
283964
|
+
kind,
|
|
283965
|
+
label: "read-only",
|
|
283966
|
+
note: `This is the key that is safe to ship in a browser bundle, and it reads. Work from a terminal wants a secret ${secret} key.`
|
|
283967
|
+
};
|
|
283968
|
+
case "ephemeral":
|
|
283969
|
+
return {
|
|
283970
|
+
kind,
|
|
283971
|
+
label: "session key",
|
|
283972
|
+
note: `This is a short-lived credential minted for one signed-in person, and it expires. Pushing a schema needs a secret ${secret} key.`
|
|
283973
|
+
};
|
|
283974
|
+
}
|
|
283975
|
+
}
|
|
283976
|
+
|
|
283977
|
+
// src/whoami.ts
|
|
283978
|
+
init_dbRole();
|
|
283979
|
+
init_theme();
|
|
283980
|
+
init_target();
|
|
283981
|
+
var WHOAMI_USAGE = ` ablo whoami \u2014 show the plane a credential acts on
|
|
283982
|
+
|
|
283983
|
+
Usage
|
|
283984
|
+
npx ablo whoami
|
|
283985
|
+
npx ablo whoami --key-env <NAME>
|
|
283986
|
+
npx ablo whoami --key <VALUE>
|
|
283987
|
+
npx ablo whoami --json
|
|
283988
|
+
|
|
283989
|
+
Credential choice
|
|
283990
|
+
With no flag, uses ABLO_API_KEY, then the active project's stored data key,
|
|
283991
|
+
then the stored login. This command does not load .env files implicitly.
|
|
283992
|
+
|
|
283993
|
+
--key-env reads a named variable from the process, .env.local, or .env
|
|
283994
|
+
without putting its value in shell history or the process list. Prefer it
|
|
283995
|
+
for comparing several keys.
|
|
283996
|
+
--key accepts a value directly for one-off use.
|
|
283997
|
+
|
|
283998
|
+
Output never prints the full credential. Identity is confirmed by the server;
|
|
283999
|
+
an invalid key, unreachable server, or unsupported server fails non-zero.`;
|
|
284000
|
+
function parseWhoamiArgs(argv) {
|
|
284001
|
+
let json = false;
|
|
284002
|
+
let key;
|
|
284003
|
+
let keyEnv;
|
|
284004
|
+
for (let i = 0; i < argv.length; i++) {
|
|
284005
|
+
const arg = argv[i];
|
|
284006
|
+
switch (arg) {
|
|
284007
|
+
case "--json":
|
|
284008
|
+
json = true;
|
|
284009
|
+
break;
|
|
284010
|
+
case "--key": {
|
|
284011
|
+
const value = argv[++i];
|
|
284012
|
+
if (!value || value.startsWith("--")) {
|
|
284013
|
+
throw new import_errors13.AbloValidationError("`--key` needs a credential value.", {
|
|
284014
|
+
code: "cli_invalid_arguments"
|
|
284015
|
+
});
|
|
284016
|
+
}
|
|
284017
|
+
key = value;
|
|
284018
|
+
break;
|
|
284019
|
+
}
|
|
284020
|
+
case "--key-env": {
|
|
284021
|
+
const value = argv[++i];
|
|
284022
|
+
if (!value || value.startsWith("--")) {
|
|
284023
|
+
throw new import_errors13.AbloValidationError("`--key-env` needs an environment variable name.", {
|
|
284024
|
+
code: "cli_invalid_arguments"
|
|
284025
|
+
});
|
|
284026
|
+
}
|
|
284027
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
|
284028
|
+
throw new import_errors13.AbloValidationError(
|
|
284029
|
+
`\`${value}\` is not a valid environment variable name.`,
|
|
284030
|
+
{ code: "cli_invalid_arguments" }
|
|
284031
|
+
);
|
|
284032
|
+
}
|
|
284033
|
+
keyEnv = value;
|
|
284034
|
+
break;
|
|
284035
|
+
}
|
|
284036
|
+
default:
|
|
284037
|
+
throw new import_errors13.AbloValidationError(`unknown whoami flag: ${arg}`, {
|
|
284038
|
+
code: "cli_invalid_arguments"
|
|
284039
|
+
});
|
|
284040
|
+
}
|
|
284041
|
+
}
|
|
284042
|
+
if (key && keyEnv) {
|
|
284043
|
+
throw new import_errors13.AbloValidationError("Choose one credential source: `--key` or `--key-env`.", {
|
|
284044
|
+
code: "cli_invalid_arguments"
|
|
284045
|
+
});
|
|
284046
|
+
}
|
|
284047
|
+
return { json, ...key ? { key } : {}, ...keyEnv ? { keyEnv } : {} };
|
|
284048
|
+
}
|
|
284049
|
+
function selectWhoamiCredential(args, cwd = process.cwd()) {
|
|
284050
|
+
if (args.key) return { key: args.key, source: "--key", targetSource: "env" };
|
|
284051
|
+
if (args.keyEnv) {
|
|
284052
|
+
const found = readProjectEnvVariable(args.keyEnv, cwd);
|
|
284053
|
+
if (!found) {
|
|
284054
|
+
throw new import_errors13.AbloAuthenticationError(
|
|
284055
|
+
`${args.keyEnv} is not set in the process environment, .env.local, or .env.`,
|
|
284056
|
+
{ code: "cli_api_key_missing" }
|
|
284057
|
+
);
|
|
284058
|
+
}
|
|
284059
|
+
return {
|
|
284060
|
+
key: found.value,
|
|
284061
|
+
source: `${found.source}:${args.keyEnv}`,
|
|
284062
|
+
targetSource: "env"
|
|
284063
|
+
};
|
|
284064
|
+
}
|
|
284065
|
+
const runtimeKey = resolveRuntimeApiKey();
|
|
284066
|
+
const dataKey = runtimeKey.key;
|
|
284067
|
+
if (dataKey) {
|
|
284068
|
+
return {
|
|
284069
|
+
key: dataKey,
|
|
284070
|
+
source: runtimeKey.source === "stored" ? "stored data key" : `${runtimeKey.source ?? "env"}:ABLO_API_KEY`,
|
|
284071
|
+
targetSource: runtimeKey.source ?? "stored"
|
|
284072
|
+
};
|
|
284073
|
+
}
|
|
284074
|
+
const managementKey = resolveManagementKey();
|
|
284075
|
+
if (managementKey) {
|
|
284076
|
+
return {
|
|
284077
|
+
key: managementKey,
|
|
284078
|
+
source: process.env.ABLO_MANAGEMENT_KEY ? "env:ABLO_MANAGEMENT_KEY" : "stored login",
|
|
284079
|
+
targetSource: process.env.ABLO_MANAGEMENT_KEY ? "env" : "stored"
|
|
284080
|
+
};
|
|
284081
|
+
}
|
|
284082
|
+
const ambient = ambientEnvKeyNote();
|
|
284083
|
+
throw new import_errors13.AbloAuthenticationError(
|
|
284084
|
+
`No credential found. Run \`ablo login\`, set ABLO_API_KEY, or pass \`--key-env <NAME>\`.${ambient ? `
|
|
284085
|
+
|
|
284086
|
+
${ambient}` : ""}`,
|
|
284087
|
+
{ code: "cli_api_key_missing" }
|
|
284088
|
+
);
|
|
284089
|
+
}
|
|
284090
|
+
async function whoami(argv) {
|
|
284091
|
+
const args = parseWhoamiArgs(argv);
|
|
284092
|
+
const selected = selectWhoamiCredential(args);
|
|
284093
|
+
const target = await resolveTarget({
|
|
284094
|
+
url: apiBaseUrl(),
|
|
284095
|
+
apiKey: selected.key,
|
|
284096
|
+
keySource: selected.targetSource,
|
|
284097
|
+
strict: true
|
|
284098
|
+
});
|
|
284099
|
+
const confirmed = target.confirmed;
|
|
284100
|
+
if (!confirmed) {
|
|
284101
|
+
throw new import_errors13.AbloAuthenticationError(
|
|
284102
|
+
"The server did not confirm an identity for this credential.",
|
|
284103
|
+
{ code: "identity_resolve_failed" }
|
|
284104
|
+
);
|
|
284105
|
+
}
|
|
284106
|
+
const project = confirmed.project;
|
|
284107
|
+
const projectLabel = project ? project.isDefault ? "default" : project.slug : "default";
|
|
284108
|
+
const actsOn = confirmed.branchId ? confirmed.branchRoot ? "production root" : `branch ${confirmed.branchId}` : confirmed.environment ?? "unknown";
|
|
284109
|
+
const capability = credentialCapability(selected.key);
|
|
284110
|
+
if (args.json) {
|
|
284111
|
+
console.log(
|
|
284112
|
+
JSON.stringify(
|
|
284113
|
+
{
|
|
284114
|
+
authenticated: true,
|
|
284115
|
+
key: {
|
|
284116
|
+
prefix: `${selected.key.slice(0, 12)}\u2026`,
|
|
284117
|
+
source: selected.source,
|
|
284118
|
+
kind: capability.kind
|
|
284119
|
+
},
|
|
284120
|
+
organizationId: confirmed.organizationId,
|
|
284121
|
+
project: project ? {
|
|
284122
|
+
id: project.id,
|
|
284123
|
+
slug: projectLabel,
|
|
284124
|
+
name: project.name,
|
|
284125
|
+
default: project.isDefault
|
|
284126
|
+
} : null,
|
|
284127
|
+
environment: confirmed.environment,
|
|
284128
|
+
branchId: confirmed.branchId ?? null,
|
|
284129
|
+
branchRoot: confirmed.branchRoot ?? false
|
|
284130
|
+
},
|
|
284131
|
+
null,
|
|
284132
|
+
2
|
|
284133
|
+
)
|
|
284134
|
+
);
|
|
284135
|
+
return;
|
|
284136
|
+
}
|
|
284137
|
+
console.log(`
|
|
284138
|
+
${brand("ablo")} ${import_picocolors16.default.dim("whoami")}
|
|
284139
|
+
`);
|
|
284140
|
+
console.log(
|
|
284141
|
+
` ${import_picocolors16.default.dim("key")} ${selected.key.slice(0, 12)}\u2026 ${import_picocolors16.default.dim(`(${selected.source} \xB7 ${capability.label})`)}`
|
|
284142
|
+
);
|
|
284143
|
+
console.log(` ${import_picocolors16.default.dim("org")} ${import_picocolors16.default.dim(confirmed.organizationId)}`);
|
|
284144
|
+
console.log(
|
|
284145
|
+
` ${import_picocolors16.default.dim("project")} ${import_picocolors16.default.bold(projectLabel)}${project ? ` ${import_picocolors16.default.dim(`(${project.id})`)}` : ""}`
|
|
284146
|
+
);
|
|
284147
|
+
console.log(` ${import_picocolors16.default.dim("acts on")} ${import_picocolors16.default.bold(actsOn)}`);
|
|
284148
|
+
console.log(`
|
|
284149
|
+
${import_picocolors16.default.green("\u2713")} ${import_picocolors16.default.dim("credential accepted; target confirmed by the server")}
|
|
284150
|
+
`);
|
|
284151
|
+
}
|
|
284152
|
+
|
|
283739
284153
|
// src/commands.ts
|
|
284154
|
+
init_push();
|
|
283740
284155
|
var CORE_GROUPS = ["Start", "Every day", "More"];
|
|
283741
284156
|
var FULL_GROUPS = [
|
|
283742
284157
|
"Set up",
|
|
@@ -283786,6 +284201,7 @@ var COMMANDS = [
|
|
|
283786
284201
|
{ run: "connect apply", does: "Run that setup for you, from a one-time admin URL" },
|
|
283787
284202
|
{ run: "connect check", does: "Confirm your database is ready to share changes with Ablo" },
|
|
283788
284203
|
{ run: "connect scan", does: "List anything Ablo ever set up in your database (read-only)" },
|
|
284204
|
+
{ run: "connect locate", does: "See which plane holds a database before connecting it" },
|
|
283789
284205
|
{ run: "connect deregister", does: "Disconnect this project's database \u2014 Ablo stops reading and writing it" }
|
|
283790
284206
|
]
|
|
283791
284207
|
}
|
|
@@ -283834,6 +284250,7 @@ var COMMANDS = [
|
|
|
283834
284250
|
},
|
|
283835
284251
|
{
|
|
283836
284252
|
name: "push",
|
|
284253
|
+
usage: PUSH_USAGE,
|
|
283837
284254
|
core: { group: "Every day", does: "Upload your schema \u2014 schema only; your rows stay in your database" },
|
|
283838
284255
|
full: {
|
|
283839
284256
|
group: "Your schema",
|
|
@@ -283875,6 +284292,18 @@ var COMMANDS = [
|
|
|
283875
284292
|
]
|
|
283876
284293
|
}
|
|
283877
284294
|
},
|
|
284295
|
+
{
|
|
284296
|
+
name: "whoami",
|
|
284297
|
+
usage: WHOAMI_USAGE,
|
|
284298
|
+
full: {
|
|
284299
|
+
group: "See what's happening",
|
|
284300
|
+
rows: [
|
|
284301
|
+
{ run: "whoami", does: "Show the server-confirmed plane the active credential acts on" },
|
|
284302
|
+
{ run: "whoami --key-env <NAME>", does: "Inspect another key without exposing it in argv" },
|
|
284303
|
+
{ run: "whoami --json", does: "Same, machine-readable" }
|
|
284304
|
+
]
|
|
284305
|
+
}
|
|
284306
|
+
},
|
|
283878
284307
|
{
|
|
283879
284308
|
name: "status",
|
|
283880
284309
|
core: { group: "Every day", does: "See what this key acts on, your pushed schema, and whether writes will work" },
|
|
@@ -283913,7 +284342,7 @@ var COMMANDS = [
|
|
|
283913
284342
|
{ run: "branch check [id|slug]", does: "CI alias for branch status" },
|
|
283914
284343
|
{ run: "branch create <slug>", does: "Create a child of the production root" },
|
|
283915
284344
|
{ run: "branch ensure <slug> --credential", does: "Resolve a branch and mint its expiring CI key" },
|
|
283916
|
-
{ run: "branch credential <id>", does: "Mint an expiring branch-bound
|
|
284345
|
+
{ run: "branch credential <id>", does: "Mint an expiring branch-bound runtime key" },
|
|
283917
284346
|
{ run: "branch delete <id>", does: "Delete a non-root branch" }
|
|
283918
284347
|
]
|
|
283919
284348
|
}
|
|
@@ -284003,15 +284432,15 @@ function fullRows(group) {
|
|
|
284003
284432
|
}
|
|
284004
284433
|
|
|
284005
284434
|
// src/index.ts
|
|
284006
|
-
var
|
|
284435
|
+
var import_errors21 = require("@abloatai/transaction/errors");
|
|
284007
284436
|
init_push();
|
|
284008
284437
|
|
|
284009
284438
|
// src/generate.ts
|
|
284010
284439
|
init_cjs_shims();
|
|
284011
|
-
var
|
|
284440
|
+
var import_errors14 = require("@abloatai/transaction/errors");
|
|
284012
284441
|
var import_fs8 = require("fs");
|
|
284013
284442
|
var import_path6 = require("path");
|
|
284014
|
-
var
|
|
284443
|
+
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
284015
284444
|
var import_schema7 = require("@abloatai/transaction/schema");
|
|
284016
284445
|
init_push();
|
|
284017
284446
|
var DEFAULT_SCHEMA_PATH4 = "ablo/schema.ts";
|
|
@@ -284034,7 +284463,7 @@ function parseGenerateArgs(argv) {
|
|
|
284034
284463
|
out = argv[++i] ?? out;
|
|
284035
284464
|
break;
|
|
284036
284465
|
default:
|
|
284037
|
-
throw new
|
|
284466
|
+
throw new import_errors14.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
284038
284467
|
}
|
|
284039
284468
|
}
|
|
284040
284469
|
return { schemaPath, exportName, out };
|
|
@@ -284044,7 +284473,7 @@ async function generate(argv) {
|
|
|
284044
284473
|
try {
|
|
284045
284474
|
args = parseGenerateArgs(argv);
|
|
284046
284475
|
} catch (err) {
|
|
284047
|
-
console.error(
|
|
284476
|
+
console.error(import_picocolors17.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
284048
284477
|
process.exit(1);
|
|
284049
284478
|
}
|
|
284050
284479
|
let source;
|
|
@@ -284053,22 +284482,22 @@ async function generate(argv) {
|
|
|
284053
284482
|
const schemaJson = JSON.parse((0, import_schema7.serializeSchema)(schema));
|
|
284054
284483
|
source = (0, import_schema7.generateTypes)(schemaJson);
|
|
284055
284484
|
} catch (err) {
|
|
284056
|
-
console.error(
|
|
284485
|
+
console.error(import_picocolors17.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
284057
284486
|
process.exit(1);
|
|
284058
284487
|
}
|
|
284059
284488
|
const abs = (0, import_path6.resolve)(process.cwd(), args.out);
|
|
284060
284489
|
(0, import_fs8.mkdirSync)((0, import_path6.dirname)(abs), { recursive: true });
|
|
284061
284490
|
(0, import_fs8.writeFileSync)(abs, source);
|
|
284062
|
-
console.log(` ${
|
|
284491
|
+
console.log(` ${import_picocolors17.default.green("\u2713")} Generated types \u2192 ${import_picocolors17.default.bold(args.out)}`);
|
|
284063
284492
|
}
|
|
284064
284493
|
|
|
284065
284494
|
// src/login.ts
|
|
284066
284495
|
init_cjs_shims();
|
|
284067
284496
|
var import_child_process2 = require("child_process");
|
|
284068
|
-
var
|
|
284497
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
284069
284498
|
init_dist2();
|
|
284070
|
-
var
|
|
284071
|
-
var
|
|
284499
|
+
var import_errors15 = require("@abloatai/transaction/errors");
|
|
284500
|
+
var import_wire8 = require("@abloatai/transaction/wire");
|
|
284072
284501
|
init_config();
|
|
284073
284502
|
init_theme();
|
|
284074
284503
|
var CLIENT_ID = "ablo-cli";
|
|
@@ -284086,20 +284515,21 @@ function openBrowser(url) {
|
|
|
284086
284515
|
} catch {
|
|
284087
284516
|
}
|
|
284088
284517
|
}
|
|
284089
|
-
function
|
|
284090
|
-
const i = argv.indexOf(
|
|
284518
|
+
function parseSlugFlag(argv, flag2) {
|
|
284519
|
+
const i = argv.indexOf(flag2);
|
|
284091
284520
|
if (i >= 0) {
|
|
284092
284521
|
const slug = argv[i + 1];
|
|
284093
284522
|
if (slug && !slug.startsWith("-")) return slug;
|
|
284094
284523
|
}
|
|
284095
|
-
const eq = argv.find((a) => a.startsWith(
|
|
284096
|
-
return eq ? eq.slice(
|
|
284524
|
+
const eq = argv.find((a) => a.startsWith(`${flag2}=`));
|
|
284525
|
+
return eq ? eq.slice(flag2.length + 1) || void 0 : void 0;
|
|
284097
284526
|
}
|
|
284098
284527
|
async function deviceLogin(argv, deps = {}) {
|
|
284099
284528
|
const openUrl = deps.openUrl ?? openBrowser;
|
|
284100
284529
|
Ie(`${brand("ablo")} login`);
|
|
284101
|
-
const requested =
|
|
284530
|
+
const requested = parseSlugFlag(argv, "--project") ?? getActiveProject()?.slug;
|
|
284102
284531
|
const targetProject = requested === DEFAULT_PROFILE ? void 0 : requested;
|
|
284532
|
+
const targetOrg = parseSlugFlag(argv, "--org");
|
|
284103
284533
|
const interactive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
284104
284534
|
let account = "login";
|
|
284105
284535
|
if (interactive) {
|
|
@@ -284126,11 +284556,11 @@ async function deviceLogin(argv, deps = {}) {
|
|
|
284126
284556
|
process.exit(1);
|
|
284127
284557
|
}
|
|
284128
284558
|
const code = await codeRes.json();
|
|
284129
|
-
const approvePath = `/cli?user_code=${code.user_code}`;
|
|
284559
|
+
const approvePath = `/cli?user_code=${code.user_code}${targetOrg ? `&org=${encodeURIComponent(targetOrg)}` : ""}`;
|
|
284130
284560
|
const url = account === "signup" ? `${DASHBOARD_URL}/signup?next=${encodeURIComponent(approvePath)}` : `${DASHBOARD_URL}${approvePath}`;
|
|
284131
|
-
Me(`${
|
|
284561
|
+
Me(`${import_picocolors18.default.bold(code.user_code)}
|
|
284132
284562
|
|
|
284133
|
-
${
|
|
284563
|
+
${import_picocolors18.default.dim(url)}`, "Approve in your browser");
|
|
284134
284564
|
openUrl(url);
|
|
284135
284565
|
const s = Y2();
|
|
284136
284566
|
s.start("Waiting for approval\u2026");
|
|
@@ -284200,7 +284630,7 @@ ${import_picocolors17.default.dim(url)}`, "Approve in your browser");
|
|
|
284200
284630
|
}
|
|
284201
284631
|
if (!provRes.ok) {
|
|
284202
284632
|
s.stop("Could not provision a key.");
|
|
284203
|
-
const err = (0,
|
|
284633
|
+
const err = (0, import_errors15.translateHttpError)(
|
|
284204
284634
|
provRes.status,
|
|
284205
284635
|
await provRes.json().catch(() => null),
|
|
284206
284636
|
provRes.headers.get("x-request-id") ?? void 0
|
|
@@ -284208,30 +284638,36 @@ ${import_picocolors17.default.dim(url)}`, "Approve in your browser");
|
|
|
284208
284638
|
M2.error(err.message);
|
|
284209
284639
|
if (err.code === "entity_not_found" && targetProject) {
|
|
284210
284640
|
M2.error(
|
|
284211
|
-
`If that isn't the account you meant, run ${
|
|
284641
|
+
`If that isn't the account you meant, run ${import_picocolors18.default.bold("npx ablo logout")} and sign in again. Otherwise create it with ${import_picocolors18.default.bold(`npx ablo projects create ${targetProject}`)}.`
|
|
284212
284642
|
);
|
|
284213
284643
|
} else {
|
|
284214
284644
|
M2.error(
|
|
284215
|
-
`The browser approval succeeded but the credential handoff failed. Try ${
|
|
284645
|
+
`The browser approval succeeded but the credential handoff failed. Try ${import_picocolors18.default.bold("npx ablo login")} again.`
|
|
284216
284646
|
);
|
|
284217
284647
|
}
|
|
284218
284648
|
process.exit(1);
|
|
284219
284649
|
}
|
|
284220
|
-
const parsedProv =
|
|
284650
|
+
const parsedProv = import_wire8.provisionKeyResponseSchema.safeParse(
|
|
284221
284651
|
await provRes.json().catch(() => null)
|
|
284222
284652
|
);
|
|
284223
284653
|
if (!parsedProv.success) {
|
|
284224
284654
|
s.stop("Could not provision a key.");
|
|
284225
284655
|
M2.error("The key handoff returned something this version does not recognize.");
|
|
284226
|
-
M2.error(`Try again, or upgrade with ${
|
|
284656
|
+
M2.error(`Try again, or upgrade with ${import_picocolors18.default.bold("npm i -g @abloatai/ablo")}.`);
|
|
284227
284657
|
process.exit(1);
|
|
284228
284658
|
}
|
|
284229
284659
|
const prov = parsedProv.data;
|
|
284230
284660
|
const entry = (k3) => ({
|
|
284231
284661
|
apiKey: k3.apiKey,
|
|
284232
284662
|
...prov.organizationId ? { organizationId: prov.organizationId } : {},
|
|
284663
|
+
...prov.organizationSlug ? { organizationSlug: prov.organizationSlug } : {},
|
|
284233
284664
|
...k3.expiresAt ? { expiresAt: k3.expiresAt } : {}
|
|
284234
284665
|
});
|
|
284666
|
+
if (targetOrg && prov.organizationSlug && prov.organizationSlug !== targetOrg) {
|
|
284667
|
+
M2.warn(
|
|
284668
|
+
`The approval chose ${import_picocolors18.default.bold(prov.organizationSlug)}, not ${import_picocolors18.default.bold(targetOrg)}. The credential is scoped to ${import_picocolors18.default.bold(prov.organizationSlug)}.`
|
|
284669
|
+
);
|
|
284670
|
+
}
|
|
284235
284671
|
const profileName = prov.project?.slug ?? DEFAULT_PROFILE;
|
|
284236
284672
|
const path = setProfileKeys(
|
|
284237
284673
|
profileName,
|
|
@@ -284241,9 +284677,10 @@ ${import_picocolors17.default.dim(url)}`, "Approve in your browser");
|
|
|
284241
284677
|
{ mode: "sandbox", activeProject: prov.project ?? void 0 }
|
|
284242
284678
|
);
|
|
284243
284679
|
s.stop(`Saved project credential to ${path}`);
|
|
284244
|
-
const
|
|
284680
|
+
const orgLabel = prov.organizationSlug ? ` to ${import_picocolors18.default.bold(prov.organizationSlug)}` : "";
|
|
284681
|
+
const where = prov.project ? ` ${import_picocolors18.default.dim(`(project ${prov.project.slug})`)}` : "";
|
|
284245
284682
|
Se(
|
|
284246
|
-
`${
|
|
284683
|
+
`${import_picocolors18.default.green("\u2713")} Logged in${orgLabel}${where}. Run ${import_picocolors18.default.bold("npx ablo dev")} to create or resume your Git branch and start with an expiring runtime key.`
|
|
284247
284684
|
);
|
|
284248
284685
|
}
|
|
284249
284686
|
async function login(argv = [], deps = {}) {
|
|
@@ -284252,14 +284689,14 @@ async function login(argv = [], deps = {}) {
|
|
|
284252
284689
|
function logout() {
|
|
284253
284690
|
const removed = clearCredential();
|
|
284254
284691
|
if (removed) {
|
|
284255
|
-
console.log(` ${
|
|
284692
|
+
console.log(` ${import_picocolors18.default.green("\u2713")} Logged out ${import_picocolors18.default.dim(`(credentials removed from ${configDir()})`)}`);
|
|
284256
284693
|
} else {
|
|
284257
|
-
console.log(` ${
|
|
284694
|
+
console.log(` ${import_picocolors18.default.dim("\u25CB")} Not logged in \u2014 nothing to remove.`);
|
|
284258
284695
|
}
|
|
284259
284696
|
if (process.env.ABLO_MANAGEMENT_KEY) {
|
|
284260
284697
|
console.log(
|
|
284261
|
-
|
|
284262
|
-
` Note: ${
|
|
284698
|
+
import_picocolors18.default.dim(
|
|
284699
|
+
` Note: ${import_picocolors18.default.bold("ABLO_MANAGEMENT_KEY")} is still set in this shell and takes precedence.`
|
|
284263
284700
|
)
|
|
284264
284701
|
);
|
|
284265
284702
|
}
|
|
@@ -284271,46 +284708,9 @@ init_projects();
|
|
|
284271
284708
|
|
|
284272
284709
|
// src/status.ts
|
|
284273
284710
|
init_cjs_shims();
|
|
284274
|
-
var
|
|
284711
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
284275
284712
|
init_config();
|
|
284276
284713
|
init_target();
|
|
284277
|
-
|
|
284278
|
-
// src/credentialCapability.ts
|
|
284279
|
-
init_cjs_shims();
|
|
284280
|
-
var import_credentialPolicy3 = require("@abloatai/transaction/auth/credentialPolicy");
|
|
284281
|
-
init_config();
|
|
284282
|
-
function secretCounterpart(key) {
|
|
284283
|
-
return modeFromKey(key) === "production" ? "sk_live_" : "sk_test_";
|
|
284284
|
-
}
|
|
284285
|
-
function credentialCapability(key) {
|
|
284286
|
-
const kind = key ? (0, import_credentialPolicy3.classifyCredentialKind)(key) : null;
|
|
284287
|
-
if (!key || kind === null) return { kind, label: "", note: null };
|
|
284288
|
-
const secret = `${secretCounterpart(key)}\u2026`;
|
|
284289
|
-
switch (kind) {
|
|
284290
|
-
case "secret":
|
|
284291
|
-
return { kind, label: "", note: null };
|
|
284292
|
-
case "restricted":
|
|
284293
|
-
return {
|
|
284294
|
-
kind,
|
|
284295
|
-
label: "scoped",
|
|
284296
|
-
note: `A scoped key does exactly what it was minted for. The production key \`ablo login\` stores is for observing your live plane with \`ablo status\` and \`ablo logs\`; authoring schema there takes a secret ${secret} key from the dashboard.`
|
|
284297
|
-
};
|
|
284298
|
-
case "publishable":
|
|
284299
|
-
return {
|
|
284300
|
-
kind,
|
|
284301
|
-
label: "read-only",
|
|
284302
|
-
note: `This is the key that is safe to ship in a browser bundle, and it reads. Work from a terminal wants a secret ${secret} key.`
|
|
284303
|
-
};
|
|
284304
|
-
case "ephemeral":
|
|
284305
|
-
return {
|
|
284306
|
-
kind,
|
|
284307
|
-
label: "session key",
|
|
284308
|
-
note: `This is a short-lived credential minted for one signed-in person, and it expires. Pushing a schema needs a secret ${secret} key.`
|
|
284309
|
-
};
|
|
284310
|
-
}
|
|
284311
|
-
}
|
|
284312
|
-
|
|
284313
|
-
// src/status.ts
|
|
284314
284714
|
init_theme();
|
|
284315
284715
|
init_controlPlane();
|
|
284316
284716
|
var import_schema8 = require("@abloatai/transaction/coordination/schema");
|
|
@@ -284318,9 +284718,9 @@ init_readiness();
|
|
|
284318
284718
|
function expiryLabel(iso) {
|
|
284319
284719
|
const ms = Date.parse(iso) - Date.now();
|
|
284320
284720
|
if (Number.isNaN(ms)) return "";
|
|
284321
|
-
if (ms <= 0) return
|
|
284721
|
+
if (ms <= 0) return import_picocolors19.default.red("expired");
|
|
284322
284722
|
const days = Math.floor(ms / (24 * 60 * 60 * 1e3));
|
|
284323
|
-
return
|
|
284723
|
+
return import_picocolors19.default.dim(days > 0 ? `expires in ${days}d` : "expires <1d");
|
|
284324
284724
|
}
|
|
284325
284725
|
async function ping(apiUrl3) {
|
|
284326
284726
|
const ctrl = new AbortController();
|
|
@@ -284341,55 +284741,55 @@ function formatConflict(conflict) {
|
|
|
284341
284741
|
const parts = import_schema8.participantKindSchema.options.flatMap((k3) => conflict[k3] ? [`${k3}:${conflict[k3]}`] : []);
|
|
284342
284742
|
return parts.length ? `{${parts.join(",")}}` : "";
|
|
284343
284743
|
}
|
|
284344
|
-
function printTargetLines(target, localProject, storedOrganizationId) {
|
|
284744
|
+
function printTargetLines(target, localProject, storedOrganizationId, storedOrganizationSlug) {
|
|
284345
284745
|
const confirmed = target?.confirmed ?? null;
|
|
284346
284746
|
const org = confirmed?.organizationId ?? storedOrganizationId;
|
|
284347
284747
|
if (org) {
|
|
284348
|
-
const suffix = confirmed?.organizationId ? "" : ` ${
|
|
284349
|
-
|
|
284748
|
+
const suffix = confirmed?.organizationId ? "" : ` ${import_picocolors19.default.yellow("(unconfirmed)")}`;
|
|
284749
|
+
const slug = org === storedOrganizationId ? storedOrganizationSlug : void 0;
|
|
284750
|
+
const label = slug ? `${import_picocolors19.default.bold(slug)} ${import_picocolors19.default.dim(`(${org})`)}` : import_picocolors19.default.dim(org);
|
|
284751
|
+
console.log(` ${import_picocolors19.default.dim("org")} ${label}${suffix}`);
|
|
284350
284752
|
} else {
|
|
284351
284753
|
console.log(
|
|
284352
|
-
` ${
|
|
284754
|
+
` ${import_picocolors19.default.dim("org")} ${import_picocolors19.default.yellow("unknown")} ${import_picocolors19.default.dim("(the server did not confirm one for this key)")}`
|
|
284353
284755
|
);
|
|
284354
284756
|
}
|
|
284355
284757
|
let projectLine;
|
|
284356
284758
|
if (confirmed?.project) {
|
|
284357
284759
|
const p2 = confirmed.project;
|
|
284358
|
-
projectLine = p2.isDefault ? `${
|
|
284760
|
+
projectLine = p2.isDefault ? `${import_picocolors19.default.bold("default")} ${import_picocolors19.default.dim("(org-default)")}` : `${import_picocolors19.default.bold(p2.slug)} ${import_picocolors19.default.dim(`(${p2.id})`)}`;
|
|
284359
284761
|
} else if (confirmed) {
|
|
284360
|
-
projectLine = `${
|
|
284762
|
+
projectLine = `${import_picocolors19.default.bold("default")} ${import_picocolors19.default.dim("(org-default)")}`;
|
|
284361
284763
|
} else if (localProject) {
|
|
284362
|
-
projectLine = `${
|
|
284764
|
+
projectLine = `${import_picocolors19.default.bold(localProject.slug)} ${import_picocolors19.default.dim(`(${localProject.id})`)} ${import_picocolors19.default.yellow("(unconfirmed)")}`;
|
|
284363
284765
|
} else {
|
|
284364
|
-
projectLine = `${
|
|
284766
|
+
projectLine = `${import_picocolors19.default.bold("default")} ${target ? import_picocolors19.default.yellow("(unconfirmed)") : import_picocolors19.default.dim("(org-default)")}`;
|
|
284365
284767
|
}
|
|
284366
|
-
console.log(` ${
|
|
284768
|
+
console.log(` ${import_picocolors19.default.dim("project")} ${projectLine}`);
|
|
284367
284769
|
const branch = confirmed?.branchId ?? null;
|
|
284368
284770
|
const env = confirmed?.environment ?? target?.keyEnv ?? null;
|
|
284369
284771
|
if (branch) {
|
|
284370
284772
|
const label = confirmed?.branchRoot ? "production root" : `branch ${branch}`;
|
|
284371
|
-
console.log(` ${
|
|
284773
|
+
console.log(` ${import_picocolors19.default.dim("acts on")} ${import_picocolors19.default.bold(label)}`);
|
|
284372
284774
|
} else if (env) {
|
|
284373
|
-
const suffix = confirmed ? "" : ` ${
|
|
284374
|
-
console.log(` ${
|
|
284775
|
+
const suffix = confirmed ? "" : ` ${import_picocolors19.default.yellow("(unconfirmed)")}`;
|
|
284776
|
+
console.log(` ${import_picocolors19.default.dim("acts on")} ${import_picocolors19.default.bold(env)}${suffix}`);
|
|
284375
284777
|
}
|
|
284376
284778
|
const divergence = describeMismatches(target?.mismatches ?? []);
|
|
284377
|
-
if (divergence) console.log(` ${
|
|
284779
|
+
if (divergence) console.log(` ${import_picocolors19.default.yellow(`\u26A0 ${divergence}`)}`);
|
|
284378
284780
|
}
|
|
284379
284781
|
async function status(args = []) {
|
|
284380
284782
|
const apiUrl3 = apiBaseUrl();
|
|
284381
284783
|
const cfg = readConfig();
|
|
284382
284784
|
const mode = getMode();
|
|
284383
|
-
const
|
|
284384
|
-
const target =
|
|
284785
|
+
const runtimeKey = resolveRuntimeApiKey();
|
|
284786
|
+
const target = runtimeKey.key ? await resolveTarget({ url: apiUrl3, apiKey: runtimeKey.key, keySource: runtimeKey.source ?? "stored" }) : null;
|
|
284385
284787
|
if (args.includes("--json")) {
|
|
284386
284788
|
const entry = getKeyEntry(mode);
|
|
284387
|
-
const key2 = describeEffectiveKey(mode, process.env.ABLO_API_KEY, entry);
|
|
284388
|
-
const plan2 = resolvePushPlan();
|
|
284389
284789
|
const activeProject2 = getActiveProject();
|
|
284390
|
-
const pushed2 = await fetchPushedSchema(apiUrl3,
|
|
284790
|
+
const pushed2 = await fetchPushedSchema(apiUrl3, runtimeKey.key);
|
|
284391
284791
|
const reachableForJson = await ping(apiUrl3);
|
|
284392
|
-
const dataSource2 = reachableForJson ? (await fetchRoutingState(apiUrl3,
|
|
284792
|
+
const dataSource2 = reachableForJson ? (await fetchRoutingState(apiUrl3, runtimeKey.key)).source : { kind: "unknown", detail: "unreachable" };
|
|
284393
284793
|
const driftForJson = schemaDrift(await readLocalSchemaHash(), pushed2?.hash);
|
|
284394
284794
|
const out = {
|
|
284395
284795
|
// The locally-active project (`ablo projects use`); null = org-default.
|
|
@@ -284397,28 +284797,20 @@ async function status(args = []) {
|
|
|
284397
284797
|
// The credential the CLI resolves for requests, with its source —
|
|
284398
284798
|
// 'env' | '.env.local' | '.env' | 'stored'. Key confusion is a common
|
|
284399
284799
|
// source of trouble, and the source is usually the answer.
|
|
284400
|
-
|
|
284401
|
-
prefix:
|
|
284402
|
-
source:
|
|
284800
|
+
runtimeKey: {
|
|
284801
|
+
prefix: runtimeKey.key ? runtimeKey.key.slice(0, 12) : null,
|
|
284802
|
+
source: runtimeKey.source,
|
|
284403
284803
|
// What this credential can do. A pipeline that pushes can read it before
|
|
284404
284804
|
// running the push, rather than learning from the 403 — the same fact
|
|
284405
284805
|
// the human output prints, from the same place.
|
|
284406
|
-
kind: credentialCapability(
|
|
284806
|
+
kind: credentialCapability(runtimeKey.key).kind
|
|
284407
284807
|
},
|
|
284408
|
-
keyPrefix: key2.keyPrefix,
|
|
284409
|
-
keySource: key2.keySource,
|
|
284410
|
-
keyMode: key2.keyMode,
|
|
284411
|
-
storedKeyPrefix: key2.storedKeyPrefix,
|
|
284412
|
-
keyMatchesActiveMode: key2.keyMatchesActiveMode,
|
|
284413
|
-
keyMatchesStoredActiveKey: key2.keyMatchesStoredActiveKey,
|
|
284414
|
-
keyMismatch: key2.keyMismatch,
|
|
284415
284808
|
organizationId: entry?.organizationId ?? null,
|
|
284416
284809
|
// The SERVER-CONFIRMED plane this key resolves to — the authoritative
|
|
284417
284810
|
// answer to "where does a push land", independent of the local
|
|
284418
284811
|
// project preference above. Null when the server didn't answer.
|
|
284419
284812
|
confirmedTarget: target?.confirmed ? {
|
|
284420
284813
|
organizationId: target.confirmed.organizationId,
|
|
284421
|
-
environment: target.confirmed.environment,
|
|
284422
284814
|
project: target.confirmed.project,
|
|
284423
284815
|
projectId: target.confirmed.projectId,
|
|
284424
284816
|
branchId: target.confirmed.branchId,
|
|
@@ -284426,14 +284818,7 @@ async function status(args = []) {
|
|
|
284426
284818
|
} : null,
|
|
284427
284819
|
// Divergence between local project intent and the confirmed target.
|
|
284428
284820
|
mismatches: target?.mismatches ?? [],
|
|
284429
|
-
//
|
|
284430
|
-
// demand a different key".
|
|
284431
|
-
push: {
|
|
284432
|
-
flow: plan2.flow,
|
|
284433
|
-
keyPrefix: plan2.apiKey?.slice(0, 12) ?? null,
|
|
284434
|
-
keySource: plan2.source
|
|
284435
|
-
},
|
|
284436
|
-
// The schema active for this key's environment — the typename and conflict
|
|
284821
|
+
// The schema active for this key's branch — the typename and conflict
|
|
284437
284822
|
// rules the engine enforces, which may differ from your local `schema.ts`.
|
|
284438
284823
|
// null means the server did not answer (unreachable, too old, or no key).
|
|
284439
284824
|
schema: pushed2 ? {
|
|
@@ -284453,7 +284838,7 @@ async function status(args = []) {
|
|
|
284453
284838
|
drift: driftForJson,
|
|
284454
284839
|
blockers: blockers({
|
|
284455
284840
|
reachable: reachableForJson,
|
|
284456
|
-
hasKey: Boolean(
|
|
284841
|
+
hasKey: Boolean(runtimeKey.key),
|
|
284457
284842
|
dataSource: dataSource2,
|
|
284458
284843
|
schemaPushed: Boolean(pushed2?.active),
|
|
284459
284844
|
drift: driftForJson
|
|
@@ -284463,26 +284848,31 @@ async function status(args = []) {
|
|
|
284463
284848
|
return;
|
|
284464
284849
|
}
|
|
284465
284850
|
console.log(`
|
|
284466
|
-
${brand("ablo")} ${
|
|
284851
|
+
${brand("ablo")} ${import_picocolors19.default.dim("status")}
|
|
284467
284852
|
`);
|
|
284468
|
-
if (
|
|
284469
|
-
const label =
|
|
284853
|
+
if (runtimeKey.key && runtimeKey.source && runtimeKey.source !== "stored") {
|
|
284854
|
+
const label = runtimeKey.source === "env" ? "ABLO_API_KEY env" : runtimeKey.source;
|
|
284470
284855
|
console.log(
|
|
284471
|
-
` ${
|
|
284856
|
+
` ${import_picocolors19.default.dim("key")} ${runtimeKey.key.slice(0, 12)}\u2026 ${import_picocolors19.default.dim(`(${label} \u2014 overrides stored)`)}`
|
|
284472
284857
|
);
|
|
284473
284858
|
} else if (!cfg) {
|
|
284474
|
-
console.log(` ${
|
|
284859
|
+
console.log(` ${import_picocolors19.default.yellow("!")} Not logged in \u2014 run ${import_picocolors19.default.bold("ablo login")}.`);
|
|
284475
284860
|
}
|
|
284476
284861
|
const activeEntry = getKeyEntry(mode);
|
|
284477
|
-
const key = describeEffectiveKey(mode, process.env.ABLO_API_KEY, activeEntry);
|
|
284478
|
-
if (key.keyMismatch) {
|
|
284479
|
-
console.log(` ${import_picocolors18.default.yellow(`! ${key.keyMismatch.message}`)}`);
|
|
284480
|
-
}
|
|
284481
284862
|
const activeProject = getActiveProject();
|
|
284482
|
-
printTargetLines(
|
|
284863
|
+
printTargetLines(
|
|
284864
|
+
target,
|
|
284865
|
+
activeProject,
|
|
284866
|
+
activeEntry?.organizationId,
|
|
284867
|
+
activeEntry?.organizationSlug
|
|
284868
|
+
);
|
|
284869
|
+
const management = getManagementKeyEntry();
|
|
284870
|
+
console.log(
|
|
284871
|
+
` ${import_picocolors19.default.dim("\u25CB")} ${"management".padEnd(12)} ${management ? import_picocolors19.default.dim(`${management.apiKey.slice(0, 12)}\u2026${management.expiresAt ? ` \xB7 ${expiryLabel(management.expiresAt)}` : ""}`) : import_picocolors19.default.dim("\u2014 no key")}`
|
|
284872
|
+
);
|
|
284483
284873
|
for (const { key: m2, label } of [
|
|
284484
|
-
{ key: "sandbox", label: "
|
|
284485
|
-
{ key: "production", label: "
|
|
284874
|
+
{ key: "sandbox", label: "legacy child" },
|
|
284875
|
+
{ key: "production", label: "legacy root" }
|
|
284486
284876
|
]) {
|
|
284487
284877
|
const entry = getKeyEntry(m2);
|
|
284488
284878
|
if (entry) {
|
|
@@ -284490,106 +284880,104 @@ async function status(args = []) {
|
|
|
284490
284880
|
credentialCapability(entry.apiKey).label,
|
|
284491
284881
|
entry.expiresAt ? expiryLabel(entry.expiresAt) : ""
|
|
284492
284882
|
].filter(Boolean);
|
|
284493
|
-
const trail = facts.length ? ` ${
|
|
284883
|
+
const trail = facts.length ? ` ${import_picocolors19.default.dim("\xB7")} ${facts.join(import_picocolors19.default.dim(" \xB7 "))}` : "";
|
|
284494
284884
|
console.log(
|
|
284495
|
-
` ${
|
|
284885
|
+
` ${import_picocolors19.default.dim("\u25CB")} ${label.padEnd(12)} ${import_picocolors19.default.dim(`${entry.apiKey.slice(0, 12)}\u2026`)}${trail}`
|
|
284496
284886
|
);
|
|
284497
|
-
} else {
|
|
284498
|
-
console.log(` ${import_picocolors18.default.dim("\u25CB")} ${label.padEnd(10)} ${import_picocolors18.default.dim("\u2014 no key")}`);
|
|
284499
284887
|
}
|
|
284500
284888
|
}
|
|
284501
|
-
const
|
|
284889
|
+
const pushBranch = target?.confirmed?.branchRoot === true ? "production root" : target?.confirmed?.branchId ? `branch ${target.confirmed.branchId}` : runtimeKey.key ? "unknown branch" : "no branch";
|
|
284502
284890
|
console.log(
|
|
284503
|
-
` ${
|
|
284891
|
+
` ${import_picocolors19.default.dim("push")} ${runtimeKey.key ? `${import_picocolors19.default.bold(pushBranch)} ${import_picocolors19.default.dim(`with ${runtimeKey.key.slice(0, 12)}\u2026 (${runtimeKey.source})`)}` : `${import_picocolors19.default.bold(pushBranch)} ${import_picocolors19.default.yellow("\u2014 no runtime key")} ${import_picocolors19.default.dim(`(set ${import_picocolors19.default.bold("ABLO_API_KEY")} or run ${import_picocolors19.default.bold("ablo dev")})`)}`}`
|
|
284504
284892
|
);
|
|
284505
|
-
const capability = credentialCapability(
|
|
284506
|
-
if (capability.note) console.log(` ${
|
|
284507
|
-
process.stdout.write(` ${
|
|
284893
|
+
const capability = credentialCapability(runtimeKey.key);
|
|
284894
|
+
if (capability.note) console.log(` ${import_picocolors19.default.dim(capability.note)}`);
|
|
284895
|
+
process.stdout.write(` ${import_picocolors19.default.dim("api")} ${apiUrl3} `);
|
|
284508
284896
|
const reachable = await ping(apiUrl3);
|
|
284509
|
-
console.log(reachable ?
|
|
284510
|
-
const introspectKey =
|
|
284897
|
+
console.log(reachable ? import_picocolors19.default.green("reachable") : import_picocolors19.default.red("unreachable"));
|
|
284898
|
+
const introspectKey = runtimeKey.key;
|
|
284511
284899
|
const { source: dataSource, validation } = reachable ? await fetchRoutingState(apiUrl3, introspectKey) : { source: { kind: "unknown", detail: "unreachable" }, validation: null };
|
|
284512
284900
|
if (dataSource.kind === "connected") {
|
|
284513
284901
|
const how = [...new Set(dataSource.connections)].join(" + ");
|
|
284514
284902
|
const pooled = detectPoolerIn(dataSource.hosts);
|
|
284515
284903
|
const unreachable = validation && !validation.ok ? validation.message : void 0;
|
|
284516
|
-
console.log(` ${
|
|
284904
|
+
console.log(` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.green("\u2713")} ${import_picocolors19.default.dim(`database connected to this plane (${how})`)}`);
|
|
284517
284905
|
if (pooled) {
|
|
284518
284906
|
console.log(
|
|
284519
|
-
` ${
|
|
284907
|
+
` ${import_picocolors19.default.yellow("\u26A0")} ${import_picocolors19.default.dim(
|
|
284520
284908
|
`${pooled.host} is a connection pooler` + (pooled.direct ? `; register the direct host instead: ${pooled.direct}` : "; register the direct host instead")
|
|
284521
284909
|
)}`
|
|
284522
284910
|
);
|
|
284523
284911
|
}
|
|
284524
284912
|
if (unreachable) {
|
|
284525
|
-
console.log(` ${
|
|
284913
|
+
console.log(` ${import_picocolors19.default.red("\u2717")} ${import_picocolors19.default.dim(`Ablo could not reach it \u2014 ${unreachable}`)}`);
|
|
284526
284914
|
}
|
|
284527
284915
|
} else if (dataSource.kind === "none") {
|
|
284528
284916
|
console.log(
|
|
284529
|
-
` ${
|
|
284917
|
+
` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.red("\u2717 no database connected to this plane")} ${import_picocolors19.default.dim("\u2014 writes are held")}`
|
|
284530
284918
|
);
|
|
284531
284919
|
} else if (reachable) {
|
|
284532
|
-
console.log(` ${
|
|
284920
|
+
console.log(` ${import_picocolors19.default.dim("data")} ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim(`could not read the plane's databases (${dataSource.detail})`)}`);
|
|
284533
284921
|
}
|
|
284534
284922
|
const pushed = reachable ? await fetchPushedSchema(apiUrl3, introspectKey) : null;
|
|
284535
284923
|
if (reachable) {
|
|
284536
284924
|
if (pushed?.active) {
|
|
284537
|
-
const when = pushed.pushedAt ? ` ${
|
|
284538
|
-
const ver = pushed.version != null ? ` ${
|
|
284539
|
-
const hashLabel = pushed.hash ? ` ${
|
|
284540
|
-
console.log(` ${
|
|
284925
|
+
const when = pushed.pushedAt ? ` ${import_picocolors19.default.dim(`@ ${pushed.pushedAt.slice(0, 10)}`)}` : "";
|
|
284926
|
+
const ver = pushed.version != null ? ` ${import_picocolors19.default.dim(`(rev ${pushed.version})`)}` : "";
|
|
284927
|
+
const hashLabel = pushed.hash ? ` ${import_picocolors19.default.dim(`hash ${pushed.hash}`)}` : "";
|
|
284928
|
+
console.log(` ${import_picocolors19.default.dim("schema")} ${import_picocolors19.default.bold(`${pushed.models.length} models pushed`)}${ver}${hashLabel}${when}`);
|
|
284541
284929
|
for (const m2 of pushed.models) {
|
|
284542
|
-
const tn = m2.typename === m2.key ?
|
|
284930
|
+
const tn = m2.typename === m2.key ? import_picocolors19.default.dim(`typename=${m2.typename}`) : import_picocolors19.default.yellow(`typename=${m2.typename}`);
|
|
284543
284931
|
const conflict = formatConflict(m2.conflict);
|
|
284544
|
-
const conflictStr2 = conflict ? ` ${
|
|
284545
|
-
console.log(` ${
|
|
284932
|
+
const conflictStr2 = conflict ? ` ${import_picocolors19.default.dim(`conflict=${conflict}`)}` : "";
|
|
284933
|
+
console.log(` ${import_picocolors19.default.dim("\u2022")} ${m2.key.padEnd(14)} ${tn}${conflictStr2}`);
|
|
284546
284934
|
}
|
|
284547
284935
|
} else if (pushed && !pushed.active) {
|
|
284548
|
-
console.log(` ${
|
|
284936
|
+
console.log(` ${import_picocolors19.default.dim("schema")} ${import_picocolors19.default.yellow("none pushed")} ${import_picocolors19.default.dim(`(run ${import_picocolors19.default.bold("ablo push")} or ${import_picocolors19.default.bold("ablo dev")})`)}`);
|
|
284549
284937
|
}
|
|
284550
284938
|
}
|
|
284551
284939
|
const drift = schemaDrift(await readLocalSchemaHash(), pushed?.hash);
|
|
284552
284940
|
if (drift) {
|
|
284553
284941
|
console.log(
|
|
284554
|
-
` ${
|
|
284942
|
+
` ${import_picocolors19.default.dim("drift")} ${import_picocolors19.default.red("\u2717 local schema differs from the server")} ` + import_picocolors19.default.dim(`(local ${drift.local}, server ${drift.server})`)
|
|
284555
284943
|
);
|
|
284556
284944
|
}
|
|
284557
284945
|
const found = blockers({
|
|
284558
284946
|
reachable,
|
|
284559
|
-
hasKey: Boolean(
|
|
284947
|
+
hasKey: Boolean(runtimeKey.key),
|
|
284560
284948
|
dataSource,
|
|
284561
284949
|
schemaPushed: Boolean(pushed?.active),
|
|
284562
284950
|
drift
|
|
284563
284951
|
});
|
|
284564
284952
|
console.log();
|
|
284565
284953
|
if (found.length > 0) {
|
|
284566
|
-
console.log(` ${
|
|
284954
|
+
console.log(` ${import_picocolors19.default.red("\u2717")} ${import_picocolors19.default.bold("writes would fail right now")}`);
|
|
284567
284955
|
for (const b4 of found) {
|
|
284568
|
-
console.log(` ${
|
|
284569
|
-
console.log(` ${
|
|
284956
|
+
console.log(` ${import_picocolors19.default.dim("\xB7")} ${b4.problem}`);
|
|
284957
|
+
console.log(` ${import_picocolors19.default.dim(b4.fix)}`);
|
|
284570
284958
|
}
|
|
284571
284959
|
} else if (dataSource.kind === "unknown") {
|
|
284572
284960
|
console.log(
|
|
284573
|
-
` ${
|
|
284961
|
+
` ${import_picocolors19.default.yellow("?")} ${import_picocolors19.default.dim("nothing is blocking a write, but this key could not read the plane's databases \u2014 some checks were skipped")}`
|
|
284574
284962
|
);
|
|
284575
284963
|
} else {
|
|
284576
|
-
console.log(` ${
|
|
284964
|
+
console.log(` ${import_picocolors19.default.green("\u2713")} ${import_picocolors19.default.dim("ready \u2014 a write should succeed")}`);
|
|
284577
284965
|
}
|
|
284578
284966
|
console.log();
|
|
284579
284967
|
}
|
|
284580
284968
|
|
|
284581
284969
|
// src/doctor.ts
|
|
284582
284970
|
init_cjs_shims();
|
|
284583
|
-
var
|
|
284971
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
284584
284972
|
init_theme();
|
|
284585
284973
|
init_controlPlane();
|
|
284586
284974
|
init_config();
|
|
284587
284975
|
init_target();
|
|
284588
284976
|
init_readiness();
|
|
284589
284977
|
function render(check2) {
|
|
284590
|
-
const mark = check2.state === "ok" ?
|
|
284591
|
-
console.log(` ${mark} ${check2.label.padEnd(10)} ${check2.state === "fail" ? check2.detail :
|
|
284592
|
-
if (check2.fix) console.log(` ${" ".repeat(11)}${
|
|
284978
|
+
const mark = check2.state === "ok" ? import_picocolors20.default.green("\u2713") : check2.state === "fail" ? import_picocolors20.default.red("\u2717") : import_picocolors20.default.dim("\u2013");
|
|
284979
|
+
console.log(` ${mark} ${check2.label.padEnd(10)} ${check2.state === "fail" ? check2.detail : import_picocolors20.default.dim(check2.detail)}`);
|
|
284980
|
+
if (check2.fix) console.log(` ${" ".repeat(11)}${import_picocolors20.default.dim(`\u2192 ${check2.fix}`)}`);
|
|
284593
284981
|
}
|
|
284594
284982
|
async function ping2(apiUrl3) {
|
|
284595
284983
|
const ctrl = new AbortController();
|
|
@@ -284607,16 +284995,16 @@ async function ping2(apiUrl3) {
|
|
|
284607
284995
|
}
|
|
284608
284996
|
async function doctor() {
|
|
284609
284997
|
console.log(`
|
|
284610
|
-
${brand("ablo")} ${
|
|
284998
|
+
${brand("ablo")} ${import_picocolors20.default.dim("doctor")}
|
|
284611
284999
|
`);
|
|
284612
285000
|
const apiUrl3 = apiBaseUrl();
|
|
284613
|
-
const
|
|
285001
|
+
const runtimeKey = resolveRuntimeApiKey();
|
|
284614
285002
|
const checks = [];
|
|
284615
|
-
if (
|
|
285003
|
+
if (runtimeKey.key) {
|
|
284616
285004
|
checks.push({
|
|
284617
285005
|
label: "key",
|
|
284618
285006
|
state: "ok",
|
|
284619
|
-
detail: `${
|
|
285007
|
+
detail: `${runtimeKey.key.slice(0, 12)}\u2026 from ${runtimeKey.source}`
|
|
284620
285008
|
});
|
|
284621
285009
|
} else {
|
|
284622
285010
|
checks.push({
|
|
@@ -284635,7 +285023,7 @@ async function doctor() {
|
|
|
284635
285023
|
fix: "check your connection, then re-run `ablo doctor`"
|
|
284636
285024
|
}
|
|
284637
285025
|
);
|
|
284638
|
-
const target =
|
|
285026
|
+
const target = runtimeKey.key ? await resolveTarget({ url: apiUrl3, apiKey: runtimeKey.key, keySource: runtimeKey.source ?? "stored" }) : null;
|
|
284639
285027
|
const confirmed = target?.confirmed ?? null;
|
|
284640
285028
|
if (confirmed) {
|
|
284641
285029
|
const project = confirmed.project ? confirmed.project.isDefault ? "default" : confirmed.project.name === null ? `${confirmed.project.id} (unnamed \u2014 ${confirmed.project.unnamedReason ?? "the project list did not answer"})` : `${confirmed.project.slug} (${confirmed.project.id})` : "default";
|
|
@@ -284648,12 +285036,12 @@ async function doctor() {
|
|
|
284648
285036
|
const local = getActiveProject();
|
|
284649
285037
|
checks.push({
|
|
284650
285038
|
label: "identity",
|
|
284651
|
-
state:
|
|
284652
|
-
detail:
|
|
284653
|
-
fix:
|
|
285039
|
+
state: runtimeKey.key && reachable ? "fail" : "skip",
|
|
285040
|
+
detail: runtimeKey.key ? `the server did not resolve this key${local ? ` (locally selected: ${local.slug})` : ""}` : "no key to resolve",
|
|
285041
|
+
fix: runtimeKey.key ? "check the key is valid and not expired \u2014 `ablo login` mints a fresh pair" : void 0
|
|
284654
285042
|
});
|
|
284655
285043
|
}
|
|
284656
|
-
const { source: dataSource, validation } = reachable ? await fetchRoutingState(apiUrl3,
|
|
285044
|
+
const { source: dataSource, validation } = reachable ? await fetchRoutingState(apiUrl3, runtimeKey.key) : { source: { kind: "unknown", detail: "unreachable" }, validation: null };
|
|
284657
285045
|
if (dataSource.kind === "connected") {
|
|
284658
285046
|
const how = [...new Set(dataSource.connections)].join(" + ");
|
|
284659
285047
|
const pooled = detectPoolerIn(dataSource.hosts);
|
|
@@ -284675,13 +285063,13 @@ async function doctor() {
|
|
|
284675
285063
|
} else {
|
|
284676
285064
|
checks.push({ label: "data", state: "skip", detail: `not determined (${dataSource.detail})` });
|
|
284677
285065
|
}
|
|
284678
|
-
const pushed = reachable ? await fetchPushedSchema(apiUrl3,
|
|
285066
|
+
const pushed = reachable ? await fetchPushedSchema(apiUrl3, runtimeKey.key) : null;
|
|
284679
285067
|
checks.push(
|
|
284680
285068
|
pushed?.active ? {
|
|
284681
285069
|
label: "schema",
|
|
284682
285070
|
state: "ok",
|
|
284683
285071
|
detail: `${pushed.models.length} models active${pushed.hash ? `, hash ${pushed.hash}` : ""}`
|
|
284684
|
-
} : reachable &&
|
|
285072
|
+
} : reachable && runtimeKey.key ? { label: "schema", state: "fail", detail: "none active for this key", fix: "run `ablo push`" } : { label: "schema", state: "skip", detail: "not determined" }
|
|
284685
285073
|
);
|
|
284686
285074
|
const drift = schemaDrift(await readLocalSchemaHash(), pushed?.hash);
|
|
284687
285075
|
if (drift) {
|
|
@@ -284712,7 +285100,7 @@ async function doctor() {
|
|
|
284712
285100
|
for (const check2 of checks) render(check2);
|
|
284713
285101
|
const blocking = blockers({
|
|
284714
285102
|
reachable,
|
|
284715
|
-
hasKey: Boolean(
|
|
285103
|
+
hasKey: Boolean(runtimeKey.key),
|
|
284716
285104
|
dataSource,
|
|
284717
285105
|
schemaPushed: Boolean(pushed?.active),
|
|
284718
285106
|
drift
|
|
@@ -284722,15 +285110,15 @@ async function doctor() {
|
|
|
284722
285110
|
console.log();
|
|
284723
285111
|
if (failed > 0) {
|
|
284724
285112
|
console.log(
|
|
284725
|
-
` ${
|
|
285113
|
+
` ${import_picocolors20.default.red("\u2717")} ${import_picocolors20.default.bold(`${failed} problem${failed === 1 ? "" : "s"}`)}` + import_picocolors20.default.dim(skipped > 0 ? `, ${skipped} check${skipped === 1 ? "" : "s"} skipped` : "")
|
|
284726
285114
|
);
|
|
284727
|
-
console.log(
|
|
285115
|
+
console.log(import_picocolors20.default.dim(" Fix them in the order above \u2014 an earlier one often explains a later one."));
|
|
284728
285116
|
} else if (skipped > 0) {
|
|
284729
285117
|
console.log(
|
|
284730
|
-
` ${
|
|
285118
|
+
` ${import_picocolors20.default.yellow("?")} ${import_picocolors20.default.dim(`nothing is blocking a write, but ${skipped} check${skipped === 1 ? "" : "s"} could not be run`)}`
|
|
284731
285119
|
);
|
|
284732
285120
|
} else {
|
|
284733
|
-
console.log(` ${
|
|
285121
|
+
console.log(` ${import_picocolors20.default.green("\u2713")} ${import_picocolors20.default.dim("everything checks out \u2014 a write should succeed")}`);
|
|
284734
285122
|
}
|
|
284735
285123
|
console.log();
|
|
284736
285124
|
if (blocking.length > 0 || failed > 0) process.exitCode = 1;
|
|
@@ -284738,9 +285126,9 @@ async function doctor() {
|
|
|
284738
285126
|
|
|
284739
285127
|
// src/logs.ts
|
|
284740
285128
|
init_cjs_shims();
|
|
284741
|
-
var
|
|
284742
|
-
var
|
|
284743
|
-
var
|
|
285129
|
+
var import_errors16 = require("@abloatai/transaction/errors");
|
|
285130
|
+
var import_wire9 = require("@abloatai/transaction/wire");
|
|
285131
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
284744
285132
|
init_config();
|
|
284745
285133
|
init_theme();
|
|
284746
285134
|
init_controlPlane();
|
|
@@ -284751,8 +285139,7 @@ function parseLogsArgs(argv) {
|
|
|
284751
285139
|
since: void 0,
|
|
284752
285140
|
model: void 0,
|
|
284753
285141
|
op: void 0,
|
|
284754
|
-
json: false
|
|
284755
|
-
mode: void 0
|
|
285142
|
+
json: false
|
|
284756
285143
|
};
|
|
284757
285144
|
for (let i = 0; i < argv.length; i++) {
|
|
284758
285145
|
const arg = argv[i];
|
|
@@ -284780,15 +285167,13 @@ function parseLogsArgs(argv) {
|
|
|
284780
285167
|
case "--json":
|
|
284781
285168
|
args.json = true;
|
|
284782
285169
|
break;
|
|
284783
|
-
case "--mode":
|
|
284784
|
-
|
|
284785
|
-
|
|
284786
|
-
|
|
284787
|
-
|
|
284788
|
-
break;
|
|
284789
|
-
}
|
|
285170
|
+
case "--mode":
|
|
285171
|
+
throw new import_errors16.AbloValidationError(
|
|
285172
|
+
"--mode was removed. Logs follow the branch bound to ABLO_API_KEY; select a different branch by supplying its key.",
|
|
285173
|
+
{ code: "cli_invalid_arguments" }
|
|
285174
|
+
);
|
|
284790
285175
|
default:
|
|
284791
|
-
throw new
|
|
285176
|
+
throw new import_errors16.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
284792
285177
|
}
|
|
284793
285178
|
}
|
|
284794
285179
|
return args;
|
|
@@ -284807,10 +285192,10 @@ function resolveSince(since) {
|
|
|
284807
285192
|
var sleep2 = (ms) => new Promise((r2) => setTimeout(r2, ms));
|
|
284808
285193
|
function colorOp(op) {
|
|
284809
285194
|
const label = op.padEnd(6);
|
|
284810
|
-
if (op === "create") return
|
|
284811
|
-
if (op === "update") return
|
|
284812
|
-
if (op === "delete") return
|
|
284813
|
-
return
|
|
285195
|
+
if (op === "create") return import_picocolors21.default.green(label);
|
|
285196
|
+
if (op === "update") return import_picocolors21.default.yellow(label);
|
|
285197
|
+
if (op === "delete") return import_picocolors21.default.red(label);
|
|
285198
|
+
return import_picocolors21.default.dim(label);
|
|
284814
285199
|
}
|
|
284815
285200
|
function render2(e2, json) {
|
|
284816
285201
|
if (json) {
|
|
@@ -284819,21 +285204,21 @@ function render2(e2, json) {
|
|
|
284819
285204
|
return;
|
|
284820
285205
|
}
|
|
284821
285206
|
const t = new Date(e2.at).toLocaleTimeString();
|
|
284822
|
-
const actor = e2.actor ?
|
|
284823
|
-
console.log(` ${
|
|
285207
|
+
const actor = e2.actor ? import_picocolors21.default.dim(` ${e2.actor}`) : "";
|
|
285208
|
+
console.log(` ${import_picocolors21.default.dim(t)} ${colorOp(e2.op)} ${import_picocolors21.default.bold(e2.model)} ${import_picocolors21.default.dim(e2.recordId)}${actor}`);
|
|
284824
285209
|
}
|
|
284825
285210
|
async function logs(argv) {
|
|
284826
285211
|
let args;
|
|
284827
285212
|
try {
|
|
284828
285213
|
args = parseLogsArgs(argv);
|
|
284829
285214
|
} catch (err) {
|
|
284830
|
-
console.error(
|
|
285215
|
+
console.error(import_picocolors21.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
284831
285216
|
process.exit(1);
|
|
284832
285217
|
}
|
|
284833
|
-
const apiKey =
|
|
285218
|
+
const apiKey = resolveRuntimeApiKey().key;
|
|
284834
285219
|
if (!apiKey) {
|
|
284835
285220
|
console.error(
|
|
284836
|
-
|
|
285221
|
+
import_picocolors21.default.red(` No API key.`) + import_picocolors21.default.dim(` Run ${import_picocolors21.default.bold("ablo login")} or set ${import_picocolors21.default.bold("ABLO_API_KEY")}.`)
|
|
284837
285222
|
);
|
|
284838
285223
|
process.exit(1);
|
|
284839
285224
|
}
|
|
@@ -284847,18 +285232,18 @@ async function logs(argv) {
|
|
|
284847
285232
|
if (!res) return null;
|
|
284848
285233
|
if (!res.ok) {
|
|
284849
285234
|
const body = await res.json().catch(() => ({}));
|
|
284850
|
-
console.error(
|
|
285235
|
+
console.error(import_picocolors21.default.red(` logs failed (${res.status}): ${body.reason ?? body.message ?? ""}`));
|
|
284851
285236
|
process.exit(1);
|
|
284852
285237
|
}
|
|
284853
285238
|
const json = await res.json();
|
|
284854
285239
|
return {
|
|
284855
285240
|
events: json.data ?? json.events ?? [],
|
|
284856
|
-
cursor: json.next_cursor ?? (json.cursor != null ? (0,
|
|
285241
|
+
cursor: json.next_cursor ?? (json.cursor != null ? (0, import_wire9.formatFeedCursor)({ log: json.cursor, claims: 0 }) : (0, import_wire9.formatFeedCursor)(import_wire9.FEED_CURSOR_START))
|
|
284857
285242
|
};
|
|
284858
285243
|
}
|
|
284859
285244
|
if (!args.json) {
|
|
284860
285245
|
console.log(`
|
|
284861
|
-
${brand("ablo")} ${
|
|
285246
|
+
${brand("ablo")} ${import_picocolors21.default.dim("logs")}
|
|
284862
285247
|
`);
|
|
284863
285248
|
}
|
|
284864
285249
|
const initial = await fetchPage({
|
|
@@ -284868,13 +285253,13 @@ async function logs(argv) {
|
|
|
284868
285253
|
...args.op ? { op: args.op } : {}
|
|
284869
285254
|
});
|
|
284870
285255
|
if (!initial) {
|
|
284871
|
-
console.error(
|
|
285256
|
+
console.error(import_picocolors21.default.red(` Couldn't reach ${baseUrl2}.`));
|
|
284872
285257
|
process.exit(1);
|
|
284873
285258
|
}
|
|
284874
285259
|
for (const e2 of initial.events) render2(e2, args.json);
|
|
284875
285260
|
let cursor = initial.cursor;
|
|
284876
285261
|
if (!args.follow) return;
|
|
284877
|
-
if (!args.json) console.log(` ${
|
|
285262
|
+
if (!args.json) console.log(` ${import_picocolors21.default.dim("watching for new activity \u2026 (Ctrl-C to stop)")}
|
|
284878
285263
|
`);
|
|
284879
285264
|
for (; ; ) {
|
|
284880
285265
|
await sleep2(1500);
|
|
@@ -284885,16 +285270,16 @@ async function logs(argv) {
|
|
|
284885
285270
|
});
|
|
284886
285271
|
if (!page) continue;
|
|
284887
285272
|
for (const e2 of page.events) render2(e2, args.json);
|
|
284888
|
-
const prev = (0,
|
|
284889
|
-
const next = (0,
|
|
284890
|
-
if (prev && next && (0,
|
|
285273
|
+
const prev = (0, import_wire9.parseFeedCursor)(cursor);
|
|
285274
|
+
const next = (0, import_wire9.parseFeedCursor)(page.cursor);
|
|
285275
|
+
if (prev && next && (0, import_wire9.feedCursorAdvanced)(prev, next)) cursor = page.cursor;
|
|
284891
285276
|
}
|
|
284892
285277
|
}
|
|
284893
285278
|
|
|
284894
285279
|
// src/webhooks.ts
|
|
284895
285280
|
init_cjs_shims();
|
|
284896
285281
|
var import_fs9 = require("fs");
|
|
284897
|
-
var
|
|
285282
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
284898
285283
|
var import_credentialPolicy4 = require("@abloatai/transaction/auth/credentialPolicy");
|
|
284899
285284
|
init_config();
|
|
284900
285285
|
init_theme();
|
|
@@ -284924,15 +285309,15 @@ function positional(args) {
|
|
|
284924
285309
|
return void 0;
|
|
284925
285310
|
}
|
|
284926
285311
|
function requireKey3(mode) {
|
|
284927
|
-
const apiKey =
|
|
285312
|
+
const apiKey = resolveMutationApiKey(mode);
|
|
284928
285313
|
if (!apiKey) {
|
|
284929
285314
|
console.error(
|
|
284930
|
-
|
|
285315
|
+
import_picocolors22.default.red(" No API key.") + import_picocolors22.default.dim(` Run ${import_picocolors22.default.bold("ablo login")} or set ${import_picocolors22.default.bold("ABLO_API_KEY")}.`)
|
|
284931
285316
|
);
|
|
284932
285317
|
process.exit(1);
|
|
284933
285318
|
}
|
|
284934
285319
|
if ((0, import_credentialPolicy4.classifyCredentialKind)(apiKey) !== "secret") {
|
|
284935
|
-
console.error(
|
|
285320
|
+
console.error(import_picocolors22.default.red(" Managing webhooks requires a branch-bound secret key ") + import_picocolors22.default.dim("(sk_)."));
|
|
284936
285321
|
process.exit(1);
|
|
284937
285322
|
}
|
|
284938
285323
|
return apiKey;
|
|
@@ -284948,12 +285333,12 @@ async function api(apiKey, method, path, body) {
|
|
|
284948
285333
|
...body ? { body: JSON.stringify(body) } : {}
|
|
284949
285334
|
}).catch(() => null);
|
|
284950
285335
|
if (!res) {
|
|
284951
|
-
console.error(
|
|
285336
|
+
console.error(import_picocolors22.default.red(` Couldn't reach ${baseUrl()}.`));
|
|
284952
285337
|
process.exit(1);
|
|
284953
285338
|
}
|
|
284954
285339
|
if (!res.ok) {
|
|
284955
285340
|
const err = await res.json().catch(() => ({}));
|
|
284956
|
-
console.error(
|
|
285341
|
+
console.error(import_picocolors22.default.red(` Request failed (${res.status}): ${err.message ?? err.reason ?? ""}`));
|
|
284957
285342
|
process.exit(1);
|
|
284958
285343
|
}
|
|
284959
285344
|
return await res.json();
|
|
@@ -284975,11 +285360,11 @@ ${line}
|
|
|
284975
285360
|
return file;
|
|
284976
285361
|
}
|
|
284977
285362
|
function printEndpoint(e2) {
|
|
284978
|
-
const dot = e2.status === "enabled" ?
|
|
284979
|
-
const health = e2.last_error ?
|
|
284980
|
-
console.log(` ${dot} ${
|
|
285363
|
+
const dot = e2.status === "enabled" ? import_picocolors22.default.green("\u25CF") : import_picocolors22.default.red("\u25CF");
|
|
285364
|
+
const health = e2.last_error ? import_picocolors22.default.red(` last error: ${e2.last_error}`) : "";
|
|
285365
|
+
console.log(` ${dot} ${import_picocolors22.default.bold(e2.id)} ${e2.url}`);
|
|
284981
285366
|
console.log(
|
|
284982
|
-
|
|
285367
|
+
import_picocolors22.default.dim(
|
|
284983
285368
|
` ${e2.status} \xB7 ${e2.environment} \xB7 events ${e2.enabled_events.join(",")} \xB7 cursor ${e2.cursor ?? "\u2014"}${health}`
|
|
284984
285369
|
)
|
|
284985
285370
|
);
|
|
@@ -284991,7 +285376,7 @@ async function webhooks(argv) {
|
|
|
284991
285376
|
if (sub === "create") {
|
|
284992
285377
|
const url = positional(rest);
|
|
284993
285378
|
if (!url) {
|
|
284994
|
-
console.error(
|
|
285379
|
+
console.error(import_picocolors22.default.red(" Usage: ") + brand("ablo webhooks create <url>"));
|
|
284995
285380
|
process.exit(1);
|
|
284996
285381
|
}
|
|
284997
285382
|
const apiKey = requireKey3(mode);
|
|
@@ -285003,8 +285388,8 @@ async function webhooks(argv) {
|
|
|
285003
285388
|
});
|
|
285004
285389
|
const file = writeSecretToEnv(created.secret);
|
|
285005
285390
|
console.log(`
|
|
285006
|
-
${
|
|
285007
|
-
console.log(` ${
|
|
285391
|
+
${import_picocolors22.default.green("\u2713")} Registered ${import_picocolors22.default.bold(created.id)} \u2192 ${created.url}`);
|
|
285392
|
+
console.log(` ${import_picocolors22.default.green("\u2713")} Wrote ${import_picocolors22.default.bold(ENV_KEY)} to ${import_picocolors22.default.bold(file)} ${import_picocolors22.default.dim("(shown once)")}
|
|
285008
285393
|
`);
|
|
285009
285394
|
return;
|
|
285010
285395
|
}
|
|
@@ -285012,7 +285397,7 @@ async function webhooks(argv) {
|
|
|
285012
285397
|
const apiKey = requireKey3(mode);
|
|
285013
285398
|
const { data } = await api(apiKey, "GET", "");
|
|
285014
285399
|
if (data.length === 0) {
|
|
285015
|
-
console.log(
|
|
285400
|
+
console.log(import_picocolors22.default.dim(" No webhook endpoints. ") + brand("ablo webhooks create <url>"));
|
|
285016
285401
|
return;
|
|
285017
285402
|
}
|
|
285018
285403
|
console.log();
|
|
@@ -285023,40 +285408,40 @@ async function webhooks(argv) {
|
|
|
285023
285408
|
if (sub === "roll") {
|
|
285024
285409
|
const id = positional(rest);
|
|
285025
285410
|
if (!id) {
|
|
285026
|
-
console.error(
|
|
285411
|
+
console.error(import_picocolors22.default.red(" Usage: ") + brand("ablo webhooks roll <id>"));
|
|
285027
285412
|
process.exit(1);
|
|
285028
285413
|
}
|
|
285029
285414
|
const apiKey = requireKey3(mode);
|
|
285030
285415
|
const rolled = await api(apiKey, "POST", `/${id}/roll_secret`);
|
|
285031
285416
|
const file = writeSecretToEnv(rolled.secret);
|
|
285032
285417
|
console.log(`
|
|
285033
|
-
${
|
|
285418
|
+
${import_picocolors22.default.green("\u2713")} Rolled secret for ${import_picocolors22.default.bold(id)} \u2192 ${import_picocolors22.default.bold(file)} ${import_picocolors22.default.dim("(old secret now invalid)")}
|
|
285034
285419
|
`);
|
|
285035
285420
|
return;
|
|
285036
285421
|
}
|
|
285037
285422
|
if (sub === "enable") {
|
|
285038
285423
|
const id = positional(rest);
|
|
285039
285424
|
if (!id) {
|
|
285040
|
-
console.error(
|
|
285425
|
+
console.error(import_picocolors22.default.red(" Usage: ") + brand("ablo webhooks enable <id>"));
|
|
285041
285426
|
process.exit(1);
|
|
285042
285427
|
}
|
|
285043
285428
|
const apiKey = requireKey3(mode);
|
|
285044
285429
|
const e2 = await api(apiKey, "POST", `/${id}/enable`);
|
|
285045
|
-
console.log(` ${
|
|
285430
|
+
console.log(` ${import_picocolors22.default.green("\u2713")} Re-enabled ${import_picocolors22.default.bold(e2.id)}`);
|
|
285046
285431
|
return;
|
|
285047
285432
|
}
|
|
285048
285433
|
if (sub === "rm" || sub === "delete") {
|
|
285049
285434
|
const id = positional(rest);
|
|
285050
285435
|
if (!id) {
|
|
285051
|
-
console.error(
|
|
285436
|
+
console.error(import_picocolors22.default.red(" Usage: ") + brand("ablo webhooks rm <id>"));
|
|
285052
285437
|
process.exit(1);
|
|
285053
285438
|
}
|
|
285054
285439
|
const apiKey = requireKey3(mode);
|
|
285055
285440
|
await api(apiKey, "DELETE", `/${id}`);
|
|
285056
|
-
console.log(` ${
|
|
285441
|
+
console.log(` ${import_picocolors22.default.green("\u2713")} Removed ${import_picocolors22.default.bold(id)}`);
|
|
285057
285442
|
return;
|
|
285058
285443
|
}
|
|
285059
|
-
console.log(` ${
|
|
285444
|
+
console.log(` ${import_picocolors22.default.bold("Usage:")}`);
|
|
285060
285445
|
console.log(` ${brand("ablo webhooks create <url>")} Register an endpoint; writes ${ENV_KEY}`);
|
|
285061
285446
|
console.log(` ${brand("ablo webhooks list")} List endpoints + delivery health`);
|
|
285062
285447
|
console.log(` ${brand("ablo webhooks roll <id>")} Mint a fresh signing secret`);
|
|
@@ -285067,8 +285452,8 @@ async function webhooks(argv) {
|
|
|
285067
285452
|
|
|
285068
285453
|
// src/check.ts
|
|
285069
285454
|
init_cjs_shims();
|
|
285070
|
-
var
|
|
285071
|
-
var
|
|
285455
|
+
var import_errors17 = require("@abloatai/transaction/errors");
|
|
285456
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
285072
285457
|
init_src();
|
|
285073
285458
|
var import_schema9 = require("@abloatai/transaction/schema");
|
|
285074
285459
|
init_push();
|
|
@@ -285215,7 +285600,7 @@ function parseCheckArgs(argv) {
|
|
|
285215
285600
|
appSchema = argv[++i] ?? appSchema;
|
|
285216
285601
|
break;
|
|
285217
285602
|
default:
|
|
285218
|
-
throw new
|
|
285603
|
+
throw new import_errors17.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
285219
285604
|
}
|
|
285220
285605
|
}
|
|
285221
285606
|
return { schemaPath, exportName, appSchema };
|
|
@@ -285229,22 +285614,22 @@ function hostOf(connectionString) {
|
|
|
285229
285614
|
}
|
|
285230
285615
|
async function reportReadSubject(dbUrl) {
|
|
285231
285616
|
const host = hostOf(dbUrl);
|
|
285232
|
-
console.log(` ${
|
|
285233
|
-
const
|
|
285234
|
-
const state = await fetchDataSourceState(apiBaseUrl(),
|
|
285617
|
+
console.log(` ${import_picocolors23.default.dim("reading")} ${import_picocolors23.default.bold(host ?? "your database")}`);
|
|
285618
|
+
const runtimeKey = resolveRuntimeApiKey();
|
|
285619
|
+
const state = await fetchDataSourceState(apiBaseUrl(), runtimeKey.key);
|
|
285235
285620
|
if (state.kind === "unknown") {
|
|
285236
285621
|
console.log(
|
|
285237
|
-
` ${
|
|
285622
|
+
` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.yellow("?")} ${import_picocolors23.default.dim(`couldn't ask which database Ablo reads (${state.detail})`)}
|
|
285238
285623
|
`
|
|
285239
285624
|
);
|
|
285240
285625
|
return;
|
|
285241
285626
|
}
|
|
285242
285627
|
if (state.kind === "none") {
|
|
285243
285628
|
console.log(
|
|
285244
|
-
` ${
|
|
285629
|
+
` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.yellow("!")} no database is registered for this plane, so Ablo does not read this one`
|
|
285245
285630
|
);
|
|
285246
285631
|
console.log(
|
|
285247
|
-
` ${
|
|
285632
|
+
` ${import_picocolors23.default.dim(`Connect it with ${import_picocolors23.default.bold("ablo connect apply")}. Until then a table here is invisible to the engine.`)}
|
|
285248
285633
|
`
|
|
285249
285634
|
);
|
|
285250
285635
|
return;
|
|
@@ -285252,15 +285637,15 @@ async function reportReadSubject(dbUrl) {
|
|
|
285252
285637
|
const registered = [...new Set(state.hosts)];
|
|
285253
285638
|
if (host && registered.length > 0 && !registered.includes(host)) {
|
|
285254
285639
|
console.log(
|
|
285255
|
-
` ${
|
|
285640
|
+
` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.yellow("!")} Ablo reads ${import_picocolors23.default.bold(registered.join(", "))}`
|
|
285256
285641
|
);
|
|
285257
285642
|
console.log(
|
|
285258
|
-
` ${
|
|
285643
|
+
` ${import_picocolors23.default.dim("If that is this database under a pooled hostname, this is fine \u2014 otherwise the report below describes a database Ablo never reads.")}
|
|
285259
285644
|
`
|
|
285260
285645
|
);
|
|
285261
285646
|
return;
|
|
285262
285647
|
}
|
|
285263
|
-
console.log(` ${
|
|
285648
|
+
console.log(` ${import_picocolors23.default.dim("ablo")} ${import_picocolors23.default.green("\u2713")} ${import_picocolors23.default.dim("reads this database")}
|
|
285264
285649
|
`);
|
|
285265
285650
|
}
|
|
285266
285651
|
async function check(argv) {
|
|
@@ -285268,20 +285653,20 @@ async function check(argv) {
|
|
|
285268
285653
|
try {
|
|
285269
285654
|
args = parseCheckArgs(argv);
|
|
285270
285655
|
} catch (err) {
|
|
285271
|
-
console.error(
|
|
285656
|
+
console.error(import_picocolors23.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
285272
285657
|
process.exit(1);
|
|
285273
285658
|
}
|
|
285274
285659
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
285275
285660
|
if (!dbUrl) {
|
|
285276
285661
|
console.error(
|
|
285277
|
-
|
|
285662
|
+
import_picocolors23.default.red(` No database.`) + import_picocolors23.default.dim(` Set ${import_picocolors23.default.bold(ADMIN_URL_VAR)} to the Postgres you want Ablo to adopt.`)
|
|
285278
285663
|
);
|
|
285279
285664
|
process.exit(1);
|
|
285280
285665
|
}
|
|
285281
285666
|
const schema = await loadSchema(args.schemaPath, args.exportName);
|
|
285282
285667
|
const schemaJson = JSON.parse((0, import_schema9.serializeSchema)(schema));
|
|
285283
285668
|
console.log(`
|
|
285284
|
-
${brand("ablo")} ${
|
|
285669
|
+
${brand("ablo")} ${import_picocolors23.default.dim("check")} ${import_picocolors23.default.dim(`schema "${args.appSchema}"`)}
|
|
285285
285670
|
`);
|
|
285286
285671
|
await reportReadSubject(dbUrl);
|
|
285287
285672
|
const sql = src_default(dbUrl, { max: 1, prepare: false, onnotice: () => {
|
|
@@ -285293,7 +285678,7 @@ async function check(argv) {
|
|
|
285293
285678
|
[args.appSchema]
|
|
285294
285679
|
);
|
|
285295
285680
|
} catch (err) {
|
|
285296
|
-
console.error(
|
|
285681
|
+
console.error(import_picocolors23.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
|
|
285297
285682
|
await sql.end({ timeout: 2 });
|
|
285298
285683
|
process.exit(1);
|
|
285299
285684
|
}
|
|
@@ -285315,7 +285700,7 @@ async function check(argv) {
|
|
|
285315
285700
|
declaredTables.add(table);
|
|
285316
285701
|
const present = colsByTable.get(table);
|
|
285317
285702
|
if (!present) {
|
|
285318
|
-
console.log(` ${
|
|
285703
|
+
console.log(` ${import_picocolors23.default.red("\u2717")} ${import_picocolors23.default.bold(key)} ${import_picocolors23.default.dim("\u2192")} table ${import_picocolors23.default.bold(table)} ${import_picocolors23.default.red("not found")}`);
|
|
285319
285704
|
errors++;
|
|
285320
285705
|
continue;
|
|
285321
285706
|
}
|
|
@@ -285337,26 +285722,26 @@ async function check(argv) {
|
|
|
285337
285722
|
if (!present.has(col)) problems.push(`missing column "${col}" (field ${fieldName})`);
|
|
285338
285723
|
}
|
|
285339
285724
|
if (problems.length > 0) {
|
|
285340
|
-
console.log(` ${
|
|
285341
|
-
for (const p2 of problems) console.log(` ${
|
|
285342
|
-
for (const w2 of warns) console.log(` ${
|
|
285725
|
+
console.log(` ${import_picocolors23.default.red("\u2717")} ${import_picocolors23.default.bold(key)} ${import_picocolors23.default.dim("\u2192")} ${table}`);
|
|
285726
|
+
for (const p2 of problems) console.log(` ${import_picocolors23.default.red("\u2022")} ${p2}`);
|
|
285727
|
+
for (const w2 of warns) console.log(` ${import_picocolors23.default.yellow("\u2022")} ${w2}`);
|
|
285343
285728
|
errors++;
|
|
285344
285729
|
} else if (warns.length > 0) {
|
|
285345
|
-
console.log(` ${
|
|
285346
|
-
for (const w2 of warns) console.log(` ${
|
|
285730
|
+
console.log(` ${import_picocolors23.default.yellow("!")} ${import_picocolors23.default.bold(key)} ${import_picocolors23.default.dim("\u2192")} ${table}`);
|
|
285731
|
+
for (const w2 of warns) console.log(` ${import_picocolors23.default.yellow("\u2022")} ${w2}`);
|
|
285347
285732
|
warnings++;
|
|
285348
285733
|
} else {
|
|
285349
|
-
console.log(` ${
|
|
285734
|
+
console.log(` ${import_picocolors23.default.green("\u2713")} ${import_picocolors23.default.bold(key)} ${import_picocolors23.default.dim(`\u2192 ${table} (id, ${orgCol ?? "no org"} ok)`)}`);
|
|
285350
285735
|
}
|
|
285351
285736
|
}
|
|
285352
285737
|
const modelCount = Object.keys(schemaJson.models).length;
|
|
285353
285738
|
const ignored = [...colsByTable.keys()].filter((t) => !declaredTables.has(t)).length;
|
|
285354
285739
|
console.log(
|
|
285355
285740
|
`
|
|
285356
|
-
${modelCount} model${modelCount === 1 ? "" : "s"} \xB7 ${
|
|
285741
|
+
${modelCount} model${modelCount === 1 ? "" : "s"} \xB7 ${import_picocolors23.default.green(`${modelCount - errors - warnings} ok`)}` + (warnings ? ` \xB7 ${import_picocolors23.default.yellow(`${warnings} warning${warnings === 1 ? "" : "s"}`)}` : "") + (errors ? ` \xB7 ${import_picocolors23.default.red(`${errors} error${errors === 1 ? "" : "s"}`)}` : "")
|
|
285357
285742
|
);
|
|
285358
285743
|
if (ignored > 0) {
|
|
285359
|
-
console.log(` ${
|
|
285744
|
+
console.log(` ${import_picocolors23.default.dim(`${ignored} other table${ignored === 1 ? "" : "s"} in your database \u2014 ignored by Ablo`)}`);
|
|
285360
285745
|
}
|
|
285361
285746
|
console.log();
|
|
285362
285747
|
process.exit(errors > 0 ? 1 : 0);
|
|
@@ -285367,7 +285752,7 @@ init_dbRole();
|
|
|
285367
285752
|
|
|
285368
285753
|
// src/upgrade.ts
|
|
285369
285754
|
init_cjs_shims();
|
|
285370
|
-
var
|
|
285755
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
285371
285756
|
var import_ts_morph = __toESM(require_ts_morph(), 1);
|
|
285372
285757
|
var DEFAULT_GLOBS = ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}", "ablo/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}"];
|
|
285373
285758
|
var VERB_ARGS = {
|
|
@@ -285445,7 +285830,7 @@ async function upgrade(argv) {
|
|
|
285445
285830
|
project.addSourceFilesAtPaths(globs.length > 0 ? globs : DEFAULT_GLOBS);
|
|
285446
285831
|
const files = project.getSourceFiles();
|
|
285447
285832
|
if (files.length === 0) {
|
|
285448
|
-
console.log(
|
|
285833
|
+
console.log(import_picocolors24.default.yellow(' No .ts/.tsx files found. Pass a glob, e.g. `ablo upgrade "src/**/*.tsx"`.'));
|
|
285449
285834
|
return;
|
|
285450
285835
|
}
|
|
285451
285836
|
const edits = [];
|
|
@@ -285519,39 +285904,39 @@ async function upgrade(argv) {
|
|
|
285519
285904
|
const rel = (f) => f.replace(cwd + "/", "");
|
|
285520
285905
|
console.log();
|
|
285521
285906
|
if (edits.length === 0 && manual.length === 0) {
|
|
285522
|
-
console.log(
|
|
285907
|
+
console.log(import_picocolors24.default.green(" \u2713 Nothing to migrate \u2014 your code is already on the current API."));
|
|
285523
285908
|
return;
|
|
285524
285909
|
}
|
|
285525
285910
|
if (edits.length > 0) {
|
|
285526
|
-
console.log(
|
|
285911
|
+
console.log(import_picocolors24.default.bold(` ${write ? "Applied" : "Would apply"} ${edits.length} change${edits.length === 1 ? "" : "s"}:`));
|
|
285527
285912
|
for (const e2 of edits) {
|
|
285528
|
-
console.log(` ${
|
|
285529
|
-
console.log(` ${
|
|
285530
|
-
console.log(` ${
|
|
285913
|
+
console.log(` ${import_picocolors24.default.dim(`${rel(e2.file)}:${e2.line}`)} ${import_picocolors24.default.cyan(e2.rule)}`);
|
|
285914
|
+
console.log(` ${import_picocolors24.default.red("-")} ${e2.before}`);
|
|
285915
|
+
console.log(` ${import_picocolors24.default.green("+")} ${e2.after}`);
|
|
285531
285916
|
}
|
|
285532
285917
|
}
|
|
285533
285918
|
if (manual.length > 0) {
|
|
285534
285919
|
console.log();
|
|
285535
|
-
console.log(
|
|
285920
|
+
console.log(import_picocolors24.default.bold(import_picocolors24.default.yellow(` ${manual.length} spot${manual.length === 1 ? "" : "s"} need manual review (structural):`)));
|
|
285536
285921
|
for (const m2 of manual) {
|
|
285537
|
-
console.log(` ${
|
|
285538
|
-
console.log(` ${
|
|
285922
|
+
console.log(` ${import_picocolors24.default.dim(`${rel(m2.file)}:${m2.line}`)} ${import_picocolors24.default.yellow(m2.rule)}`);
|
|
285923
|
+
console.log(` ${import_picocolors24.default.dim(m2.snippet)}`);
|
|
285539
285924
|
console.log(` \u2192 ${m2.hint}`);
|
|
285540
285925
|
}
|
|
285541
285926
|
}
|
|
285542
285927
|
console.log();
|
|
285543
285928
|
if (write) {
|
|
285544
285929
|
await project.save();
|
|
285545
|
-
console.log(
|
|
285930
|
+
console.log(import_picocolors24.default.green(` \u2713 Wrote ${edits.length} change${edits.length === 1 ? "" : "s"}. Review the diff, run your typecheck.`));
|
|
285546
285931
|
} else {
|
|
285547
|
-
console.log(
|
|
285932
|
+
console.log(import_picocolors24.default.dim(" Dry run. Re-run with `--write` to apply the auto-fixes above (manual items are never auto-written)."));
|
|
285548
285933
|
}
|
|
285549
285934
|
}
|
|
285550
285935
|
|
|
285551
285936
|
// src/pull.ts
|
|
285552
285937
|
init_cjs_shims();
|
|
285553
|
-
var
|
|
285554
|
-
var
|
|
285938
|
+
var import_errors18 = require("@abloatai/transaction/errors");
|
|
285939
|
+
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
285555
285940
|
init_src();
|
|
285556
285941
|
var import_fs10 = require("fs");
|
|
285557
285942
|
init_theme();
|
|
@@ -285579,7 +285964,7 @@ function parsePullArgs(argv) {
|
|
|
285579
285964
|
force = true;
|
|
285580
285965
|
break;
|
|
285581
285966
|
default:
|
|
285582
|
-
throw new
|
|
285967
|
+
throw new import_errors18.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
285583
285968
|
}
|
|
285584
285969
|
}
|
|
285585
285970
|
return { out, appSchema, importPath, force };
|
|
@@ -285649,56 +286034,56 @@ async function pull(argv) {
|
|
|
285649
286034
|
try {
|
|
285650
286035
|
args = parsePullArgs(argv);
|
|
285651
286036
|
} catch (err) {
|
|
285652
|
-
console.error(
|
|
286037
|
+
console.error(import_picocolors25.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
285653
286038
|
process.exit(1);
|
|
285654
286039
|
}
|
|
285655
286040
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
285656
286041
|
if (!dbUrl) {
|
|
285657
286042
|
console.error(
|
|
285658
|
-
|
|
286043
|
+
import_picocolors25.default.red(` No database.`) + import_picocolors25.default.dim(` Set ${import_picocolors25.default.bold(ADMIN_URL_VAR)} to the Postgres to pull from.`)
|
|
285659
286044
|
);
|
|
285660
286045
|
process.exit(1);
|
|
285661
286046
|
}
|
|
285662
286047
|
if ((0, import_fs10.existsSync)(args.out) && !args.force) {
|
|
285663
286048
|
console.error(
|
|
285664
|
-
|
|
286049
|
+
import_picocolors25.default.red(` ${args.out} already exists.`) + import_picocolors25.default.dim(` Re-run with ${import_picocolors25.default.bold("--force")} to overwrite.`)
|
|
285665
286050
|
);
|
|
285666
286051
|
process.exit(1);
|
|
285667
286052
|
}
|
|
285668
286053
|
console.log(`
|
|
285669
|
-
${brand("ablo")} ${
|
|
286054
|
+
${brand("ablo")} ${import_picocolors25.default.dim("pull")} ${import_picocolors25.default.dim(`schema "${args.appSchema}"`)}
|
|
285670
286055
|
`);
|
|
285671
286056
|
let result;
|
|
285672
286057
|
try {
|
|
285673
286058
|
result = await buildSchemaSourceFromDb({ dbUrl, appSchema: args.appSchema, importPath: args.importPath });
|
|
285674
286059
|
} catch (err) {
|
|
285675
|
-
console.error(
|
|
286060
|
+
console.error(import_picocolors25.default.red(` Couldn't read the database: ${err instanceof Error ? err.message : String(err)}`));
|
|
285676
286061
|
process.exit(1);
|
|
285677
286062
|
}
|
|
285678
286063
|
if (result.models.length === 0) {
|
|
285679
286064
|
console.error(
|
|
285680
|
-
|
|
286065
|
+
import_picocolors25.default.yellow(` No adoptable tables found`) + import_picocolors25.default.dim(` (a model needs an ${import_picocolors25.default.bold("id")} + ${import_picocolors25.default.bold("organization_id")} column).`)
|
|
285681
286066
|
);
|
|
285682
286067
|
process.exit(1);
|
|
285683
286068
|
}
|
|
285684
286069
|
(0, import_fs10.writeFileSync)(args.out, result.source);
|
|
285685
|
-
console.log(` ${
|
|
285686
|
-
console.log(` ${
|
|
286070
|
+
console.log(` ${import_picocolors25.default.green("\u2713")} wrote ${import_picocolors25.default.bold(args.out)} ${import_picocolors25.default.dim(`(${result.models.length} models)`)}`);
|
|
286071
|
+
console.log(` ${import_picocolors25.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
285687
286072
|
if (result.skipped.length > 0) {
|
|
285688
|
-
console.log(` ${
|
|
285689
|
-
for (const s of result.skipped) console.log(` ${
|
|
286073
|
+
console.log(` ${import_picocolors25.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
|
|
286074
|
+
for (const s of result.skipped) console.log(` ${import_picocolors25.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
285690
286075
|
}
|
|
285691
286076
|
console.log(
|
|
285692
286077
|
`
|
|
285693
|
-
${
|
|
286078
|
+
${import_picocolors25.default.dim("Introspection is lossy (enums, JSON shape, relations). Review the file, then")} ${import_picocolors25.default.bold("ablo check")}.
|
|
285694
286079
|
`
|
|
285695
286080
|
);
|
|
285696
286081
|
}
|
|
285697
286082
|
|
|
285698
286083
|
// src/prismaPull.ts
|
|
285699
286084
|
init_cjs_shims();
|
|
285700
|
-
var
|
|
285701
|
-
var
|
|
286085
|
+
var import_errors19 = require("@abloatai/transaction/errors");
|
|
286086
|
+
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
285702
286087
|
var import_fs11 = require("fs");
|
|
285703
286088
|
init_theme();
|
|
285704
286089
|
var DEFAULT_SCHEMA = "prisma/schema.prisma";
|
|
@@ -285895,7 +286280,7 @@ function parsePrismaPullArgs(argv) {
|
|
|
285895
286280
|
force = true;
|
|
285896
286281
|
break;
|
|
285897
286282
|
default:
|
|
285898
|
-
if (arg.startsWith("--")) throw new
|
|
286283
|
+
if (arg.startsWith("--")) throw new import_errors19.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
285899
286284
|
schema = arg;
|
|
285900
286285
|
}
|
|
285901
286286
|
}
|
|
@@ -285906,56 +286291,56 @@ async function prismaPull(argv) {
|
|
|
285906
286291
|
try {
|
|
285907
286292
|
args = parsePrismaPullArgs(argv);
|
|
285908
286293
|
} catch (err) {
|
|
285909
|
-
console.error(
|
|
286294
|
+
console.error(import_picocolors26.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
285910
286295
|
process.exit(1);
|
|
285911
286296
|
}
|
|
285912
286297
|
if (!(0, import_fs11.existsSync)(args.schema)) {
|
|
285913
286298
|
console.error(
|
|
285914
|
-
|
|
286299
|
+
import_picocolors26.default.red(` No Prisma schema at ${import_picocolors26.default.bold(args.schema)}.`) + import_picocolors26.default.dim(` Pass a path: ${import_picocolors26.default.bold("ablo pull prisma <path>")}.`)
|
|
285915
286300
|
);
|
|
285916
286301
|
process.exit(1);
|
|
285917
286302
|
}
|
|
285918
286303
|
if ((0, import_fs11.existsSync)(args.out) && !args.force) {
|
|
285919
286304
|
console.error(
|
|
285920
|
-
|
|
286305
|
+
import_picocolors26.default.red(` ${args.out} already exists.`) + import_picocolors26.default.dim(` Re-run with ${import_picocolors26.default.bold("--force")} to overwrite.`)
|
|
285921
286306
|
);
|
|
285922
286307
|
process.exit(1);
|
|
285923
286308
|
}
|
|
285924
286309
|
console.log(`
|
|
285925
|
-
${brand("ablo")} ${
|
|
286310
|
+
${brand("ablo")} ${import_picocolors26.default.dim("pull prisma")} ${import_picocolors26.default.dim(args.schema)}
|
|
285926
286311
|
`);
|
|
285927
286312
|
let result;
|
|
285928
286313
|
try {
|
|
285929
286314
|
const src = (0, import_fs11.readFileSync)(args.schema, "utf8");
|
|
285930
286315
|
result = buildSchemaSourceFromPrisma({ src, importPath: args.importPath });
|
|
285931
286316
|
} catch (err) {
|
|
285932
|
-
console.error(
|
|
286317
|
+
console.error(import_picocolors26.default.red(` Couldn't parse the schema: ${err instanceof Error ? err.message : String(err)}`));
|
|
285933
286318
|
process.exit(1);
|
|
285934
286319
|
}
|
|
285935
286320
|
if (result.models.length === 0) {
|
|
285936
286321
|
console.error(
|
|
285937
|
-
|
|
286322
|
+
import_picocolors26.default.yellow(` No adoptable models found`) + import_picocolors26.default.dim(` (a model needs an ${import_picocolors26.default.bold("id")} + ${import_picocolors26.default.bold("organizationId")} / ${import_picocolors26.default.bold("organization_id")}).`)
|
|
285938
286323
|
);
|
|
285939
286324
|
process.exit(1);
|
|
285940
286325
|
}
|
|
285941
286326
|
(0, import_fs11.writeFileSync)(args.out, result.source);
|
|
285942
|
-
console.log(` ${
|
|
285943
|
-
console.log(` ${
|
|
286327
|
+
console.log(` ${import_picocolors26.default.green("\u2713")} wrote ${import_picocolors26.default.bold(args.out)} ${import_picocolors26.default.dim(`(${result.models.length} models)`)}`);
|
|
286328
|
+
console.log(` ${import_picocolors26.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
285944
286329
|
if (result.skipped.length > 0) {
|
|
285945
|
-
console.log(` ${
|
|
285946
|
-
for (const s of result.skipped) console.log(` ${
|
|
286330
|
+
console.log(` ${import_picocolors26.default.dim(`${result.skipped.length} model(s) skipped:`)}`);
|
|
286331
|
+
for (const s of result.skipped) console.log(` ${import_picocolors26.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
285947
286332
|
}
|
|
285948
286333
|
console.log(
|
|
285949
286334
|
`
|
|
285950
|
-
${
|
|
286335
|
+
${import_picocolors26.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors26.default.bold("ablo check")}.
|
|
285951
286336
|
`
|
|
285952
286337
|
);
|
|
285953
286338
|
}
|
|
285954
286339
|
|
|
285955
286340
|
// src/drizzlePull.ts
|
|
285956
286341
|
init_cjs_shims();
|
|
285957
|
-
var
|
|
285958
|
-
var
|
|
286342
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
286343
|
+
var import_errors20 = require("@abloatai/transaction/errors");
|
|
285959
286344
|
var import_fs12 = require("fs");
|
|
285960
286345
|
var import_path7 = require("path");
|
|
285961
286346
|
init_theme();
|
|
@@ -286062,7 +286447,7 @@ function parseDrizzlePullArgs(argv) {
|
|
|
286062
286447
|
force = true;
|
|
286063
286448
|
break;
|
|
286064
286449
|
default:
|
|
286065
|
-
if (arg.startsWith("--")) throw new
|
|
286450
|
+
if (arg.startsWith("--")) throw new import_errors20.AbloValidationError(`unknown flag: ${arg}`, { code: "cli_invalid_arguments" });
|
|
286066
286451
|
schema = arg;
|
|
286067
286452
|
}
|
|
286068
286453
|
}
|
|
@@ -286079,27 +286464,27 @@ async function drizzlePull(argv) {
|
|
|
286079
286464
|
try {
|
|
286080
286465
|
args = parseDrizzlePullArgs(argv);
|
|
286081
286466
|
} catch (err) {
|
|
286082
|
-
console.error(
|
|
286467
|
+
console.error(import_picocolors27.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
286083
286468
|
process.exit(1);
|
|
286084
286469
|
}
|
|
286085
286470
|
if (!args.schema) {
|
|
286086
286471
|
console.error(
|
|
286087
|
-
|
|
286472
|
+
import_picocolors27.default.red(` No Drizzle schema given.`) + import_picocolors27.default.dim(` Pass the module: ${import_picocolors27.default.bold("ablo pull drizzle src/db/schema.ts")}.`)
|
|
286088
286473
|
);
|
|
286089
286474
|
process.exit(1);
|
|
286090
286475
|
}
|
|
286091
286476
|
if (!(0, import_fs12.existsSync)(args.schema)) {
|
|
286092
|
-
console.error(
|
|
286477
|
+
console.error(import_picocolors27.default.red(` No file at ${import_picocolors27.default.bold(args.schema)}.`));
|
|
286093
286478
|
process.exit(1);
|
|
286094
286479
|
}
|
|
286095
286480
|
if ((0, import_fs12.existsSync)(args.out) && !args.force) {
|
|
286096
286481
|
console.error(
|
|
286097
|
-
|
|
286482
|
+
import_picocolors27.default.red(` ${args.out} already exists.`) + import_picocolors27.default.dim(` Re-run with ${import_picocolors27.default.bold("--force")} to overwrite.`)
|
|
286098
286483
|
);
|
|
286099
286484
|
process.exit(1);
|
|
286100
286485
|
}
|
|
286101
286486
|
console.log(`
|
|
286102
|
-
${brand("ablo")} ${
|
|
286487
|
+
${brand("ablo")} ${import_picocolors27.default.dim("pull drizzle")} ${import_picocolors27.default.dim(args.schema)}
|
|
286103
286488
|
`);
|
|
286104
286489
|
let result;
|
|
286105
286490
|
try {
|
|
@@ -286107,26 +286492,26 @@ async function drizzlePull(argv) {
|
|
|
286107
286492
|
result = await buildSchemaSourceFromDrizzle({ mod, importPath: args.importPath });
|
|
286108
286493
|
} catch (err) {
|
|
286109
286494
|
const msg = err instanceof Error ? err.message : String(err);
|
|
286110
|
-
const hint = msg.includes("Cannot find package 'drizzle-orm'") ?
|
|
286111
|
-
console.error(
|
|
286495
|
+
const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors27.default.dim(` (install ${import_picocolors27.default.bold("drizzle-orm")} in this project)`) : "";
|
|
286496
|
+
console.error(import_picocolors27.default.red(` Couldn't load the schema: ${msg}`) + hint);
|
|
286112
286497
|
process.exit(1);
|
|
286113
286498
|
}
|
|
286114
286499
|
if (result.models.length === 0) {
|
|
286115
286500
|
console.error(
|
|
286116
|
-
|
|
286501
|
+
import_picocolors27.default.yellow(` No adoptable tables found`) + import_picocolors27.default.dim(` (a table needs an ${import_picocolors27.default.bold("id")} + ${import_picocolors27.default.bold("organization_id")} column).`)
|
|
286117
286502
|
);
|
|
286118
286503
|
process.exit(1);
|
|
286119
286504
|
}
|
|
286120
286505
|
(0, import_fs12.writeFileSync)(args.out, result.source);
|
|
286121
|
-
console.log(` ${
|
|
286122
|
-
console.log(` ${
|
|
286506
|
+
console.log(` ${import_picocolors27.default.green("\u2713")} wrote ${import_picocolors27.default.bold(args.out)} ${import_picocolors27.default.dim(`(${result.models.length} models)`)}`);
|
|
286507
|
+
console.log(` ${import_picocolors27.default.dim(`models: ${result.models.join(", ")}`)}`);
|
|
286123
286508
|
if (result.skipped.length > 0) {
|
|
286124
|
-
console.log(` ${
|
|
286125
|
-
for (const s of result.skipped) console.log(` ${
|
|
286509
|
+
console.log(` ${import_picocolors27.default.dim(`${result.skipped.length} table(s) skipped:`)}`);
|
|
286510
|
+
for (const s of result.skipped) console.log(` ${import_picocolors27.default.dim(`- ${s.name}: ${s.reason}`)}`);
|
|
286126
286511
|
}
|
|
286127
286512
|
console.log(
|
|
286128
286513
|
`
|
|
286129
|
-
${
|
|
286514
|
+
${import_picocolors27.default.dim("Enums and relations were preserved. Review the file, then")} ${import_picocolors27.default.bold("ablo check")}.
|
|
286130
286515
|
`
|
|
286131
286516
|
);
|
|
286132
286517
|
}
|
|
@@ -286212,7 +286597,7 @@ async function getCurrentUser(): Promise<{ id: string } | null> {
|
|
|
286212
286597
|
|
|
286213
286598
|
// src/index.ts
|
|
286214
286599
|
var LOGO = `
|
|
286215
|
-
${brand("ablo")} ${
|
|
286600
|
+
${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}
|
|
286216
286601
|
`;
|
|
286217
286602
|
var HANDLERS = {
|
|
286218
286603
|
init: (argv) => init([...argv]),
|
|
@@ -286221,6 +286606,7 @@ var HANDLERS = {
|
|
|
286221
286606
|
projects: (argv) => projects([...argv]),
|
|
286222
286607
|
branch: (argv) => branches([...argv]),
|
|
286223
286608
|
status: (argv) => status([...argv]),
|
|
286609
|
+
whoami: (argv) => whoami([...argv]),
|
|
286224
286610
|
doctor: () => doctor(),
|
|
286225
286611
|
logs: (argv) => logs([...argv]),
|
|
286226
286612
|
webhooks: (argv) => webhooks([...argv]),
|
|
@@ -286239,7 +286625,7 @@ async function runDev(argv) {
|
|
|
286239
286625
|
const devArgs = [...argv];
|
|
286240
286626
|
const oneShot = devArgs.includes("--no-watch");
|
|
286241
286627
|
console.log(
|
|
286242
|
-
|
|
286628
|
+
import_picocolors28.default.dim(
|
|
286243
286629
|
oneShot ? " `ablo dev --no-watch` prepares this Git branch and pushes once." : " `ablo dev` prepares this Git branch and watches the schema."
|
|
286244
286630
|
)
|
|
286245
286631
|
);
|
|
@@ -286253,31 +286639,11 @@ async function runPull(argv) {
|
|
|
286253
286639
|
}
|
|
286254
286640
|
async function runPush2(argv) {
|
|
286255
286641
|
const rest = [...argv];
|
|
286256
|
-
|
|
286257
|
-
(a) => ["--force", "--rename", "--backfill", "--url", "--dry-run", "--plan", "--yes", "-y", "--allow-dirty"].includes(a)
|
|
286258
|
-
);
|
|
286259
|
-
const watching = rest.includes("--watch");
|
|
286260
|
-
const guard = guardActiveProjectKey();
|
|
286261
|
-
if (!guard.ok && guard.available.length > 0 && !rest.includes("--url")) {
|
|
286262
|
-
console.error(
|
|
286263
|
-
` ${import_picocolors27.default.yellow("\u26A0")} active project ${import_picocolors27.default.bold(guard.activeProfile)} has no stored key ${import_picocolors27.default.dim(
|
|
286264
|
-
`(you have keys for: ${guard.available.join(", ")})`
|
|
286265
|
-
)}`
|
|
286266
|
-
);
|
|
286267
|
-
const loginCmd = guard.activeProfile === "default" ? "ablo login" : `ablo login --project ${guard.activeProfile}`;
|
|
286268
|
-
console.error(
|
|
286269
|
-
import_picocolors27.default.dim(` Mint one with ${import_picocolors27.default.bold(loginCmd)}, or switch with ${import_picocolors27.default.bold("ablo projects use <slug>")}.`)
|
|
286270
|
-
);
|
|
286271
|
-
process.exitCode = 1;
|
|
286272
|
-
return;
|
|
286273
|
-
}
|
|
286274
|
-
const plan = resolvePushPlan();
|
|
286275
|
-
if (advanced || plan.flow === "production" && !watching) await push(rest);
|
|
286276
|
-
else await dev(rest);
|
|
286642
|
+
await push(rest);
|
|
286277
286643
|
}
|
|
286278
286644
|
function runRenamedSchema(argv) {
|
|
286279
286645
|
const forwarded = argv.slice(1).join(" ");
|
|
286280
|
-
console.error(` ${
|
|
286646
|
+
console.error(` ${import_picocolors28.default.red("\u2717")} \`ablo schema push\` was renamed to \`${brand("ablo push")}\`.`);
|
|
286281
286647
|
console.error(` Run \`ablo push${forwarded ? " " + forwarded : ""}\` instead.`);
|
|
286282
286648
|
process.exitCode = 1;
|
|
286283
286649
|
}
|
|
@@ -286287,7 +286653,7 @@ async function main() {
|
|
|
286287
286653
|
const argv = process.argv.slice(3);
|
|
286288
286654
|
if (!command && raw !== void 0 && raw !== "help" && !raw.startsWith("-")) {
|
|
286289
286655
|
const suggestion = suggestCommand(raw);
|
|
286290
|
-
throw new
|
|
286656
|
+
throw new import_errors21.AbloValidationError(
|
|
286291
286657
|
`\`${raw}\` isn't an ablo command.` + (suggestion ? ` Did you mean \`ablo ${suggestion}\`?` : " Run `ablo help --all` to see every command."),
|
|
286292
286658
|
{ code: "cli_invalid_arguments" }
|
|
286293
286659
|
);
|
|
@@ -286318,7 +286684,7 @@ function printCoreHelp() {
|
|
|
286318
286684
|
const width = Math.max(...rows.map((r2) => r2.run.length)) + 4;
|
|
286319
286685
|
console.log(LOGO);
|
|
286320
286686
|
for (const group of CORE_GROUPS) {
|
|
286321
|
-
console.log(` ${
|
|
286687
|
+
console.log(` ${import_picocolors28.default.bold(group)}`);
|
|
286322
286688
|
const printed = group === "More" ? [...coreRows(group), ...extra] : coreRows(group);
|
|
286323
286689
|
for (const row of printed) console.log(` npx ablo ${row.run.padEnd(width)}${row.does}`);
|
|
286324
286690
|
console.log();
|
|
@@ -286327,7 +286693,7 @@ function printCoreHelp() {
|
|
|
286327
286693
|
}
|
|
286328
286694
|
function printSchemaReminder() {
|
|
286329
286695
|
console.log(
|
|
286330
|
-
|
|
286696
|
+
import_picocolors28.default.dim(` Edit ${import_picocolors28.default.bold("ablo/schema.ts")}, then push \u2014 writes to models you haven't pushed fail with `) + import_picocolors28.default.yellow("server_execute_unknown_model") + import_picocolors28.default.dim(".")
|
|
286331
286697
|
);
|
|
286332
286698
|
console.log();
|
|
286333
286699
|
}
|
|
@@ -286337,7 +286703,7 @@ function printFullHelp() {
|
|
|
286337
286703
|
) + 2;
|
|
286338
286704
|
console.log(LOGO);
|
|
286339
286705
|
for (const group of FULL_GROUPS) {
|
|
286340
|
-
console.log(` ${
|
|
286706
|
+
console.log(` ${import_picocolors28.default.bold(group)}`);
|
|
286341
286707
|
for (const row of fullRows(group)) {
|
|
286342
286708
|
console.log(row.does === void 0 ? ` ${" ".repeat(9)}${row.run}` : ` npx ablo ${row.run.padEnd(width)}${row.does}`);
|
|
286343
286709
|
}
|
|
@@ -286392,7 +286758,7 @@ async function ensureInitProject(opts) {
|
|
|
286392
286758
|
const ensured = await ensureProject(slug);
|
|
286393
286759
|
if (ensured) {
|
|
286394
286760
|
console.log(
|
|
286395
|
-
` ${
|
|
286761
|
+
` ${import_picocolors28.default.green("\u2713")} ${ensured.created ? "Created" : "Using"} project ${import_picocolors28.default.bold(ensured.slug)} ${import_picocolors28.default.dim(`(${ensured.id})`)} \u2014 keys you mint for it are isolated from the org's other apps.`
|
|
286396
286762
|
);
|
|
286397
286763
|
}
|
|
286398
286764
|
}
|
|
@@ -286434,7 +286800,7 @@ async function chooseBool(flagValue, fallback, interactive, prompt) {
|
|
|
286434
286800
|
async function init(args = []) {
|
|
286435
286801
|
const opts = parseInitArgs(args);
|
|
286436
286802
|
const interactive = Boolean(process.stdin.isTTY) && !opts.yes && !process.env.CI;
|
|
286437
|
-
Ie(`${brand("ablo")} ${
|
|
286803
|
+
Ie(`${brand("ablo")} ${import_picocolors28.default.dim("sync engine")}`);
|
|
286438
286804
|
if (!(0, import_fs13.existsSync)("package.json")) {
|
|
286439
286805
|
xe("No package.json found. Run this from your project root.");
|
|
286440
286806
|
process.exit(1);
|
|
@@ -286512,7 +286878,7 @@ async function init(args = []) {
|
|
|
286512
286878
|
if (pullExisting) {
|
|
286513
286879
|
const dbUrl = readProjectAdminDatabaseUrl();
|
|
286514
286880
|
if (!dbUrl) {
|
|
286515
|
-
schemaNote =
|
|
286881
|
+
schemaNote = import_picocolors28.default.dim(` (no ${ADMIN_URL_VAR} \u2014 wrote starter; run \`ablo pull\` later)`);
|
|
286516
286882
|
} else {
|
|
286517
286883
|
try {
|
|
286518
286884
|
const pulled = await buildSchemaSourceFromDb({
|
|
@@ -286522,12 +286888,12 @@ async function init(args = []) {
|
|
|
286522
286888
|
});
|
|
286523
286889
|
if (pulled.models.length > 0) {
|
|
286524
286890
|
schemaSource = pulled.source;
|
|
286525
|
-
schemaNote =
|
|
286891
|
+
schemaNote = import_picocolors28.default.dim(` (pulled ${pulled.models.length} models)`);
|
|
286526
286892
|
} else {
|
|
286527
|
-
schemaNote =
|
|
286893
|
+
schemaNote = import_picocolors28.default.dim(" (no adoptable tables \u2014 wrote starter)");
|
|
286528
286894
|
}
|
|
286529
286895
|
} catch {
|
|
286530
|
-
schemaNote =
|
|
286896
|
+
schemaNote = import_picocolors28.default.dim(" (pull failed \u2014 wrote starter)");
|
|
286531
286897
|
}
|
|
286532
286898
|
}
|
|
286533
286899
|
}
|
|
@@ -286551,9 +286917,9 @@ async function init(args = []) {
|
|
|
286551
286917
|
const existing = (0, import_fs13.readFileSync)(envFile, "utf-8");
|
|
286552
286918
|
if (!existing.includes("ABLO_")) {
|
|
286553
286919
|
(0, import_fs13.writeFileSync)(envFile, existing + "\n" + envBody);
|
|
286554
|
-
created.push(`${envFile} ${
|
|
286920
|
+
created.push(`${envFile} ${import_picocolors28.default.dim("(appended)")}`);
|
|
286555
286921
|
} else {
|
|
286556
|
-
created.push(`${envFile} ${
|
|
286922
|
+
created.push(`${envFile} ${import_picocolors28.default.dim("(already configured)")}`);
|
|
286557
286923
|
}
|
|
286558
286924
|
}
|
|
286559
286925
|
if (agent) {
|
|
@@ -286569,17 +286935,17 @@ async function init(args = []) {
|
|
|
286569
286935
|
}
|
|
286570
286936
|
const providersPath = (0, import_path8.join)(layout.appBase, "providers.tsx");
|
|
286571
286937
|
(0, import_fs13.writeFileSync)(providersPath, generateProviders());
|
|
286572
|
-
created.push(`${providersPath} ${
|
|
286938
|
+
created.push(`${providersPath} ${import_picocolors28.default.dim(`(wrap ${(0, import_path8.join)(layout.appBase, "layout.tsx")} in <Providers>)`)}`);
|
|
286573
286939
|
const sessionDir = (0, import_path8.join)(layout.appBase, "api", "ablo-session");
|
|
286574
286940
|
(0, import_fs13.mkdirSync)(sessionDir, { recursive: true });
|
|
286575
286941
|
(0, import_fs13.writeFileSync)((0, import_path8.join)(sessionDir, "route.ts"), generateSessionRoute());
|
|
286576
|
-
created.push(`${(0, import_path8.join)(sessionDir, "route.ts")} ${
|
|
286942
|
+
created.push(`${(0, import_path8.join)(sessionDir, "route.ts")} ${import_picocolors28.default.dim("(wire your auth)")}`);
|
|
286577
286943
|
}
|
|
286578
286944
|
if (framework !== "vanilla") {
|
|
286579
286945
|
(0, import_fs13.writeFileSync)((0, import_path8.join)(abloDir, "TaskList.tsx"), generateComponent());
|
|
286580
286946
|
created.push(`${abloDir}/TaskList.tsx`);
|
|
286581
286947
|
}
|
|
286582
|
-
Me(created.map((f) => `${
|
|
286948
|
+
Me(created.map((f) => `${import_picocolors28.default.green("\u2713")} ${f}`).join("\n"), "Created");
|
|
286583
286949
|
const pm = detectPackageManager();
|
|
286584
286950
|
if (opts.install) {
|
|
286585
286951
|
const s = Y2();
|
|
@@ -286588,46 +286954,46 @@ async function init(args = []) {
|
|
|
286588
286954
|
(0, import_child_process3.execSync)(`${pm} add @abloatai/ablo`, { stdio: "ignore" });
|
|
286589
286955
|
s.stop("Installed @abloatai/ablo");
|
|
286590
286956
|
} catch {
|
|
286591
|
-
s.stop(`${
|
|
286957
|
+
s.stop(`${import_picocolors28.default.yellow("!")} Couldn't auto-install \u2014 run ${import_picocolors28.default.bold(`${pm} install @abloatai/ablo`)}`);
|
|
286592
286958
|
}
|
|
286593
286959
|
}
|
|
286594
286960
|
const steps = [
|
|
286595
|
-
`Run ${
|
|
286596
|
-
`Set ${
|
|
286597
|
-
`Run ${
|
|
286961
|
+
`Run ${import_picocolors28.default.bold("npx ablo login")} to authorize branch management`,
|
|
286962
|
+
`Set ${import_picocolors28.default.bold("DATABASE_URL")} in ${import_picocolors28.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
|
|
286963
|
+
`Run ${import_picocolors28.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
|
|
286598
286964
|
...storage === "replication" ? [
|
|
286599
|
-
`Connect your database \u2014 ${
|
|
286600
|
-
`Verify it \u2014 ${
|
|
286601
|
-
`Register it \u2014 ${
|
|
286965
|
+
`Connect your database \u2014 ${import_picocolors28.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
|
|
286966
|
+
`Verify it \u2014 ${import_picocolors28.default.bold("npx ablo connect check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
|
|
286967
|
+
`Register it \u2014 ${import_picocolors28.default.bold("npx ablo connect register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
|
|
286602
286968
|
] : [
|
|
286603
|
-
`Provision your DB: ${
|
|
286969
|
+
`Provision your DB: ${import_picocolors28.default.bold("npx ablo migrate")} (creates your Ablo-model tables + the adapter tables; keep your own migrations for everything else), then mount ${import_picocolors28.default.bold(`${abloDir}/data-source.ts`)} at ${import_picocolors28.default.bold("/api/ablo/source")}`
|
|
286604
286970
|
],
|
|
286605
286971
|
...framework === "nextjs" ? [
|
|
286606
|
-
`Wrap ${
|
|
286972
|
+
`Wrap ${import_picocolors28.default.bold((0, import_path8.join)(layout.appBase, "layout.tsx"))} in ${import_picocolors28.default.bold("<Providers>")} (${(0, import_path8.join)(layout.appBase, "providers.tsx")}) and add your auth to ${import_picocolors28.default.bold((0, import_path8.join)(layout.appBase, "api", "ablo-session", "route.ts"))}`
|
|
286607
286973
|
] : [],
|
|
286608
|
-
`Run ${
|
|
286974
|
+
`Run ${import_picocolors28.default.bold(`${pm} run dev`)} and open two browser tabs \u2014 changes sync in real-time`,
|
|
286609
286975
|
...agent ? [
|
|
286610
|
-
`Run ${
|
|
286611
|
-
`Run ${
|
|
286976
|
+
`Run ${import_picocolors28.default.bold(`npx tsx ${abloDir}/agent.ts`)} \u2014 an AI teammate edits the same tasks`,
|
|
286977
|
+
`Run ${import_picocolors28.default.bold("npx ablo logs")} to watch human + agent commits stream by`
|
|
286612
286978
|
] : []
|
|
286613
286979
|
];
|
|
286614
286980
|
Me(steps.map((s, i) => `${i + 1}. ${s}`).join("\n"), "Next steps");
|
|
286615
286981
|
const existingKey = resolveManagementKey();
|
|
286616
286982
|
if (existingKey) {
|
|
286617
286983
|
await ensureInitProject(opts);
|
|
286618
|
-
Se(`Already authorized ${
|
|
286984
|
+
Se(`Already authorized ${import_picocolors28.default.dim(`(${existingKey.slice(0, 11)}\u2026)`)}. Run ${import_picocolors28.default.bold("npx ablo dev")} next. ${import_picocolors28.default.dim("Docs:")} https://abloatai.com/docs`);
|
|
286619
286985
|
return;
|
|
286620
286986
|
}
|
|
286621
286987
|
if (interactive && opts.login) {
|
|
286622
286988
|
const loginNow = await ye({ message: "Log in now? (opens your browser)", initialValue: true });
|
|
286623
286989
|
if (!pD(loginNow) && loginNow) {
|
|
286624
|
-
Se(`${
|
|
286990
|
+
Se(`${import_picocolors28.default.dim("Docs:")} https://abloatai.com/docs`);
|
|
286625
286991
|
await login();
|
|
286626
286992
|
await ensureInitProject(opts);
|
|
286627
286993
|
return;
|
|
286628
286994
|
}
|
|
286629
286995
|
}
|
|
286630
|
-
Se(`Run ${
|
|
286996
|
+
Se(`Run ${import_picocolors28.default.bold("npx ablo login")} when ready. ${import_picocolors28.default.dim("Docs:")} https://abloatai.com/docs`);
|
|
286631
286997
|
}
|
|
286632
286998
|
function generateSchema() {
|
|
286633
286999
|
return `import { defineSchema, model, relation, z } from '@abloatai/ablo/schema';
|
|
@@ -286702,7 +287068,7 @@ function generateEnv(storage, opts = {}) {
|
|
|
286702
287068
|
const { includeApiKey = true } = opts;
|
|
286703
287069
|
const databaseBlock = storage === "replication" ? "# Used by `npx ablo connect` to set up + register logical replication \u2014 the\n# DIRECT (un-pooled) endpoint. Ablo TAILS your WAL from here; it never writes.\n# The client never sees it; the browser never sees it. Your DB stays yours.\nDATABASE_URL=postgres://user:password@host:5432/db\n" : "# Used by ablo/data-source.ts (your DB endpoint) + `ablo migrate` \u2014 NOT the client.\n# Ablo never sees it; the browser never sees it. Your DB stays in your app.\nDATABASE_URL=postgres://user:password@host:5432/db\n";
|
|
286704
287070
|
const webhookBlock = storage === "endpoint" ? "# Signing secret for the webhook receiver (app/api/ablo/webhooks/route.ts).\n# Ablo mints this when you register the endpoint's URL (POST /v1/webhook_endpoints\n# or the dashboard) and returns it once \u2014 paste it here.\nABLO_WEBHOOK_SECRET=whsec_your_endpoint_secret_here\n" : "";
|
|
286705
|
-
const apiKeyBlock = includeApiKey ? "# Ablo: a
|
|
287071
|
+
const apiKeyBlock = includeApiKey ? "# Ablo: a branch-bound sk_ key (`npx ablo dev` wires a development branch for you)\nABLO_API_KEY=sk_your_key_here\n" : "";
|
|
286706
287072
|
return `${apiKeyBlock}${webhookBlock}${databaseBlock}`;
|
|
286707
287073
|
}
|
|
286708
287074
|
function generateDataSource(orm) {
|
|
@@ -286778,8 +287144,8 @@ var WEBHOOK_DOC = `/**
|
|
|
286778
287144
|
* signature, then write each change into YOUR database. The other half \u2014 your app
|
|
286779
287145
|
* MAKING changes + live sync \u2014 is the Ablo client in \`ablo/index.ts\`.
|
|
286780
287146
|
*
|
|
286781
|
-
*
|
|
286782
|
-
*
|
|
287147
|
+
* Your app calls Ablo to make changes, and Ablo calls this route to persist
|
|
287148
|
+
* them. Reliability is built in \u2014 Ablo retries on any
|
|
286783
287149
|
* non-2xx, and \`event.syncId\` is a monotonic log position, so apply in order and
|
|
286784
287150
|
* dedupe (skip a \`syncId\` you've already stored).
|
|
286785
287151
|
*/`;
|