@easybits.cloud/cli 0.17.0 → 0.18.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/README.md +23 -0
- package/dist/index.js +301 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,24 @@ easybits secrets set --dotenv .env.production # KEY=VALUE lines; - reads stdin
|
|
|
123
123
|
printf '%s' "$TOKEN" | easybits secrets set GITHUB_TOKEN # one value from stdin
|
|
124
124
|
easybits secrets rm GITHUB_TOKEN --yes
|
|
125
125
|
|
|
126
|
+
# Your crons: call a public https URL or message one of your agents (at most every 5 min)
|
|
127
|
+
easybits crons create "Study reminder" --cron "30 8 * * *" --url https://www.ghosty.studio/api/v2/me/push \
|
|
128
|
+
--method POST --body '{"title":"Study time"}' --secret GHOSTY_PUSH_TOKEN
|
|
129
|
+
easybits crons create "Weekly report" --cron "0 9 * * 1" --agent <agentId> --prompt "Send me the sales summary"
|
|
130
|
+
easybits crons ls
|
|
131
|
+
easybits crons update "Study reminder" --cron "0 7 * * 1-5"
|
|
132
|
+
easybits crons run "Study reminder" # id or exact name
|
|
133
|
+
easybits crons runs "Study reminder"
|
|
134
|
+
easybits crons pause "Study reminder"
|
|
135
|
+
easybits crons rm "Study reminder" --yes
|
|
136
|
+
|
|
137
|
+
# Platform crons (platform admins only; key with the ADMIN scope)
|
|
138
|
+
easybits crons ls --platform
|
|
139
|
+
easybits crons runs backup-machines
|
|
140
|
+
easybits crons run purge-notifications
|
|
141
|
+
easybits crons pause check-hosting
|
|
142
|
+
easybits crons resume check-hosting
|
|
143
|
+
|
|
126
144
|
# Databases
|
|
127
145
|
easybits db ls
|
|
128
146
|
easybits db create leads
|
|
@@ -275,6 +293,11 @@ Host *.ghosty
|
|
|
275
293
|
|
|
276
294
|
Full reference: https://www.easybits.cloud/docs#cli · https://www.easybits.cloud/en/docs/cli.md
|
|
277
295
|
|
|
296
|
+
## Changes in 0.17.1
|
|
297
|
+
|
|
298
|
+
- `easybits crons ls|runs|run|pause|resume`: EasyBits' scheduled jobs, the same as the
|
|
299
|
+
/dash/admin/crons panel (platform admins only; key with the ADMIN scope).
|
|
300
|
+
|
|
278
301
|
## Changes in 0.17.0
|
|
279
302
|
|
|
280
303
|
- `sites create --prompt … [--kind webapp|static] [--stack …] [--template …]` and
|
package/dist/index.js
CHANGED
|
@@ -305,7 +305,15 @@ var HEADERS_ES = {
|
|
|
305
305
|
SCENES: "ESCENAS",
|
|
306
306
|
DURATION: "DURACI\xD3N",
|
|
307
307
|
NARRATION: "NARRACI\xD3N",
|
|
308
|
-
PROMPT: "PROMPT"
|
|
308
|
+
PROMPT: "PROMPT",
|
|
309
|
+
JOB: "TAREA",
|
|
310
|
+
SCHEDULE: "HORARIO",
|
|
311
|
+
"LAST RUN": "\xDALTIMA",
|
|
312
|
+
"NEXT RUN": "PR\xD3XIMA",
|
|
313
|
+
RESULT: "RESULTADO",
|
|
314
|
+
TOOK: "TARD\xD3",
|
|
315
|
+
TRIGGER: "ORIGEN",
|
|
316
|
+
SUMMARY: "RESUMEN"
|
|
309
317
|
};
|
|
310
318
|
function table(rows, cols, empty = t("Nothing here yet.", "Todav\xEDa no hay nada.")) {
|
|
311
319
|
if (lang() === "es") cols = cols.map(([k, l]) => [k, HEADERS_ES[l] ?? l]);
|
|
@@ -4910,7 +4918,7 @@ async function updateNotice(current2) {
|
|
|
4910
4918
|
}
|
|
4911
4919
|
|
|
4912
4920
|
// src/commands/doctor.ts
|
|
4913
|
-
var VERSION = true ? "0.
|
|
4921
|
+
var VERSION = true ? "0.18.0" : "dev";
|
|
4914
4922
|
var doctor2 = {
|
|
4915
4923
|
name: "doctor",
|
|
4916
4924
|
group: "Account",
|
|
@@ -5416,6 +5424,272 @@ var secrets = {
|
|
|
5416
5424
|
defaultSub: "ls"
|
|
5417
5425
|
};
|
|
5418
5426
|
|
|
5427
|
+
// src/commands/crons.ts
|
|
5428
|
+
var HEX24 = /^[a-f0-9]{24}$/;
|
|
5429
|
+
var isUserCronId = (ref) => HEX24.test(ref);
|
|
5430
|
+
function describeCronAction(a) {
|
|
5431
|
+
if (a.type === "http") return `${a.method} ${a.url}${a.secretName ? ` (+${a.secretName})` : ""}`;
|
|
5432
|
+
return `agent ${a.fleetAgentId}: ${a.prompt.length > 40 ? a.prompt.slice(0, 39) + "\u2026" : a.prompt}`;
|
|
5433
|
+
}
|
|
5434
|
+
async function resolveUserCron(ctx, ref) {
|
|
5435
|
+
const { items } = await api(ctx, "GET", "/crons");
|
|
5436
|
+
const byId = items.find((c) => c.id === ref);
|
|
5437
|
+
if (byId) return byId;
|
|
5438
|
+
const byName = items.filter((c) => c.name.toLowerCase() === ref.trim().toLowerCase());
|
|
5439
|
+
if (byName.length > 1) {
|
|
5440
|
+
throw new CliError(t(`"${ref}" matches ${byName.length} crons. Use the id.`, `"${ref}" coincide con ${byName.length} crons. Usa el id.`), EXIT.USAGE);
|
|
5441
|
+
}
|
|
5442
|
+
return byName[0] ?? null;
|
|
5443
|
+
}
|
|
5444
|
+
async function userCronOrNull(ctx, ref) {
|
|
5445
|
+
if (isUserCronId(ref)) return await resolveUserCron(ctx, ref) ?? { id: ref };
|
|
5446
|
+
return resolveUserCron(ctx, ref);
|
|
5447
|
+
}
|
|
5448
|
+
var ACTION_OPTIONS = {
|
|
5449
|
+
url: { type: "string", value: "https-url", description: "Call this public https URL on each run" },
|
|
5450
|
+
method: { type: "string", value: "GET|POST|PUT|PATCH|DELETE", description: "HTTP method (default GET)" },
|
|
5451
|
+
body: { type: "string", value: "json|text", description: "Request body (not with GET)" },
|
|
5452
|
+
secret: { type: "string", value: "NAME", description: "Vault secret sent as a header (default Authorization: Bearer)" },
|
|
5453
|
+
"secret-header": { type: "string", value: "header", description: "Header for --secret" },
|
|
5454
|
+
agent: { type: "string", value: "id", description: "Send a turn to this fleet agent instead of calling a URL" },
|
|
5455
|
+
prompt: { type: "string", value: "text", description: "What the agent is told on each run (with --agent)" }
|
|
5456
|
+
};
|
|
5457
|
+
function actionFromFlags(f) {
|
|
5458
|
+
if (f.url && f.agent) return { error: "--url and --agent are exclusive" };
|
|
5459
|
+
if (f.url) {
|
|
5460
|
+
return {
|
|
5461
|
+
action: {
|
|
5462
|
+
type: "http",
|
|
5463
|
+
url: f.url,
|
|
5464
|
+
method: (f.method ?? "GET").toUpperCase(),
|
|
5465
|
+
...f.body ? { body: f.body } : {},
|
|
5466
|
+
...f.secret ? { secretName: f.secret, ...f.secretHeader ? { secretHeader: f.secretHeader } : {} } : {}
|
|
5467
|
+
}
|
|
5468
|
+
};
|
|
5469
|
+
}
|
|
5470
|
+
if (f.agent) {
|
|
5471
|
+
if (!f.prompt) return { error: "--agent needs --prompt" };
|
|
5472
|
+
return { action: { type: "agent_turn", fleetAgentId: f.agent, prompt: f.prompt } };
|
|
5473
|
+
}
|
|
5474
|
+
return {};
|
|
5475
|
+
}
|
|
5476
|
+
var flagsOf = (ctx) => ({
|
|
5477
|
+
url: str(ctx, "url"),
|
|
5478
|
+
method: str(ctx, "method"),
|
|
5479
|
+
body: str(ctx, "body"),
|
|
5480
|
+
secret: str(ctx, "secret"),
|
|
5481
|
+
secretHeader: str(ctx, "secret-header"),
|
|
5482
|
+
agent: str(ctx, "agent"),
|
|
5483
|
+
prompt: str(ctx, "prompt")
|
|
5484
|
+
});
|
|
5485
|
+
var STATUS = {
|
|
5486
|
+
"al-dia": ["up to date", "al d\xEDa"],
|
|
5487
|
+
tarde: ["late", "tarde"],
|
|
5488
|
+
fallo: ["failed", "fall\xF3"],
|
|
5489
|
+
pausado: ["paused", "pausado"],
|
|
5490
|
+
nuevo: ["no runs yet", "sin corridas"]
|
|
5491
|
+
};
|
|
5492
|
+
function cronStatus(c) {
|
|
5493
|
+
if (c.running) return t("running", "corriendo");
|
|
5494
|
+
const s = STATUS[c.status];
|
|
5495
|
+
return s ? t(s[0], s[1]) : c.status;
|
|
5496
|
+
}
|
|
5497
|
+
function duration(ms) {
|
|
5498
|
+
if (ms == null) return "\u2014";
|
|
5499
|
+
return ms < 1e3 ? `${ms} ms` : `${(ms / 1e3).toFixed(1)} s`;
|
|
5500
|
+
}
|
|
5501
|
+
var crons = {
|
|
5502
|
+
name: "crons",
|
|
5503
|
+
aliases: ["cron"],
|
|
5504
|
+
group: "Account",
|
|
5505
|
+
summary: "Your scheduled jobs (call a URL or message an agent) and, for admins, the platform's",
|
|
5506
|
+
synopsis: "crons <ls|create|update|rm|run|runs|pause|resume>",
|
|
5507
|
+
subs: {
|
|
5508
|
+
ls: {
|
|
5509
|
+
aliases: ["list"],
|
|
5510
|
+
summary: "List your crons (or, with --platform, the platform's scheduled jobs)",
|
|
5511
|
+
usage: "easybits crons ls [--platform]",
|
|
5512
|
+
options: { platform: { type: "boolean", description: "Platform jobs (backups, purges\u2026; platform admins only)" } },
|
|
5513
|
+
examples: ["easybits crons ls", "easybits crons ls --json", "easybits crons ls --platform"],
|
|
5514
|
+
async run(ctx) {
|
|
5515
|
+
if (!bool(ctx, "platform")) {
|
|
5516
|
+
const { items: items2 } = await api(ctx, "GET", "/crons");
|
|
5517
|
+
emit(
|
|
5518
|
+
ctx,
|
|
5519
|
+
{ items: items2 },
|
|
5520
|
+
() => table(
|
|
5521
|
+
items2.map((c) => ({
|
|
5522
|
+
id: c.id,
|
|
5523
|
+
name: c.name,
|
|
5524
|
+
schedule: c.enabled ? c.schedule : `${c.schedule} (${t("paused", "en pausa")})`,
|
|
5525
|
+
does: describeCronAction(c.action),
|
|
5526
|
+
last: c.lastRunAt ? `${fmtDate(c.lastRunAt)} ${c.lastOk === false ? t("failed", "fall\xF3") : "ok"}` : "\u2014",
|
|
5527
|
+
next: c.enabled ? fmtDate(c.nextRunAt) : "\u2014"
|
|
5528
|
+
})),
|
|
5529
|
+
[["id", "ID"], ["name", "NAME"], ["schedule", "SCHEDULE"], ["does", "DOES"], ["last", "LAST RUN"], ["next", "NEXT RUN"]],
|
|
5530
|
+
t(
|
|
5531
|
+
'No crons. Create one: easybits crons create "Ping" --cron "*/15 * * * *" --url https://example.com/ping',
|
|
5532
|
+
'Sin crons. Crea uno: easybits crons create "Ping" --cron "*/15 * * * *" --url https://ejemplo.com/ping'
|
|
5533
|
+
)
|
|
5534
|
+
)
|
|
5535
|
+
);
|
|
5536
|
+
return;
|
|
5537
|
+
}
|
|
5538
|
+
const { items } = await api(ctx, "GET", "/admin/crons");
|
|
5539
|
+
emit(
|
|
5540
|
+
ctx,
|
|
5541
|
+
{ items },
|
|
5542
|
+
() => table(
|
|
5543
|
+
items.map((c) => ({
|
|
5544
|
+
key: c.key,
|
|
5545
|
+
status: cronStatus(c),
|
|
5546
|
+
schedule: c.schedule,
|
|
5547
|
+
last: c.lastRun ? `${fmtDate(c.lastRun.startedAt)} (${duration(c.lastRun.durationMs)})` : "\u2014",
|
|
5548
|
+
next: c.paused ? "\u2014" : fmtDate(c.nextRunAt)
|
|
5549
|
+
})),
|
|
5550
|
+
[["key", "JOB"], ["status", "STATUS"], ["schedule", "SCHEDULE"], ["last", "LAST RUN"], ["next", "NEXT RUN"]]
|
|
5551
|
+
)
|
|
5552
|
+
);
|
|
5553
|
+
}
|
|
5554
|
+
},
|
|
5555
|
+
runs: {
|
|
5556
|
+
summary: "Show the last runs of one of your crons (id or name) or of a platform job, with the full error",
|
|
5557
|
+
usage: "easybits crons runs <id|name|job>",
|
|
5558
|
+
examples: ["easybits crons runs 66f0c2a1b2c3d4e5f6a7b8c9", "easybits crons runs backup-machines --json"],
|
|
5559
|
+
async run(ctx) {
|
|
5560
|
+
const key = need(ctx, 0, "id|name|job", this.usage);
|
|
5561
|
+
const mine = await userCronOrNull(ctx, key);
|
|
5562
|
+
const path = mine ? `/crons/${mine.id}/runs?limit=50` : `/admin/crons/${encodeURIComponent(key)}/runs`;
|
|
5563
|
+
const { items } = await api(ctx, "GET", path);
|
|
5564
|
+
emit(ctx, { items }, () => {
|
|
5565
|
+
table(
|
|
5566
|
+
items.map((r) => ({
|
|
5567
|
+
at: fmtDate(r.startedAt),
|
|
5568
|
+
ok: r.ok == null ? t("running", "corriendo") : r.ok ? "ok" : t("failed", "fall\xF3"),
|
|
5569
|
+
status: r.status ?? "\u2014",
|
|
5570
|
+
took: duration(r.durationMs),
|
|
5571
|
+
trigger: r.trigger,
|
|
5572
|
+
summary: (r.error ?? r.summary ?? "").slice(0, 80)
|
|
5573
|
+
})),
|
|
5574
|
+
[["at", "STARTED"], ["ok", "RESULT"], ["status", "HTTP"], ["took", "TOOK"], ["trigger", "TRIGGER"], ["summary", "SUMMARY"]],
|
|
5575
|
+
t("No runs yet.", "Todav\xEDa no hay corridas.")
|
|
5576
|
+
);
|
|
5577
|
+
const failed = items.find((r) => r.ok === false && r.error);
|
|
5578
|
+
if (failed) console.log(`
|
|
5579
|
+
${t("Last error", "\xDAltimo error")} (${fmtDate(failed.startedAt)}):
|
|
5580
|
+
${failed.error}`);
|
|
5581
|
+
});
|
|
5582
|
+
}
|
|
5583
|
+
},
|
|
5584
|
+
run: {
|
|
5585
|
+
summary: "Run one of your crons or a platform job now, in the background (trigger manual)",
|
|
5586
|
+
usage: "easybits crons run <id|name|job>",
|
|
5587
|
+
examples: ["easybits crons run 66f0c2a1b2c3d4e5f6a7b8c9", "easybits crons run purge-notifications --json"],
|
|
5588
|
+
async run(ctx) {
|
|
5589
|
+
const key = need(ctx, 0, "id|name|job", this.usage);
|
|
5590
|
+
const mine = await userCronOrNull(ctx, key);
|
|
5591
|
+
const r = await api(ctx, "POST", mine ? `/crons/${mine.id}/run` : `/admin/crons/${encodeURIComponent(key)}/run`);
|
|
5592
|
+
emit(
|
|
5593
|
+
ctx,
|
|
5594
|
+
r,
|
|
5595
|
+
() => console.log(t(`Started ${key}. Follow it with: easybits crons runs ${key}`, `Arranc\xF3 ${key}. S\xEDguela con: easybits crons runs ${key}`))
|
|
5596
|
+
);
|
|
5597
|
+
}
|
|
5598
|
+
},
|
|
5599
|
+
pause: {
|
|
5600
|
+
summary: "Pause one of your crons or a platform job until you resume it",
|
|
5601
|
+
usage: "easybits crons pause <id|name|job>",
|
|
5602
|
+
examples: ["easybits crons pause 66f0c2a1b2c3d4e5f6a7b8c9", "easybits crons pause check-hosting"],
|
|
5603
|
+
async run(ctx) {
|
|
5604
|
+
const key = need(ctx, 0, "id|name|job", this.usage);
|
|
5605
|
+
const mine = await userCronOrNull(ctx, key);
|
|
5606
|
+
const r = mine ? await api(ctx, "PATCH", `/crons/${mine.id}`, { enabled: false }) : await api(ctx, "POST", `/admin/crons/${encodeURIComponent(key)}/pause`, { paused: true });
|
|
5607
|
+
emit(ctx, r, () => console.log(t(`Paused ${key}.`, `${key} en pausa.`)));
|
|
5608
|
+
}
|
|
5609
|
+
},
|
|
5610
|
+
resume: {
|
|
5611
|
+
summary: "Resume one of your crons or a platform job",
|
|
5612
|
+
usage: "easybits crons resume <id|name|job>",
|
|
5613
|
+
examples: ["easybits crons resume 66f0c2a1b2c3d4e5f6a7b8c9", "easybits crons resume check-hosting"],
|
|
5614
|
+
async run(ctx) {
|
|
5615
|
+
const key = need(ctx, 0, "id|name|job", this.usage);
|
|
5616
|
+
const mine = await userCronOrNull(ctx, key);
|
|
5617
|
+
const r = mine ? await api(ctx, "PATCH", `/crons/${mine.id}`, { enabled: true }) : await api(ctx, "POST", `/admin/crons/${encodeURIComponent(key)}/pause`, { paused: false });
|
|
5618
|
+
emit(ctx, r, () => console.log(t(`Resumed ${key}.`, `${key} reanudada.`)));
|
|
5619
|
+
}
|
|
5620
|
+
},
|
|
5621
|
+
create: {
|
|
5622
|
+
aliases: ["add"],
|
|
5623
|
+
summary: "Create a cron: call a public https URL or send a turn to one of your agents (at most every 5 min)",
|
|
5624
|
+
usage: 'easybits crons create <name> --cron "<5 fields>" [--tz <IANA>] (--url <https-url> [--method] [--body] [--secret NAME] | --agent <id> --prompt <text>)',
|
|
5625
|
+
options: {
|
|
5626
|
+
cron: { type: "string", value: "expr", description: 'Cron of 5 fields, e.g. "30 8 * * *" = daily 8:30' },
|
|
5627
|
+
tz: { type: "string", value: "zone", description: "IANA time zone (default America/Mexico_City)" },
|
|
5628
|
+
...ACTION_OPTIONS
|
|
5629
|
+
},
|
|
5630
|
+
examples: [
|
|
5631
|
+
`easybits crons create "Study reminder" --cron "30 8 * * *" --url https://www.ghosty.studio/api/v2/me/push --method POST --body '{"title":"Study time"}' --secret GHOSTY_PUSH_TOKEN`,
|
|
5632
|
+
'easybits crons create "Weekly report" --cron "0 9 * * 1" --agent 6a3c046d2cf7d7f4163f739d --prompt "Send me the weekly sales summary"'
|
|
5633
|
+
],
|
|
5634
|
+
async run(ctx) {
|
|
5635
|
+
const name = need(ctx, 0, "name", this.usage);
|
|
5636
|
+
const cron = str(ctx, "cron");
|
|
5637
|
+
if (!cron) throw usageError(t("Missing --cron.", "Falta --cron."), this.usage);
|
|
5638
|
+
const a = actionFromFlags(flagsOf(ctx));
|
|
5639
|
+
if ("error" in a) throw usageError(a.error, this.usage);
|
|
5640
|
+
if (!a.action) throw usageError(t("Missing --url or --agent.", "Falta --url o --agent."), this.usage);
|
|
5641
|
+
const c = await api(ctx, "POST", "/crons", { name, cron, ...str(ctx, "tz") ? { timezone: str(ctx, "tz") } : {}, action: a.action });
|
|
5642
|
+
emit(ctx, c, () => console.log(t(`Created ${c.id} \xAB${c.name}\xBB \u2014 ${c.schedule}; next ${fmtDate(c.nextRunAt)}`, `Creado ${c.id} \xAB${c.name}\xBB \u2014 ${c.schedule}; pr\xF3xima ${fmtDate(c.nextRunAt)}`)));
|
|
5643
|
+
}
|
|
5644
|
+
},
|
|
5645
|
+
update: {
|
|
5646
|
+
aliases: ["edit", "set"],
|
|
5647
|
+
summary: "Change one of your crons (only what you pass)",
|
|
5648
|
+
usage: 'easybits crons update <id|name> [--name <n>] [--cron "<expr>"] [--tz <IANA>] [--url \u2026 | --agent \u2026 --prompt \u2026]',
|
|
5649
|
+
options: {
|
|
5650
|
+
name: { type: "string", value: "name", description: "New name" },
|
|
5651
|
+
cron: { type: "string", value: "expr", description: "New schedule" },
|
|
5652
|
+
tz: { type: "string", value: "zone", description: "New IANA time zone" },
|
|
5653
|
+
...ACTION_OPTIONS
|
|
5654
|
+
},
|
|
5655
|
+
examples: ['easybits crons update 66f0c2a1b2c3d4e5f6a7b8c9 --cron "0 7 * * 1-5"'],
|
|
5656
|
+
async run(ctx) {
|
|
5657
|
+
const ref = need(ctx, 0, "id|name", this.usage);
|
|
5658
|
+
const mine = await resolveUserCron(ctx, ref);
|
|
5659
|
+
if (!mine) throw new CliError(t(`You have no cron "${ref}".`, `No tienes un cron "${ref}".`), EXIT.API, "easybits crons ls", "not_found", 404);
|
|
5660
|
+
const a = actionFromFlags(flagsOf(ctx));
|
|
5661
|
+
if ("error" in a) throw usageError(a.error, this.usage);
|
|
5662
|
+
const patch = {
|
|
5663
|
+
...str(ctx, "name") ? { name: str(ctx, "name") } : {},
|
|
5664
|
+
...str(ctx, "cron") ? { cron: str(ctx, "cron") } : {},
|
|
5665
|
+
...str(ctx, "tz") ? { timezone: str(ctx, "tz") } : {},
|
|
5666
|
+
...a.action ? { action: a.action } : {}
|
|
5667
|
+
};
|
|
5668
|
+
if (!Object.keys(patch).length) throw usageError(t("Nothing to change.", "No hay nada que cambiar."), this.usage);
|
|
5669
|
+
const c = await api(ctx, "PATCH", `/crons/${mine.id}`, patch);
|
|
5670
|
+
emit(ctx, c, () => console.log(t(`Updated \xAB${c.name}\xBB \u2014 ${c.schedule}`, `Actualizado \xAB${c.name}\xBB \u2014 ${c.schedule}`)));
|
|
5671
|
+
}
|
|
5672
|
+
},
|
|
5673
|
+
rm: {
|
|
5674
|
+
aliases: ["remove", "delete"],
|
|
5675
|
+
summary: "Delete one of your crons",
|
|
5676
|
+
usage: "easybits crons rm <id|name> [--yes]",
|
|
5677
|
+
options: { ...YES_OPTION },
|
|
5678
|
+
examples: ["easybits crons rm 66f0c2a1b2c3d4e5f6a7b8c9 --yes"],
|
|
5679
|
+
async run(ctx) {
|
|
5680
|
+
const ref = need(ctx, 0, "id|name", this.usage);
|
|
5681
|
+
const mine = await resolveUserCron(ctx, ref);
|
|
5682
|
+
if (!mine) throw new CliError(t(`You have no cron "${ref}".`, `No tienes un cron "${ref}".`), EXIT.API, "easybits crons ls", "not_found", 404);
|
|
5683
|
+
requireYesIfHeadless(ctx);
|
|
5684
|
+
await confirm(ctx, t(`Delete cron \xAB${mine.name}\xBB? It stops running right away.`, `\xBFBorrar el cron \xAB${mine.name}\xBB? Deja de correr de inmediato.`));
|
|
5685
|
+
const r = await api(ctx, "DELETE", `/crons/${mine.id}`);
|
|
5686
|
+
emit(ctx, r, () => console.log(t(`Deleted \xAB${mine.name}\xBB`, `Borrado \xAB${mine.name}\xBB`)));
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
},
|
|
5690
|
+
defaultSub: "ls"
|
|
5691
|
+
};
|
|
5692
|
+
|
|
5419
5693
|
// src/commands/documents.ts
|
|
5420
5694
|
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync18, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
5421
5695
|
import { join as join11 } from "path";
|
|
@@ -6203,6 +6477,7 @@ var COMMANDS = [
|
|
|
6203
6477
|
doctor2,
|
|
6204
6478
|
usage,
|
|
6205
6479
|
secrets,
|
|
6480
|
+
crons,
|
|
6206
6481
|
sandboxes,
|
|
6207
6482
|
agents,
|
|
6208
6483
|
fleet,
|
|
@@ -6543,6 +6818,29 @@ var HELP_ES = {
|
|
|
6543
6818
|
"Path kept out of the release (repeatable)": "Ruta que no entra al release (repetible)",
|
|
6544
6819
|
"Release a machine: stops billing, takes a last backup and destroys it": "Libera una m\xE1quina: deja de cobrarse, toma un \xFAltimo respaldo y la destruye",
|
|
6545
6820
|
"The hosting catalog: sizes and monthly prices in MXN": "El cat\xE1logo de hosting: tama\xF1os y precio mensual en MXN",
|
|
6821
|
+
// crons (tuyos y de la plataforma)
|
|
6822
|
+
"Your scheduled jobs (call a URL or message an agent) and, for admins, the platform's": "Tus tareas programadas (pegarle a una URL o escribirle a un agente) y, para admins, las de la plataforma",
|
|
6823
|
+
"List your crons (or, with --platform, the platform's scheduled jobs)": "Enlista tus crons (o, con --platform, las tareas de la plataforma)",
|
|
6824
|
+
"Platform jobs (backups, purges\u2026; platform admins only)": "Tareas de la plataforma (respaldos, purgas\u2026; s\xF3lo admins)",
|
|
6825
|
+
"Show the last runs of one of your crons (id or name) or of a platform job, with the full error": "Muestra las \xFAltimas corridas de un cron tuyo (id o nombre) o de una tarea de la plataforma, con el error completo",
|
|
6826
|
+
"Run one of your crons or a platform job now, in the background (trigger manual)": "Corre ya un cron tuyo o una tarea de la plataforma, en segundo plano (manual)",
|
|
6827
|
+
"Pause one of your crons or a platform job until you resume it": "Pausa un cron tuyo o una tarea de la plataforma hasta que lo reanudes",
|
|
6828
|
+
"Resume one of your crons or a platform job": "Reanuda un cron tuyo o una tarea de la plataforma",
|
|
6829
|
+
"Create a cron: call a public https URL or send a turn to one of your agents (at most every 5 min)": "Crea un cron: pegarle a una URL https p\xFAblica o mandarle un turno a uno de tus agentes (como mucho cada 5 min)",
|
|
6830
|
+
'Cron of 5 fields, e.g. "30 8 * * *" = daily 8:30': 'Cron de 5 campos, p. ej. "30 8 * * *" = diario 8:30',
|
|
6831
|
+
"IANA time zone (default America/Mexico_City)": "Zona horaria IANA (default America/Mexico_City)",
|
|
6832
|
+
"Call this public https URL on each run": "Pegarle a esta URL https p\xFAblica en cada corrida",
|
|
6833
|
+
"HTTP method (default GET)": "M\xE9todo HTTP (default GET)",
|
|
6834
|
+
"Request body (not with GET)": "Cuerpo de la petici\xF3n (no con GET)",
|
|
6835
|
+
"Vault secret sent as a header (default Authorization: Bearer)": "Secreto de la b\xF3veda que viaja como header (default Authorization: Bearer)",
|
|
6836
|
+
"Header for --secret": "Header para --secret",
|
|
6837
|
+
"Send a turn to this fleet agent instead of calling a URL": "Mandarle un turno a este agente de la flota en vez de pegarle a una URL",
|
|
6838
|
+
"What the agent is told on each run (with --agent)": "Lo que se le dice al agente en cada corrida (con --agent)",
|
|
6839
|
+
"Change one of your crons (only what you pass)": "Cambia un cron tuyo (s\xF3lo lo que pases)",
|
|
6840
|
+
"New name": "Nombre nuevo",
|
|
6841
|
+
"New schedule": "Horario nuevo",
|
|
6842
|
+
"New IANA time zone": "Zona horaria IANA nueva",
|
|
6843
|
+
"Delete one of your crons": "Borra un cron tuyo",
|
|
6546
6844
|
// secrets (vault de la cuenta)
|
|
6547
6845
|
"Your account's secrets vault: names only; used as $secret:NAME": "La b\xF3veda de secretos de tu cuenta: s\xF3lo nombres; se usan como $secret:NOMBRE",
|
|
6548
6846
|
"List the names in your vault (values never come back)": "Enlista los nombres de tu b\xF3veda (los valores nunca regresan)",
|
|
@@ -6857,7 +7155,7 @@ function normalizeArgs(input) {
|
|
|
6857
7155
|
}
|
|
6858
7156
|
|
|
6859
7157
|
// src/index.ts
|
|
6860
|
-
var VERSION2 = true ? "0.
|
|
7158
|
+
var VERSION2 = true ? "0.18.0" : "dev";
|
|
6861
7159
|
var GLOBAL_OPTIONS = {
|
|
6862
7160
|
json: { type: "boolean" },
|
|
6863
7161
|
token: { type: "string" },
|
package/package.json
CHANGED