@kryd/cli 0.11.0 → 0.12.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 +2 -0
- package/dist/index.js +31 -19
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The command-line client for **[Kryd](https://kryd.eu)** — the **European cloud for your AI**. Push a React / Vite / Next.js app and seconds later it's live on a real URL with SSL, one-click managed Postgres and object storage, and an EU-hosted AI gateway already wired in. The same instant `git push → live` loop you know from Vercel/Netlify, on infrastructure that is genuinely European — code **and** AI inference stay inside the EU.
|
|
4
4
|
|
|
5
|
+
**Kryd is in beta.** `kryd login` needs a Kryd account: sign up for a beta account at **[kryd.eu/beta](https://kryd.eu/beta)**.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```sh
|
package/dist/index.js
CHANGED
|
@@ -15433,7 +15433,7 @@ function parseDomainRecord(body) {
|
|
|
15433
15433
|
function parseProjectDomain(body, label) {
|
|
15434
15434
|
const d = body;
|
|
15435
15435
|
const bad = () => new ApiError(`The API returned an unexpected ${label} response.`);
|
|
15436
|
-
if (!d || typeof d.id !== "string" || typeof d.host !== "string" || typeof d.status !== "string" || !DOMAIN_STATUSES.includes(d.status) || typeof d.detail !== "string" && d.detail !== null || typeof d.checkedAt !== "string" && d.checkedAt !== null || typeof d.createdAt !== "string" || !Array.isArray(d.records)) {
|
|
15436
|
+
if (!d || typeof d.id !== "string" || typeof d.host !== "string" || typeof d.status !== "string" || !DOMAIN_STATUSES.includes(d.status) || typeof d.detail !== "string" && d.detail !== null || typeof d.checkedAt !== "string" && d.checkedAt !== null || typeof d.createdAt !== "string" || !Array.isArray(d.records) || d.redirectTo !== void 0 && typeof d.redirectTo !== "string") {
|
|
15437
15437
|
throw bad();
|
|
15438
15438
|
}
|
|
15439
15439
|
const records = d.records.map(parseDomainRecord);
|
|
@@ -15443,6 +15443,8 @@ function parseProjectDomain(body, label) {
|
|
|
15443
15443
|
host: d.host,
|
|
15444
15444
|
// KRYD-381a — absent from an older API: then it is `web`, the only app there was.
|
|
15445
15445
|
...typeof d.app === "string" ? { app: d.app } : {},
|
|
15446
|
+
// KRYD-541 — present only on a redirect domain.
|
|
15447
|
+
...typeof d.redirectTo === "string" ? { redirectTo: d.redirectTo } : {},
|
|
15446
15448
|
status: d.status,
|
|
15447
15449
|
detail: d.detail,
|
|
15448
15450
|
checkedAt: d.checkedAt,
|
|
@@ -15469,11 +15471,11 @@ async function listDomains(apiUrl, token, projectId) {
|
|
|
15469
15471
|
domains: body.domains.map((d) => parseProjectDomain(d, "domain-list"))
|
|
15470
15472
|
};
|
|
15471
15473
|
}
|
|
15472
|
-
async function addDomain(apiUrl, token, projectId, host, app) {
|
|
15474
|
+
async function addDomain(apiUrl, token, projectId, host, app, redirectTo) {
|
|
15473
15475
|
const res = await fetch(domainsUrl(apiUrl, projectId), {
|
|
15474
15476
|
method: "POST",
|
|
15475
15477
|
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
15476
|
-
body: JSON.stringify({ host, ...app ? { app } : {} })
|
|
15478
|
+
body: JSON.stringify({ host, ...app ? { app } : {}, ...redirectTo !== void 0 ? { redirectTo } : {} })
|
|
15477
15479
|
});
|
|
15478
15480
|
if (!res.ok) {
|
|
15479
15481
|
throw new ApiError(`Domain add failed (${res.status})`, await parseEnvelope(res), res.status);
|
|
@@ -18135,7 +18137,7 @@ async function resolveProjectIdByName(apiUrl, token, name) {
|
|
|
18135
18137
|
const matches = projects.filter((p) => p.name === name);
|
|
18136
18138
|
if (matches.length === 0) {
|
|
18137
18139
|
process.stderr.write(
|
|
18138
|
-
`No project named ${name} on this account. Run \`kryd project list\`
|
|
18140
|
+
`No project named ${name} on this account. Run \`kryd project list\` and use the NAME column, not SUBDOMAIN.
|
|
18139
18141
|
`
|
|
18140
18142
|
);
|
|
18141
18143
|
process.exitCode = 1;
|
|
@@ -18631,22 +18633,22 @@ async function runDomainAdd(opts) {
|
|
|
18631
18633
|
if (!ctx) return;
|
|
18632
18634
|
try {
|
|
18633
18635
|
const [domain3, list] = await Promise.all([
|
|
18634
|
-
addDomain(ctx.apiUrl, ctx.token, ctx.project, opts.host, opts.app),
|
|
18636
|
+
addDomain(ctx.apiUrl, ctx.token, ctx.project, opts.host, opts.app, opts.redirect),
|
|
18635
18637
|
listDomains(ctx.apiUrl, ctx.token, ctx.project).catch(() => null)
|
|
18636
18638
|
]);
|
|
18637
18639
|
if (domain3.status !== "pending") {
|
|
18638
18640
|
process.stdout.write(
|
|
18639
|
-
`${domain3.host} is already on ${ctx.project}${
|
|
18641
|
+
`${domain3.host} is already on ${ctx.project}${domainRole(domain3)}: ${DOMAIN_STATUS_TEXT[domain3.status]}.
|
|
18640
18642
|
`
|
|
18641
18643
|
);
|
|
18642
18644
|
return;
|
|
18643
18645
|
}
|
|
18644
18646
|
process.stdout.write(
|
|
18645
|
-
`${domain3.host} added to ${ctx.project}${
|
|
18647
|
+
`${domain3.host} added to ${ctx.project}${domainRole(domain3)} \u2014 pending until its DNS records exist.
|
|
18646
18648
|
|
|
18647
18649
|
Create these records at your DNS provider:
|
|
18648
18650
|
` + formatDomainRecords(domain3.records) + `
|
|
18649
|
-
Kryd checks every minute; once they are right it issues a certificate and serves ${domain3.host} from ${domain3.app && domain3.app !== "web" ? `app ${domain3.app}'s` : "your"} production deploy
|
|
18651
|
+
Kryd checks every minute; once they are right it issues a certificate and ` + (domain3.redirectTo ? `answers every request on ${domain3.host} with a permanent redirect (301) to https://${domain3.redirectTo}, path and query kept.` : `serves ${domain3.host} from ${domain3.app && domain3.app !== "web" ? `app ${domain3.app}'s` : "your"} production deploy.`) + ` Follow it with \`kryd domain status ${domain3.host}\`.
|
|
18650
18652
|
` + (list?.projectHost ? `${ctx.project} keeps its own host, ${list.projectHost}.
|
|
18651
18653
|
` : "")
|
|
18652
18654
|
);
|
|
@@ -18688,6 +18690,9 @@ async function runDeployHookRemove(opts) {
|
|
|
18688
18690
|
function appSuffix(app) {
|
|
18689
18691
|
return app && app !== "web" ? ` (app ${app})` : "";
|
|
18690
18692
|
}
|
|
18693
|
+
function domainRole(d) {
|
|
18694
|
+
return d.redirectTo ? ` \u2192 redirects to ${d.redirectTo}` : appSuffix(d.app);
|
|
18695
|
+
}
|
|
18691
18696
|
async function runDomainRemove(opts) {
|
|
18692
18697
|
const ctx = domainContext(opts, "kryd domain remove <host> --project <projectId>");
|
|
18693
18698
|
if (!ctx) return;
|
|
@@ -18727,7 +18732,7 @@ ${own}`);
|
|
|
18727
18732
|
let out2 = `${ctx.project}: ${list.domains.length} custom domain${list.domains.length === 1 ? "" : "s"}.
|
|
18728
18733
|
`;
|
|
18729
18734
|
for (const d2 of list.domains) {
|
|
18730
|
-
out2 += ` ${d2.host} ${DOMAIN_STATUS_TEXT[d2.status]}
|
|
18735
|
+
out2 += ` ${d2.host} ${DOMAIN_STATUS_TEXT[d2.status]}${d2.redirectTo ? ` \u2192 redirects to ${d2.redirectTo}` : ""}
|
|
18731
18736
|
`;
|
|
18732
18737
|
if (d2.detail) out2 += ` ${d2.detail}
|
|
18733
18738
|
`;
|
|
@@ -18744,6 +18749,8 @@ ${own}`);
|
|
|
18744
18749
|
return;
|
|
18745
18750
|
}
|
|
18746
18751
|
let out = `${d.host}: ${DOMAIN_STATUS_TEXT[d.status]}.
|
|
18752
|
+
`;
|
|
18753
|
+
if (d.redirectTo) out += ` \u2192 redirects to ${d.redirectTo}
|
|
18747
18754
|
`;
|
|
18748
18755
|
if (d.detail) out += ` ${d.detail}
|
|
18749
18756
|
`;
|
|
@@ -19096,15 +19103,17 @@ async function runProjectList(opts) {
|
|
|
19096
19103
|
return;
|
|
19097
19104
|
}
|
|
19098
19105
|
const linkedId = resolveProjectId(void 0, opts.cwd);
|
|
19099
|
-
const nameWidth = projects.reduce((max, p) => Math.max(max, p.name.length),
|
|
19100
|
-
const subWidth = projects.reduce(
|
|
19101
|
-
|
|
19106
|
+
const nameWidth = projects.reduce((max, p) => Math.max(max, p.name.length), "NAME".length);
|
|
19107
|
+
const subWidth = projects.reduce(
|
|
19108
|
+
(max, p) => Math.max(max, p.subdomain.length),
|
|
19109
|
+
"SUBDOMAIN".length
|
|
19110
|
+
);
|
|
19111
|
+
const statusWidth = projects.reduce((max, p) => Math.max(max, p.status.length), "STATUS".length);
|
|
19112
|
+
const row = (mark, name, sub, status, id) => `${mark} ${name.padEnd(nameWidth)} ${sub.padEnd(subWidth)} ${status.padEnd(statusWidth)} ${id}
|
|
19113
|
+
`;
|
|
19114
|
+
process.stdout.write(row(" ", "NAME", "SUBDOMAIN", "STATUS", "ID"));
|
|
19102
19115
|
for (const p of projects) {
|
|
19103
|
-
|
|
19104
|
-
process.stdout.write(
|
|
19105
|
-
`${mark} ${p.name.padEnd(nameWidth)} ${p.subdomain.padEnd(subWidth)} ${p.status.padEnd(statusWidth)} ${p.id}
|
|
19106
|
-
`
|
|
19107
|
-
);
|
|
19116
|
+
process.stdout.write(row(p.id === linkedId ? "*" : " ", p.name, p.subdomain, p.status, p.id));
|
|
19108
19117
|
}
|
|
19109
19118
|
if (projects.some((p) => p.id === linkedId)) {
|
|
19110
19119
|
process.stdout.write("\n* linked to this directory\n");
|
|
@@ -19499,7 +19508,7 @@ Run \`kryd env list\` to see what is set. (If you meant the runtime variable of
|
|
|
19499
19508
|
await reportError(err);
|
|
19500
19509
|
}
|
|
19501
19510
|
}
|
|
19502
|
-
var CLI_VERSION = true ? "0.
|
|
19511
|
+
var CLI_VERSION = true ? "0.12.0" : "0.0.0-dev";
|
|
19503
19512
|
var program = new Command();
|
|
19504
19513
|
program.name("kryd").description("Kryd CLI").version(CLI_VERSION);
|
|
19505
19514
|
program.hook("postAction", async () => {
|
|
@@ -19632,7 +19641,10 @@ workflow.command("init").description(
|
|
|
19632
19641
|
`worker language: ${SCAFFOLD_LANGUAGES.join(" | ")}`
|
|
19633
19642
|
).option("--path <folder>", "the worker's folder inside the app (default: workflows)").option("--only", "a project that runs ONLY a worker: scaffold it at the root, git init, and link").option("--dir <path>", "the project directory, instead of the current one").option("--name <name>", "worker name (and, with --only, project name); defaults to the directory name").option("--no-link", "with --only: only write the files; do not create a Kryd project").option("--api-url <url>", "control-plane API base URL").action((opts) => runWorkflowInit(opts));
|
|
19634
19643
|
var domain2 = program.command("domain").description("Serve the project on your own hostname (custom domains)");
|
|
19635
|
-
domain2.command("add <host>").description("Add a custom domain and print the DNS records to create").option("--project <projectId>", "the project (default: the one linked here)").option("--app <name>", "a project with several web apps: the app the domain serves (default: web)").option(
|
|
19644
|
+
domain2.command("add <host>").description("Add a custom domain and print the DNS records to create").option("--project <projectId>", "the project (default: the one linked here)").option("--app <name>", "a project with several web apps: the app the domain serves (default: web)").option(
|
|
19645
|
+
"--redirect <host>",
|
|
19646
|
+
"redirect instead of serving: every request answers 301 to https://<host>, path and query kept"
|
|
19647
|
+
).option("--api-url <url>", "control-plane API base URL").action((host, opts) => runDomainAdd({ ...opts, host }));
|
|
19636
19648
|
domain2.command("remove <host>").description("Remove a custom domain \u2014 its route and certificate go (asks for confirmation)").option("--project <projectId>", "the project (default: the one linked here)").option("--yes", "skip the confirmation prompt").option("--api-url <url>", "control-plane API base URL").action((host, opts) => runDomainRemove({ ...opts, host }));
|
|
19637
19649
|
domain2.command("status [host]").description("Show the project's custom domains, or one in detail with what is missing").option("--project <projectId>", "the project (default: the one linked here)").option("--api-url <url>", "control-plane API base URL").action((host, opts) => runDomainStatus({ ...opts, host }));
|
|
19638
19650
|
function invokedDirectly() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kryd/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Kryd CLI — push a React / Vite / Next.js app to the European cloud for your AI: git push → live with SSL, one-click managed Postgres & object storage, and an EU-hosted AI gateway already wired in. Your code and your model calls stay in the EU.",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Kryd CLI — push a React / Vite / Next.js app to the European cloud for your AI: git push → live with SSL, one-click managed Postgres & object storage, and an EU-hosted AI gateway already wired in. Your code and your model calls stay in the EU. Kryd is in beta: sign up for a beta account at https://kryd.eu/beta.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kryd",
|
|
7
7
|
"deploy",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"tsx": "^4.19.2",
|
|
42
42
|
"typescript": "^5.6.3",
|
|
43
43
|
"vitest": "^2.1.8",
|
|
44
|
+
"@kryd/config-eslint": "0.0.0",
|
|
44
45
|
"@kryd/shared-types": "0.0.0",
|
|
45
|
-
"@kryd/config-ts": "0.0.0"
|
|
46
|
-
"@kryd/config-eslint": "0.0.0"
|
|
46
|
+
"@kryd/config-ts": "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",
|