@kryd/cli 0.14.0 → 0.15.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 +8 -0
- package/dist/index.js +198 -32
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Once you've run `kryd init` in a directory, the commands below work **arg-less**
|
|
|
43
43
|
| `kryd ai add \| remove \| status [project]` | Give the project an authenticated EU AI-gateway endpoint (injected on the next deploy), take it away again, or show what it has. |
|
|
44
44
|
| `kryd workflow add \| remove \| status [project]` | Give the project its own durable-workflow tenant — `HATCHET_CLIENT_TOKEN` is injected on the next deploy — revoke that token again, or show whether it has one and when it expires. `remove` keeps the tenant's history, crons and schedules until the project is deleted. |
|
|
45
45
|
| `kryd workflow init --language <typescript\|python\|go>` | Scaffold a workflow worker here and link it as a new project. The worker ships with the small HTTP health listener Kryd's deploy gate needs — without it a deploy is torn down with "nothing listening yet" — plus a `kryd.json` that tells `kryd init` what this project is. `--no-link` writes the files only. |
|
|
46
|
+
| `kryd token create \| list \| revoke` | Deploy tokens for CI and scripts. `create <name> [--expires 30\|90\|365\|never]` (default 90 days) prints the token once; it acts as you, inside your account, and cannot create tokens itself. Managing tokens needs `kryd login`. A token can do what you can on your projects — read env values and push — so after a leak, revoke it and also rotate the secrets it could read. |
|
|
46
47
|
| `kryd support new \| list \| show \| reply` | Ask Kryd support a question, report a bug or a wish, and read the answer. Non-interactive (every input is a flag) and `--json` prints one JSON document on stdout — so an agent can use it too. In a linked folder, `new` adds the project and its last production deploy; when that deploy failed, the last lines of its log are sent to Kryd support too, with secret-looking values masked. `--no-context` leaves all of it out. |
|
|
47
48
|
|
|
48
49
|
For an agent, for example:
|
|
@@ -52,6 +53,13 @@ kryd support new --type bug --subject "Deploy hangs on build" --message "Every d
|
|
|
52
53
|
kryd support show T-1042 --json
|
|
53
54
|
```
|
|
54
55
|
|
|
56
|
+
In CI, no `kryd login` and no config file: set a deploy token as the secret `KRYD_TOKEN` and every command uses it (it wins over a stored login).
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
kryd token create github-actions # prints kryd_… once — store it as the CI secret KRYD_TOKEN
|
|
60
|
+
KRYD_TOKEN=kryd_… kryd deploy <project>
|
|
61
|
+
```
|
|
62
|
+
|
|
55
63
|
Run `kryd <command> --help` for options. Every project-scoped command accepts an explicit `<project>` id, or resolves it from the `.kryd` link (walking up from the current directory, git-style).
|
|
56
64
|
|
|
57
65
|
## Sovereignty
|
package/dist/index.js
CHANGED
|
@@ -15931,6 +15931,10 @@ function loadConfig() {
|
|
|
15931
15931
|
return {};
|
|
15932
15932
|
}
|
|
15933
15933
|
}
|
|
15934
|
+
function resolveToken() {
|
|
15935
|
+
const fromEnv = process.env.KRYD_TOKEN?.trim();
|
|
15936
|
+
return fromEnv ? fromEnv : loadConfig().token;
|
|
15937
|
+
}
|
|
15934
15938
|
function writeConfig(config2) {
|
|
15935
15939
|
const path = configPath();
|
|
15936
15940
|
mkdirSync(dirname(path), { recursive: true, mode: 448 });
|
|
@@ -16156,7 +16160,7 @@ function reportSupportError(err) {
|
|
|
16156
16160
|
process.exitCode = 1;
|
|
16157
16161
|
}
|
|
16158
16162
|
function requireToken() {
|
|
16159
|
-
const token =
|
|
16163
|
+
const token = resolveToken();
|
|
16160
16164
|
if (!token) usage("Not logged in \u2014 run `kryd login` first.");
|
|
16161
16165
|
return token ?? null;
|
|
16162
16166
|
}
|
|
@@ -16308,6 +16312,154 @@ async function runSupportReply(raw, opts) {
|
|
|
16308
16312
|
}
|
|
16309
16313
|
}
|
|
16310
16314
|
|
|
16315
|
+
// src/tokens.ts
|
|
16316
|
+
var TOKEN_EXPIRY_CHOICES = ["30", "90", "365", "never"];
|
|
16317
|
+
var DEFAULT_TOKEN_EXPIRY = "90";
|
|
16318
|
+
var MAX_TOKEN_NAME = 32;
|
|
16319
|
+
function expiresInSeconds(choice) {
|
|
16320
|
+
if (choice === "never") return null;
|
|
16321
|
+
if (!TOKEN_EXPIRY_CHOICES.includes(choice)) return void 0;
|
|
16322
|
+
return Number(choice) * 24 * 60 * 60;
|
|
16323
|
+
}
|
|
16324
|
+
async function tokenFetch(apiUrl, token, path, what, body) {
|
|
16325
|
+
const res = await fetch(`${apiUrl}/api/auth/api-key/${path}`, {
|
|
16326
|
+
method: body === void 0 ? "GET" : "POST",
|
|
16327
|
+
headers: {
|
|
16328
|
+
authorization: `Bearer ${token}`,
|
|
16329
|
+
...body !== void 0 ? { "content-type": "application/json" } : {}
|
|
16330
|
+
},
|
|
16331
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
16332
|
+
});
|
|
16333
|
+
if (!res.ok) {
|
|
16334
|
+
const parsed = await res.json().catch(() => void 0);
|
|
16335
|
+
const message = typeof parsed?.message === "string" ? parsed.message : `${what} failed (${res.status})`;
|
|
16336
|
+
const code = typeof parsed?.code === "string" ? parsed.code : `http.${res.status}`;
|
|
16337
|
+
throw new ApiError(`${what} failed (${res.status})`, { error: { code, message } }, res.status);
|
|
16338
|
+
}
|
|
16339
|
+
try {
|
|
16340
|
+
return await res.json();
|
|
16341
|
+
} catch {
|
|
16342
|
+
throw new ApiError(`The API returned an unexpected answer to "${what.toLowerCase()}".`);
|
|
16343
|
+
}
|
|
16344
|
+
}
|
|
16345
|
+
var isToken = (v) => {
|
|
16346
|
+
const t = v;
|
|
16347
|
+
return typeof t?.id === "string" && typeof t?.createdAt === "string";
|
|
16348
|
+
};
|
|
16349
|
+
async function createDeployToken(apiUrl, token, input) {
|
|
16350
|
+
const body = await tokenFetch(apiUrl, token, "create", "Creating the token", input);
|
|
16351
|
+
if (!isToken(body) || typeof body.key !== "string" || body.key.length === 0) {
|
|
16352
|
+
throw new ApiError("The API returned an unexpected answer to creating the token.");
|
|
16353
|
+
}
|
|
16354
|
+
return body;
|
|
16355
|
+
}
|
|
16356
|
+
async function listDeployTokens(apiUrl, token) {
|
|
16357
|
+
const body = await tokenFetch(apiUrl, token, "list", "Listing the tokens");
|
|
16358
|
+
if (!Array.isArray(body?.apiKeys) || !body.apiKeys.every(isToken)) {
|
|
16359
|
+
throw new ApiError("The API returned an unexpected answer to listing the tokens.");
|
|
16360
|
+
}
|
|
16361
|
+
return body.apiKeys;
|
|
16362
|
+
}
|
|
16363
|
+
async function revokeDeployToken(apiUrl, token, id) {
|
|
16364
|
+
await tokenFetch(apiUrl, token, "delete", "Revoking the token", { keyId: id });
|
|
16365
|
+
}
|
|
16366
|
+
function fail(message) {
|
|
16367
|
+
process.stderr.write(`${message}
|
|
16368
|
+
`);
|
|
16369
|
+
process.exitCode = 1;
|
|
16370
|
+
}
|
|
16371
|
+
function reportTokenError(err) {
|
|
16372
|
+
if (err instanceof ApiError && err.status === 401) {
|
|
16373
|
+
fail("Not logged in, or the session expired \u2014 run `kryd login`.");
|
|
16374
|
+
} else if (err instanceof ApiError && err.status === 403 && resolveToken()?.startsWith("kryd_")) {
|
|
16375
|
+
fail(
|
|
16376
|
+
"A deploy token cannot manage tokens. Sign in with `kryd login` (and unset KRYD_TOKEN for this command)."
|
|
16377
|
+
);
|
|
16378
|
+
} else if (err instanceof ApiError && err.status === 404) {
|
|
16379
|
+
fail("No such token on your account. `kryd token list` shows their ids.");
|
|
16380
|
+
} else if (err instanceof ApiError && err.envelope) {
|
|
16381
|
+
fail(err.envelope.error.message);
|
|
16382
|
+
} else {
|
|
16383
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
16384
|
+
}
|
|
16385
|
+
}
|
|
16386
|
+
function requireToken2() {
|
|
16387
|
+
const token = resolveToken();
|
|
16388
|
+
if (!token) fail("Not logged in \u2014 run `kryd login` first.");
|
|
16389
|
+
return token ?? null;
|
|
16390
|
+
}
|
|
16391
|
+
var day = (iso) => iso ? iso.slice(0, 10) : "\u2014";
|
|
16392
|
+
async function runTokenCreate(name, opts) {
|
|
16393
|
+
const trimmed = name.trim();
|
|
16394
|
+
if (trimmed.length === 0 || trimmed.length > MAX_TOKEN_NAME) {
|
|
16395
|
+
return fail(`A token name is 1 to ${MAX_TOKEN_NAME} characters.`);
|
|
16396
|
+
}
|
|
16397
|
+
const choice = opts.expires ?? DEFAULT_TOKEN_EXPIRY;
|
|
16398
|
+
const expiresIn = expiresInSeconds(choice);
|
|
16399
|
+
if (expiresIn === void 0) {
|
|
16400
|
+
return fail(`--expires is one of ${TOKEN_EXPIRY_CHOICES.join(", ")} (days, or never).`);
|
|
16401
|
+
}
|
|
16402
|
+
const token = requireToken2();
|
|
16403
|
+
if (!token) return;
|
|
16404
|
+
try {
|
|
16405
|
+
const created = await createDeployToken(resolveApiUrl(opts.apiUrl), token, { name: trimmed, expiresIn });
|
|
16406
|
+
process.stdout.write(`${created.key}
|
|
16407
|
+
`);
|
|
16408
|
+
process.stderr.write(
|
|
16409
|
+
`Created deploy token "${trimmed}" (${created.id}), ${created.expiresAt ? `valid until ${day(created.expiresAt)}` : "without expiry"}.
|
|
16410
|
+
This token will not be shown again. Store it now, e.g. as the CI secret KRYD_TOKEN.
|
|
16411
|
+
`
|
|
16412
|
+
);
|
|
16413
|
+
} catch (err) {
|
|
16414
|
+
reportTokenError(err);
|
|
16415
|
+
}
|
|
16416
|
+
}
|
|
16417
|
+
async function runTokenList(opts) {
|
|
16418
|
+
const token = requireToken2();
|
|
16419
|
+
if (!token) return;
|
|
16420
|
+
try {
|
|
16421
|
+
const list = await listDeployTokens(resolveApiUrl(opts.apiUrl), token);
|
|
16422
|
+
if (opts.json) {
|
|
16423
|
+
process.stdout.write(`${JSON.stringify(list, null, 2)}
|
|
16424
|
+
`);
|
|
16425
|
+
return;
|
|
16426
|
+
}
|
|
16427
|
+
if (list.length === 0) {
|
|
16428
|
+
process.stdout.write("No deploy tokens. Create one with `kryd token create <name>`.\n");
|
|
16429
|
+
return;
|
|
16430
|
+
}
|
|
16431
|
+
const rows = [
|
|
16432
|
+
["ID", "NAME", "STARTS WITH", "CREATED", "LAST USED", "EXPIRES"],
|
|
16433
|
+
...list.map((t) => [
|
|
16434
|
+
t.id,
|
|
16435
|
+
t.name ?? "\u2014",
|
|
16436
|
+
t.start ? `${t.start}\u2026` : "\u2014",
|
|
16437
|
+
day(t.createdAt),
|
|
16438
|
+
day(t.lastRequest),
|
|
16439
|
+
t.expiresAt ? day(t.expiresAt) : "never"
|
|
16440
|
+
])
|
|
16441
|
+
];
|
|
16442
|
+
const widths = rows[0].map((_, i) => Math.max(...rows.map((r) => r[i].length)));
|
|
16443
|
+
for (const r of rows) {
|
|
16444
|
+
process.stdout.write(`${r.map((c, i) => c.padEnd(widths[i])).join(" ").trimEnd()}
|
|
16445
|
+
`);
|
|
16446
|
+
}
|
|
16447
|
+
} catch (err) {
|
|
16448
|
+
reportTokenError(err);
|
|
16449
|
+
}
|
|
16450
|
+
}
|
|
16451
|
+
async function runTokenRevoke(id, opts) {
|
|
16452
|
+
const token = requireToken2();
|
|
16453
|
+
if (!token) return;
|
|
16454
|
+
try {
|
|
16455
|
+
await revokeDeployToken(resolveApiUrl(opts.apiUrl), token, id);
|
|
16456
|
+
process.stdout.write(`Revoked ${id}. Anything still using it now gets 401.
|
|
16457
|
+
`);
|
|
16458
|
+
} catch (err) {
|
|
16459
|
+
reportTokenError(err);
|
|
16460
|
+
}
|
|
16461
|
+
}
|
|
16462
|
+
|
|
16311
16463
|
// src/browser-login.ts
|
|
16312
16464
|
import { spawn } from "node:child_process";
|
|
16313
16465
|
import { randomUUID } from "node:crypto";
|
|
@@ -16396,7 +16548,7 @@ async function runGitCredential(operation, opts = {}) {
|
|
|
16396
16548
|
const input = parseCredentialInput(opts.stdin ?? "");
|
|
16397
16549
|
if (input.protocol && input.protocol !== "https") return;
|
|
16398
16550
|
const cwd = opts.cwd ?? process.cwd();
|
|
16399
|
-
const token =
|
|
16551
|
+
const token = resolveToken();
|
|
16400
16552
|
if (!token) return;
|
|
16401
16553
|
const projectId = resolveProjectId(void 0, cwd);
|
|
16402
16554
|
if (!projectId) return;
|
|
@@ -17607,7 +17759,7 @@ async function explainMissingProject(err) {
|
|
|
17607
17759
|
if (err.status !== 404) return "";
|
|
17608
17760
|
const resolution = resolvedLink();
|
|
17609
17761
|
if (!resolution) return "";
|
|
17610
|
-
const token =
|
|
17762
|
+
const token = resolveToken();
|
|
17611
17763
|
if (!token) return "";
|
|
17612
17764
|
if (await projectIsVisible(token, resolution.link.projectId) !== false) return "";
|
|
17613
17765
|
let session;
|
|
@@ -17635,7 +17787,7 @@ async function backfillLinkAccount() {
|
|
|
17635
17787
|
const resolution = resolvedLink();
|
|
17636
17788
|
if (!resolution) return;
|
|
17637
17789
|
if (resolution.link.accountId && resolution.link.accountSlug) return;
|
|
17638
|
-
const token =
|
|
17790
|
+
const token = resolveToken();
|
|
17639
17791
|
if (!token) return;
|
|
17640
17792
|
if (await projectIsVisible(token, resolution.link.projectId) !== true) return;
|
|
17641
17793
|
try {
|
|
@@ -17660,15 +17812,17 @@ async function runLogin(opts) {
|
|
|
17660
17812
|
if (pastedToken) {
|
|
17661
17813
|
saveToken(pastedToken, apiUrl);
|
|
17662
17814
|
process.stdout.write("Token saved.\n");
|
|
17815
|
+
warnIfEnvTokenOverrides();
|
|
17663
17816
|
return;
|
|
17664
17817
|
}
|
|
17665
17818
|
const { token, apiUrl: learnedApiUrl } = await browserLogin(resolveDashboardUrl(opts.dashboardUrl));
|
|
17666
17819
|
saveToken(token, learnedApiUrl ?? apiUrl);
|
|
17667
17820
|
process.stdout.write("Logged in.\n");
|
|
17821
|
+
warnIfEnvTokenOverrides();
|
|
17668
17822
|
}
|
|
17669
17823
|
async function runWhoami(opts = {}) {
|
|
17670
17824
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
17671
|
-
const token =
|
|
17825
|
+
const token = resolveToken() ?? "";
|
|
17672
17826
|
try {
|
|
17673
17827
|
const me = await whoami(apiUrl, token);
|
|
17674
17828
|
process.stdout.write(
|
|
@@ -17679,14 +17833,22 @@ async function runWhoami(opts = {}) {
|
|
|
17679
17833
|
await reportError(err);
|
|
17680
17834
|
}
|
|
17681
17835
|
}
|
|
17836
|
+
function warnIfEnvTokenOverrides() {
|
|
17837
|
+
if (process.env.KRYD_TOKEN?.trim()) {
|
|
17838
|
+
process.stderr.write(
|
|
17839
|
+
"KRYD_TOKEN is set in this shell and overrides the stored login; commands keep using it until you unset it.\n"
|
|
17840
|
+
);
|
|
17841
|
+
}
|
|
17842
|
+
}
|
|
17682
17843
|
function runLogout() {
|
|
17683
17844
|
clearToken();
|
|
17684
17845
|
process.stdout.write("Logged out.\n");
|
|
17846
|
+
warnIfEnvTokenOverrides();
|
|
17685
17847
|
}
|
|
17686
17848
|
async function runInit(opts) {
|
|
17687
17849
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
17688
17850
|
const cwd = opts.cwd ?? process.cwd();
|
|
17689
|
-
const token =
|
|
17851
|
+
const token = resolveToken();
|
|
17690
17852
|
if (!token) {
|
|
17691
17853
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
17692
17854
|
process.exitCode = 1;
|
|
@@ -17909,7 +18071,7 @@ async function replayStoredLog(apiUrl, token, deploymentId) {
|
|
|
17909
18071
|
}
|
|
17910
18072
|
async function runLogs(opts) {
|
|
17911
18073
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
17912
|
-
const token =
|
|
18074
|
+
const token = resolveToken();
|
|
17913
18075
|
if (!token) {
|
|
17914
18076
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
17915
18077
|
process.exitCode = 1;
|
|
@@ -17961,7 +18123,7 @@ async function runLogs(opts) {
|
|
|
17961
18123
|
}
|
|
17962
18124
|
async function runRuntimeLogs(opts) {
|
|
17963
18125
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
17964
|
-
const token =
|
|
18126
|
+
const token = resolveToken();
|
|
17965
18127
|
if (!token) {
|
|
17966
18128
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
17967
18129
|
process.exitCode = 1;
|
|
@@ -18018,7 +18180,7 @@ async function runRuntimeLogs(opts) {
|
|
|
18018
18180
|
}
|
|
18019
18181
|
async function runDeploy(opts) {
|
|
18020
18182
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18021
|
-
const token =
|
|
18183
|
+
const token = resolveToken();
|
|
18022
18184
|
if (!token) {
|
|
18023
18185
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18024
18186
|
process.exitCode = 1;
|
|
@@ -18054,7 +18216,7 @@ function renderFor(logs) {
|
|
|
18054
18216
|
var LOGS_FLAG_HELP = "stream the full build log line by line instead of the progress display";
|
|
18055
18217
|
async function runPush(opts) {
|
|
18056
18218
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18057
|
-
const token =
|
|
18219
|
+
const token = resolveToken();
|
|
18058
18220
|
if (!token) {
|
|
18059
18221
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18060
18222
|
process.exitCode = 1;
|
|
@@ -18206,7 +18368,7 @@ async function followApps(apiUrl, token, deployments, render, estimateFrom) {
|
|
|
18206
18368
|
}
|
|
18207
18369
|
async function runRollback(opts) {
|
|
18208
18370
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18209
|
-
const token =
|
|
18371
|
+
const token = resolveToken();
|
|
18210
18372
|
if (!token) {
|
|
18211
18373
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18212
18374
|
process.exitCode = 1;
|
|
@@ -18237,7 +18399,7 @@ async function runRollback(opts) {
|
|
|
18237
18399
|
}
|
|
18238
18400
|
async function runRedeploy(opts) {
|
|
18239
18401
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18240
|
-
const token =
|
|
18402
|
+
const token = resolveToken();
|
|
18241
18403
|
if (!token) {
|
|
18242
18404
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18243
18405
|
process.exitCode = 1;
|
|
@@ -18267,7 +18429,7 @@ ${note}
|
|
|
18267
18429
|
}
|
|
18268
18430
|
async function runDbAdd(opts) {
|
|
18269
18431
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18270
|
-
const token =
|
|
18432
|
+
const token = resolveToken();
|
|
18271
18433
|
if (!token) {
|
|
18272
18434
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18273
18435
|
process.exitCode = 1;
|
|
@@ -18348,7 +18510,7 @@ function reportSettleResult(result, opts) {
|
|
|
18348
18510
|
}
|
|
18349
18511
|
async function runStorageAdd(opts) {
|
|
18350
18512
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18351
|
-
const token =
|
|
18513
|
+
const token = resolveToken();
|
|
18352
18514
|
if (!token) {
|
|
18353
18515
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18354
18516
|
process.exitCode = 1;
|
|
@@ -18442,7 +18604,7 @@ ${listed}Re-run \`kryd project rm <id>\` with the one you mean.
|
|
|
18442
18604
|
}
|
|
18443
18605
|
async function runProjectRemove(opts) {
|
|
18444
18606
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18445
|
-
const token =
|
|
18607
|
+
const token = resolveToken();
|
|
18446
18608
|
if (!token) {
|
|
18447
18609
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18448
18610
|
process.exitCode = 1;
|
|
@@ -18557,7 +18719,7 @@ async function describeProjectResources(apiUrl, token, projectId) {
|
|
|
18557
18719
|
}
|
|
18558
18720
|
async function runDbRemove(opts) {
|
|
18559
18721
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18560
|
-
const token =
|
|
18722
|
+
const token = resolveToken();
|
|
18561
18723
|
if (!token) {
|
|
18562
18724
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18563
18725
|
process.exitCode = 1;
|
|
@@ -18596,7 +18758,7 @@ async function runDbRemove(opts) {
|
|
|
18596
18758
|
}
|
|
18597
18759
|
async function runAiAdd(opts) {
|
|
18598
18760
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18599
|
-
const token =
|
|
18761
|
+
const token = resolveToken();
|
|
18600
18762
|
if (!token) {
|
|
18601
18763
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18602
18764
|
process.exitCode = 1;
|
|
@@ -18621,7 +18783,7 @@ async function runAiAdd(opts) {
|
|
|
18621
18783
|
}
|
|
18622
18784
|
async function runAiRemove(opts) {
|
|
18623
18785
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18624
|
-
const token =
|
|
18786
|
+
const token = resolveToken();
|
|
18625
18787
|
if (!token) {
|
|
18626
18788
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18627
18789
|
process.exitCode = 1;
|
|
@@ -18688,7 +18850,7 @@ Remove it before attaching another.
|
|
|
18688
18850
|
}
|
|
18689
18851
|
async function runDbStatus(opts) {
|
|
18690
18852
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18691
|
-
const token =
|
|
18853
|
+
const token = resolveToken();
|
|
18692
18854
|
if (!token) {
|
|
18693
18855
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18694
18856
|
process.exitCode = 1;
|
|
@@ -18708,7 +18870,7 @@ async function runDbStatus(opts) {
|
|
|
18708
18870
|
}
|
|
18709
18871
|
async function runStorageStatus(opts) {
|
|
18710
18872
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18711
|
-
const token =
|
|
18873
|
+
const token = resolveToken();
|
|
18712
18874
|
if (!token) {
|
|
18713
18875
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18714
18876
|
process.exitCode = 1;
|
|
@@ -18728,7 +18890,7 @@ async function runStorageStatus(opts) {
|
|
|
18728
18890
|
}
|
|
18729
18891
|
async function runAiStatus(opts) {
|
|
18730
18892
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18731
|
-
const token =
|
|
18893
|
+
const token = resolveToken();
|
|
18732
18894
|
if (!token) {
|
|
18733
18895
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18734
18896
|
process.exitCode = 1;
|
|
@@ -18764,7 +18926,7 @@ function daysUntil(iso) {
|
|
|
18764
18926
|
var TOKEN_EXPIRY_WARNING_DAYS = 30;
|
|
18765
18927
|
async function runWorkflowAdd(opts) {
|
|
18766
18928
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18767
|
-
const token =
|
|
18929
|
+
const token = resolveToken();
|
|
18768
18930
|
if (!token) {
|
|
18769
18931
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18770
18932
|
process.exitCode = 1;
|
|
@@ -18797,7 +18959,7 @@ HATCHET_CLIENT_TOKEN will be injected on your next production deploy (kryd deplo
|
|
|
18797
18959
|
}
|
|
18798
18960
|
async function runWorkflowRemove(opts) {
|
|
18799
18961
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18800
|
-
const token =
|
|
18962
|
+
const token = resolveToken();
|
|
18801
18963
|
if (!token) {
|
|
18802
18964
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18803
18965
|
process.exitCode = 1;
|
|
@@ -18842,7 +19004,7 @@ Workflow history, crons and schedules stay until the project is deleted.
|
|
|
18842
19004
|
}
|
|
18843
19005
|
async function runWorkflowStatus(opts) {
|
|
18844
19006
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18845
|
-
const token =
|
|
19007
|
+
const token = resolveToken();
|
|
18846
19008
|
if (!token) {
|
|
18847
19009
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18848
19010
|
process.exitCode = 1;
|
|
@@ -18901,7 +19063,7 @@ function formatDomainRecords(records) {
|
|
|
18901
19063
|
}
|
|
18902
19064
|
function domainContext(opts, usage2) {
|
|
18903
19065
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
18904
|
-
const token =
|
|
19066
|
+
const token = resolveToken();
|
|
18905
19067
|
if (!token) {
|
|
18906
19068
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
18907
19069
|
process.exitCode = 1;
|
|
@@ -19308,7 +19470,7 @@ HATCHET_CLIENT_TOKEN is injected into your app and your worker on production dep
|
|
|
19308
19470
|
}
|
|
19309
19471
|
async function runStorageRemove(opts) {
|
|
19310
19472
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19311
|
-
const token =
|
|
19473
|
+
const token = resolveToken();
|
|
19312
19474
|
if (!token) {
|
|
19313
19475
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19314
19476
|
process.exitCode = 1;
|
|
@@ -19371,7 +19533,7 @@ function envAnnotation(environments) {
|
|
|
19371
19533
|
}
|
|
19372
19534
|
async function runProjectList(opts) {
|
|
19373
19535
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19374
|
-
const token =
|
|
19536
|
+
const token = resolveToken();
|
|
19375
19537
|
if (!token) {
|
|
19376
19538
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19377
19539
|
process.exitCode = 1;
|
|
@@ -19422,7 +19584,7 @@ ${rows}`;
|
|
|
19422
19584
|
}
|
|
19423
19585
|
async function runEnvList(opts) {
|
|
19424
19586
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19425
|
-
const token =
|
|
19587
|
+
const token = resolveToken();
|
|
19426
19588
|
if (!token) {
|
|
19427
19589
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19428
19590
|
process.exitCode = 1;
|
|
@@ -19504,7 +19666,7 @@ function toDotenvLine(key, value) {
|
|
|
19504
19666
|
}
|
|
19505
19667
|
async function runEnvPull(opts) {
|
|
19506
19668
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19507
|
-
const token =
|
|
19669
|
+
const token = resolveToken();
|
|
19508
19670
|
if (!token) {
|
|
19509
19671
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19510
19672
|
process.exitCode = 1;
|
|
@@ -19605,7 +19767,7 @@ async function runEnvSet(opts) {
|
|
|
19605
19767
|
const scope = opts.build ? "build" : "runtime";
|
|
19606
19768
|
const environment = opts.preview ? "preview" : "production";
|
|
19607
19769
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19608
|
-
const token =
|
|
19770
|
+
const token = resolveToken();
|
|
19609
19771
|
if (!token) {
|
|
19610
19772
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19611
19773
|
process.exitCode = 1;
|
|
@@ -19700,7 +19862,7 @@ async function runEnvRemove(opts) {
|
|
|
19700
19862
|
const scope = opts.build ? "build" : "runtime";
|
|
19701
19863
|
const environment = opts.preview ? "preview" : "production";
|
|
19702
19864
|
const apiUrl = resolveApiUrl(opts.apiUrl);
|
|
19703
|
-
const token =
|
|
19865
|
+
const token = resolveToken();
|
|
19704
19866
|
if (!token) {
|
|
19705
19867
|
process.stderr.write("Not logged in \u2014 run `kryd login` first.\n");
|
|
19706
19868
|
process.exitCode = 1;
|
|
@@ -19794,7 +19956,7 @@ Run \`kryd env list\` to see what is set. (If you meant the runtime variable of
|
|
|
19794
19956
|
await reportError(err);
|
|
19795
19957
|
}
|
|
19796
19958
|
}
|
|
19797
|
-
var CLI_VERSION = true ? "0.
|
|
19959
|
+
var CLI_VERSION = true ? "0.15.0" : "0.0.0-dev";
|
|
19798
19960
|
var program = new Command();
|
|
19799
19961
|
program.name("kryd").description("Kryd CLI").version(CLI_VERSION);
|
|
19800
19962
|
program.hook("postAction", async () => {
|
|
@@ -19942,6 +20104,10 @@ support.command("new").description(
|
|
|
19942
20104
|
support.command("list").description("Your account's tickets, with their status").option("--json", "print { items } as JSON on stdout").option("--api-url <url>", "control-plane API base URL").action((opts) => runSupportList(opts));
|
|
19943
20105
|
support.command("show <ticket>").description("One ticket and its conversation, e.g. `kryd support show T-1042`").option("--json", "print the ticket and its messages as JSON on stdout").option("--api-url <url>", "control-plane API base URL").action((ticket, opts) => runSupportShow(ticket, opts));
|
|
19944
20106
|
support.command("reply <ticket>").description("Answer in a ticket's conversation \u2014 the ticket goes back to Kryd support (status open)").option("--message <text>", "your reply (required)").option("--json", "print the updated ticket as JSON on stdout").option("--api-url <url>", "control-plane API base URL").action((ticket, opts) => runSupportReply(ticket, opts));
|
|
20107
|
+
var tokenCommand = program.command("token").description("Deploy tokens for CI and scripts: set one as KRYD_TOKEN and every command uses it, no login needed");
|
|
20108
|
+
tokenCommand.command("create <name>").description("Create a deploy token and print it once \u2014 it acts as you, inside your account").option("--expires <days>", "30 | 90 | 365 | never", DEFAULT_TOKEN_EXPIRY).option("--api-url <url>", "control-plane API base URL").action((name, opts) => runTokenCreate(name, opts));
|
|
20109
|
+
tokenCommand.command("list").description("Your deploy tokens: name, first characters, created, last used, expiry \u2014 never the value").option("--json", "print the tokens as JSON on stdout").option("--api-url <url>", "control-plane API base URL").action((opts) => runTokenList(opts));
|
|
20110
|
+
tokenCommand.command("revoke <id>").description("Revoke a deploy token; anything still using it gets 401").option("--api-url <url>", "control-plane API base URL").action((id, opts) => runTokenRevoke(id, opts));
|
|
19945
20111
|
function invokedDirectly() {
|
|
19946
20112
|
const entry = process.argv[1];
|
|
19947
20113
|
if (!entry) return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kryd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Kryd CLI — git push → live on the European cloud for your AI: SSL, managed Postgres & object storage, and an EU-hosted AI gateway. Your code and model calls stay in the EU. Beta: sign up at https://kryd.eu/beta",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kryd",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"tsx": "^4.19.2",
|
|
42
42
|
"typescript": "^5.6.3",
|
|
43
43
|
"vitest": "^2.1.8",
|
|
44
|
-
"@kryd/
|
|
44
|
+
"@kryd/shared-types": "0.0.0",
|
|
45
45
|
"@kryd/config-ts": "0.0.0",
|
|
46
|
-
"@kryd/
|
|
46
|
+
"@kryd/config-eslint": "0.0.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --external:commander --define:__KRYD_VERSION__=\\\"$npm_package_version\\\" --outfile=dist/index.js",
|