@neta-art/cohub-cli 10.11.0 → 10.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 +9 -0
- package/dist/board-kernel.js +46 -44
- package/dist/commands/app-domains.d.ts +2 -0
- package/dist/commands/app-domains.js +133 -0
- package/dist/commands/apps.js +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -496,6 +496,15 @@ cohub apps versions <appId> --json
|
|
|
496
496
|
cohub apps rm <appId> --yes
|
|
497
497
|
```
|
|
498
498
|
|
|
499
|
+
Bind a custom domain to a published public App. The binding costs a one-time $5, charged when the domain goes live; `add` prints the CNAME and TXT records to create at the DNS provider:
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
cohub apps domains add <app> app.example.com --yes
|
|
503
|
+
cohub apps domains ls <app>
|
|
504
|
+
cohub apps domains check <app> app.example.com
|
|
505
|
+
cohub apps domains rm <app> app.example.com --yes
|
|
506
|
+
```
|
|
507
|
+
|
|
499
508
|
Resolve a published App by public identity:
|
|
500
509
|
|
|
501
510
|
```bash
|
package/dist/board-kernel.js
CHANGED
|
@@ -9401,6 +9401,7 @@ function isBoardModelItem(item) {
|
|
|
9401
9401
|
}
|
|
9402
9402
|
//#endregion
|
|
9403
9403
|
//#region ../sdk/src/board/model/asset-key.ts
|
|
9404
|
+
const COVER = "cover:";
|
|
9404
9405
|
function imageAssetKey(item) {
|
|
9405
9406
|
if (item.type === "image") {
|
|
9406
9407
|
const source = parseBoardMediaSource$1(item.props.src);
|
|
@@ -9421,8 +9422,7 @@ function imageAssetKey(item) {
|
|
|
9421
9422
|
return source ? `${source.kind}:${source.value}` : null;
|
|
9422
9423
|
}
|
|
9423
9424
|
const STILL_MEDIA = ["video", "model"];
|
|
9424
|
-
function stillKey(media,
|
|
9425
|
-
const source = parseBoardMediaSource$1(src);
|
|
9425
|
+
function stillKey(media, source, mtimeMs) {
|
|
9426
9426
|
if (!source) return null;
|
|
9427
9427
|
return source.kind === "url" ? `${media}-url:${encodeURIComponent(source.value)}` : `${media}:${encodeURIComponent(source.value)}:${mtimeMs ?? "unknown"}`;
|
|
9428
9428
|
}
|
|
@@ -9436,8 +9436,8 @@ function taskPreviewKey(item) {
|
|
|
9436
9436
|
}
|
|
9437
9437
|
function boardAssetKey(item) {
|
|
9438
9438
|
if (item.type === "task") return taskPreviewKey(item);
|
|
9439
|
-
if (item.type === "video") return stillKey("video", item.props.src, item.props.snapshot?.mtimeMs);
|
|
9440
|
-
if (item.type === "file" && isBoardModelItem(item)) return stillKey("model", item.props.src, item.props.snapshot?.mtimeMs);
|
|
9439
|
+
if (item.type === "video") return stillKey("video", parseBoardMediaSource$1(item.props.src), item.props.snapshot?.mtimeMs);
|
|
9440
|
+
if (item.type === "file" && isBoardModelItem(item)) return stillKey("model", parseBoardMediaSource$1(item.props.src), item.props.snapshot?.mtimeMs);
|
|
9441
9441
|
return imageAssetKey(item);
|
|
9442
9442
|
}
|
|
9443
9443
|
function boardAssetKeySource(key) {
|
|
@@ -9447,6 +9447,14 @@ function boardAssetKeySource(key) {
|
|
|
9447
9447
|
if (separator < 0) return null;
|
|
9448
9448
|
base = key.slice(separator + 1);
|
|
9449
9449
|
}
|
|
9450
|
+
if (!base.startsWith(COVER)) return sourceOf(base);
|
|
9451
|
+
const source = sourceOf(base.slice(6));
|
|
9452
|
+
return source?.media === "image" ? {
|
|
9453
|
+
...source,
|
|
9454
|
+
fit: "cover"
|
|
9455
|
+
} : null;
|
|
9456
|
+
}
|
|
9457
|
+
function sourceOf(base) {
|
|
9450
9458
|
try {
|
|
9451
9459
|
for (const media of STILL_MEDIA) {
|
|
9452
9460
|
if (base.startsWith(`${media}-url:`)) return {
|
|
@@ -9476,12 +9484,6 @@ function boardAssetKeySource(key) {
|
|
|
9476
9484
|
media: "image",
|
|
9477
9485
|
value: base.slice(4)
|
|
9478
9486
|
};
|
|
9479
|
-
if (base.startsWith("cover-url:")) return {
|
|
9480
|
-
kind: "url",
|
|
9481
|
-
media: "image",
|
|
9482
|
-
value: base.slice(10),
|
|
9483
|
-
fit: "cover"
|
|
9484
|
-
};
|
|
9485
9487
|
return null;
|
|
9486
9488
|
}
|
|
9487
9489
|
function boardTexturePixels(item, scale) {
|
|
@@ -10106,12 +10108,12 @@ const BOARD_THEME_DATA = {
|
|
|
10106
10108
|
colorScheme: "dark",
|
|
10107
10109
|
palette: {
|
|
10108
10110
|
bg: 329221,
|
|
10109
|
-
surface:
|
|
10110
|
-
hover:
|
|
10111
|
+
surface: 1249814,
|
|
10112
|
+
hover: 1973788,
|
|
10111
10113
|
border: 1842202,
|
|
10112
10114
|
brand: 3900150,
|
|
10113
|
-
text:
|
|
10114
|
-
muted:
|
|
10115
|
+
text: 16314853,
|
|
10116
|
+
muted: 7630695,
|
|
10115
10117
|
rare: 9235170,
|
|
10116
10118
|
epic: 7266776,
|
|
10117
10119
|
legendary: 15449187
|
|
@@ -10120,47 +10122,47 @@ const BOARD_THEME_DATA = {
|
|
|
10120
10122
|
brand: {
|
|
10121
10123
|
stroke: 15524306,
|
|
10122
10124
|
fill: 15524306,
|
|
10123
|
-
label:
|
|
10125
|
+
label: 16314853
|
|
10124
10126
|
},
|
|
10125
10127
|
neutral: {
|
|
10126
|
-
stroke:
|
|
10127
|
-
fill:
|
|
10128
|
-
label:
|
|
10128
|
+
stroke: 15524306,
|
|
10129
|
+
fill: 15524306,
|
|
10130
|
+
label: 16314853
|
|
10129
10131
|
},
|
|
10130
10132
|
black: {
|
|
10131
10133
|
stroke: 0,
|
|
10132
10134
|
fill: 0,
|
|
10133
|
-
label:
|
|
10135
|
+
label: 16314853
|
|
10134
10136
|
},
|
|
10135
10137
|
white: {
|
|
10136
10138
|
stroke: 16777215,
|
|
10137
10139
|
fill: 16777215,
|
|
10138
|
-
label:
|
|
10140
|
+
label: 16314853
|
|
10139
10141
|
},
|
|
10140
10142
|
blue: {
|
|
10141
10143
|
stroke: 9235170,
|
|
10142
10144
|
fill: 9235170,
|
|
10143
|
-
label:
|
|
10145
|
+
label: 16314853
|
|
10144
10146
|
},
|
|
10145
10147
|
green: {
|
|
10146
10148
|
stroke: 8177036,
|
|
10147
10149
|
fill: 8177036,
|
|
10148
|
-
label:
|
|
10150
|
+
label: 16314853
|
|
10149
10151
|
},
|
|
10150
10152
|
amber: {
|
|
10151
10153
|
stroke: 15449187,
|
|
10152
10154
|
fill: 15449187,
|
|
10153
|
-
label:
|
|
10155
|
+
label: 16314853
|
|
10154
10156
|
},
|
|
10155
10157
|
violet: {
|
|
10156
10158
|
stroke: 11971327,
|
|
10157
10159
|
fill: 11971327,
|
|
10158
|
-
label:
|
|
10160
|
+
label: 16314853
|
|
10159
10161
|
},
|
|
10160
10162
|
rose: {
|
|
10161
10163
|
stroke: 15562341,
|
|
10162
10164
|
fill: 15562341,
|
|
10163
|
-
label:
|
|
10165
|
+
label: 16314853
|
|
10164
10166
|
}
|
|
10165
10167
|
},
|
|
10166
10168
|
style: {
|
|
@@ -10173,8 +10175,8 @@ const BOARD_THEME_DATA = {
|
|
|
10173
10175
|
palette: {
|
|
10174
10176
|
bg: 16185078,
|
|
10175
10177
|
surface: 16777215,
|
|
10176
|
-
hover:
|
|
10177
|
-
border:
|
|
10178
|
+
hover: 16185078,
|
|
10179
|
+
border: 15527149,
|
|
10178
10180
|
brand: 1824230,
|
|
10179
10181
|
text: 1447704,
|
|
10180
10182
|
muted: 7566452,
|
|
@@ -10255,13 +10257,13 @@ const BOARD_THEME_DATA = {
|
|
|
10255
10257
|
"neta-pixel-dark": {
|
|
10256
10258
|
colorScheme: "dark",
|
|
10257
10259
|
palette: {
|
|
10258
|
-
bg:
|
|
10259
|
-
surface:
|
|
10260
|
-
hover:
|
|
10261
|
-
border:
|
|
10260
|
+
bg: 1118739,
|
|
10261
|
+
surface: 1842463,
|
|
10262
|
+
hover: 2237220,
|
|
10263
|
+
border: 2763565,
|
|
10262
10264
|
brand: 1824230,
|
|
10263
|
-
text:
|
|
10264
|
-
muted:
|
|
10265
|
+
text: 16185078,
|
|
10266
|
+
muted: 9079436,
|
|
10265
10267
|
rare: 1824230,
|
|
10266
10268
|
epic: 1824230,
|
|
10267
10269
|
legendary: 16766287
|
|
@@ -10270,47 +10272,47 @@ const BOARD_THEME_DATA = {
|
|
|
10270
10272
|
brand: {
|
|
10271
10273
|
stroke: 16185078,
|
|
10272
10274
|
fill: 16185078,
|
|
10273
|
-
label:
|
|
10275
|
+
label: 16185078
|
|
10274
10276
|
},
|
|
10275
10277
|
neutral: {
|
|
10276
|
-
stroke:
|
|
10277
|
-
fill:
|
|
10278
|
-
label:
|
|
10278
|
+
stroke: 9079436,
|
|
10279
|
+
fill: 9079436,
|
|
10280
|
+
label: 16185078
|
|
10279
10281
|
},
|
|
10280
10282
|
black: {
|
|
10281
10283
|
stroke: 0,
|
|
10282
10284
|
fill: 0,
|
|
10283
|
-
label:
|
|
10285
|
+
label: 16185078
|
|
10284
10286
|
},
|
|
10285
10287
|
white: {
|
|
10286
10288
|
stroke: 16777215,
|
|
10287
10289
|
fill: 16777215,
|
|
10288
|
-
label:
|
|
10290
|
+
label: 16185078
|
|
10289
10291
|
},
|
|
10290
10292
|
blue: {
|
|
10291
10293
|
stroke: 6010853,
|
|
10292
10294
|
fill: 6010853,
|
|
10293
|
-
label:
|
|
10295
|
+
label: 16185078
|
|
10294
10296
|
},
|
|
10295
10297
|
green: {
|
|
10296
10298
|
stroke: 9683613,
|
|
10297
10299
|
fill: 9683613,
|
|
10298
|
-
label:
|
|
10300
|
+
label: 16185078
|
|
10299
10301
|
},
|
|
10300
10302
|
amber: {
|
|
10301
10303
|
stroke: 14264410,
|
|
10302
10304
|
fill: 14264410,
|
|
10303
|
-
label:
|
|
10305
|
+
label: 16185078
|
|
10304
10306
|
},
|
|
10305
10307
|
violet: {
|
|
10306
10308
|
stroke: 11441117,
|
|
10307
10309
|
fill: 11441117,
|
|
10308
|
-
label:
|
|
10310
|
+
label: 16185078
|
|
10309
10311
|
},
|
|
10310
10312
|
rose: {
|
|
10311
10313
|
stroke: 15043210,
|
|
10312
10314
|
fill: 15043210,
|
|
10313
|
-
label:
|
|
10315
|
+
label: 16185078
|
|
10314
10316
|
}
|
|
10315
10317
|
},
|
|
10316
10318
|
style: {
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { normalizeAppDomainHostname } from "@neta-art/cohub";
|
|
2
|
+
import { createClient } from "../client.js";
|
|
3
|
+
import { getAppByRef } from "../app-ref.js";
|
|
4
|
+
import { error, handleHttp, json as outJson, jsonRequested, ok, table } from "../output.js";
|
|
5
|
+
async function confirm(question, opts, hint) {
|
|
6
|
+
if (opts.yes)
|
|
7
|
+
return;
|
|
8
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
9
|
+
return error("Confirmation required", hint);
|
|
10
|
+
process.stdout.write(`${question} [y/N] `);
|
|
11
|
+
const chunks = [];
|
|
12
|
+
for await (const chunk of process.stdin) {
|
|
13
|
+
chunks.push(chunk);
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
const answer = Buffer.concat(chunks).toString().trim().toLowerCase();
|
|
17
|
+
if (answer !== "y" && answer !== "yes")
|
|
18
|
+
return error("Cancelled");
|
|
19
|
+
}
|
|
20
|
+
async function findDomain(client, appId, ref) {
|
|
21
|
+
const { domains } = await client.apps.listDomains(appId);
|
|
22
|
+
const target = normalizeAppDomainHostname(ref) ?? ref.trim().toLowerCase();
|
|
23
|
+
const domain = domains.find((item) => item.id === ref || item.hostname === target);
|
|
24
|
+
return domain ?? error(`Domain not found: ${ref}`, "Run `cohub apps domains ls <app>` to see the App's domains.");
|
|
25
|
+
}
|
|
26
|
+
const info = (message) => console.log(message);
|
|
27
|
+
function printDomain(domain) {
|
|
28
|
+
table([{
|
|
29
|
+
hostname: domain.hostname,
|
|
30
|
+
status: domain.status,
|
|
31
|
+
certificate: domain.certificateStatus ?? "-",
|
|
32
|
+
error: domain.error?.message ?? "",
|
|
33
|
+
}], [
|
|
34
|
+
{ key: "hostname", label: "Hostname" },
|
|
35
|
+
{ key: "status", label: "Status" },
|
|
36
|
+
{ key: "certificate", label: "Certificate" },
|
|
37
|
+
{ key: "error", label: "Error" },
|
|
38
|
+
]);
|
|
39
|
+
if (domain.status === "active")
|
|
40
|
+
return;
|
|
41
|
+
info("Add these DNS records at your DNS provider:");
|
|
42
|
+
table(domain.dnsRecords.map((record) => ({
|
|
43
|
+
...record,
|
|
44
|
+
state: record.satisfied === true ? "ok" : record.satisfied === false ? "missing" : "-",
|
|
45
|
+
})), [
|
|
46
|
+
{ key: "type", label: "Type" },
|
|
47
|
+
{ key: "name", label: "Name" },
|
|
48
|
+
{ key: "value", label: "Value" },
|
|
49
|
+
{ key: "state", label: "State" },
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
export function registerAppDomains(appsCmd) {
|
|
53
|
+
const domainsCmd = appsCmd.command("domains").description("Custom domains for published Apps");
|
|
54
|
+
domainsCmd
|
|
55
|
+
.command("list <app>")
|
|
56
|
+
.alias("ls")
|
|
57
|
+
.description("List the App's custom domains")
|
|
58
|
+
.option("--json", "Output as JSON")
|
|
59
|
+
.action(async (appRef, opts) => {
|
|
60
|
+
const client = createClient();
|
|
61
|
+
try {
|
|
62
|
+
const detail = await getAppByRef(client, appRef);
|
|
63
|
+
const result = await client.apps.listDomains(detail.app.id);
|
|
64
|
+
if (jsonRequested(opts))
|
|
65
|
+
return outJson(result);
|
|
66
|
+
if (!result.enabled && result.domains.length === 0)
|
|
67
|
+
return info("Custom domains are not enabled on this deployment.");
|
|
68
|
+
if (result.domains.length === 0)
|
|
69
|
+
return info(`No custom domain. Add one with \`cohub apps domains add ${appRef} <hostname>\` ($${result.priceUsd}, one-time).`);
|
|
70
|
+
result.domains.forEach(printDomain);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
handleHttp(e);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
domainsCmd
|
|
77
|
+
.command("add <app> <hostname>")
|
|
78
|
+
.description("Bind a custom domain; charged once when it goes live")
|
|
79
|
+
.option("-y, --yes", "Confirm the one-time charge")
|
|
80
|
+
.option("--json", "Output as JSON")
|
|
81
|
+
.action(async (appRef, hostname, opts) => {
|
|
82
|
+
const client = createClient();
|
|
83
|
+
try {
|
|
84
|
+
const detail = await getAppByRef(client, appRef);
|
|
85
|
+
const { priceUsd } = await client.apps.listDomains(detail.app.id);
|
|
86
|
+
await confirm(`Binding ${hostname} costs $${priceUsd}, charged once when the domain goes live. Continue?`, opts, `Pass --yes to accept the one-time $${priceUsd} charge.`);
|
|
87
|
+
const { domain } = await client.apps.addDomain(detail.app.id, hostname);
|
|
88
|
+
if (jsonRequested(opts))
|
|
89
|
+
return outJson(domain);
|
|
90
|
+
ok(`Domain added: ${domain.hostname}`);
|
|
91
|
+
printDomain(domain);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
handleHttp(e);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
domainsCmd
|
|
98
|
+
.command("check <app> <domain>")
|
|
99
|
+
.description("Check DNS and certificate status now")
|
|
100
|
+
.option("--json", "Output as JSON")
|
|
101
|
+
.action(async (appRef, domainRef, opts) => {
|
|
102
|
+
const client = createClient();
|
|
103
|
+
try {
|
|
104
|
+
const detail = await getAppByRef(client, appRef);
|
|
105
|
+
const target = await findDomain(client, detail.app.id, domainRef);
|
|
106
|
+
const { domain } = await client.apps.checkDomain(detail.app.id, target.id);
|
|
107
|
+
if (jsonRequested(opts))
|
|
108
|
+
return outJson(domain);
|
|
109
|
+
printDomain(domain);
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
handleHttp(e);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
domainsCmd
|
|
116
|
+
.command("rm <app> <domain>")
|
|
117
|
+
.alias("remove")
|
|
118
|
+
.description("Remove a custom domain")
|
|
119
|
+
.option("-y, --yes", "Confirm removal")
|
|
120
|
+
.action(async (appRef, domainRef, opts) => {
|
|
121
|
+
const client = createClient();
|
|
122
|
+
try {
|
|
123
|
+
const detail = await getAppByRef(client, appRef);
|
|
124
|
+
const target = await findDomain(client, detail.app.id, domainRef);
|
|
125
|
+
await confirm(`Remove ${target.hostname}? The one-time charge is not refunded.`, opts, "Pass --yes to remove the domain.");
|
|
126
|
+
const result = await client.apps.removeDomain(detail.app.id, target.id);
|
|
127
|
+
ok(result.domain ? `Removing ${target.hostname}; its certificate is being released` : `Domain removed: ${target.hostname}`);
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
handleHttp(e);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
package/dist/commands/apps.js
CHANGED
|
@@ -9,6 +9,7 @@ import { getAppByRef, parseAppRef } from "../app-ref.js";
|
|
|
9
9
|
import { checkAppTarget } from "../app-target.js";
|
|
10
10
|
import { putBytes, putLocalFile } from "../http-put.js";
|
|
11
11
|
import { registerAppCommerce } from "./app-commerce.js";
|
|
12
|
+
import { registerAppDomains } from "./app-domains.js";
|
|
12
13
|
import { collectPublicUpload } from "./public.js";
|
|
13
14
|
const APP_STATUSES = ["published", "disabled"];
|
|
14
15
|
const APP_VISIBILITIES = ["public", "space"];
|
|
@@ -722,6 +723,7 @@ export function registerApps(program) {
|
|
|
722
723
|
}
|
|
723
724
|
});
|
|
724
725
|
registerAppCommerce(appsCmd);
|
|
726
|
+
registerAppDomains(appsCmd);
|
|
725
727
|
// ── Viewer grants ─────────────────────────────────────────────────────────
|
|
726
728
|
appsCmd
|
|
727
729
|
.command("authorize <app>")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neta-art/cohub-cli",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.12.0",
|
|
4
4
|
"description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"NOTICE"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@neta-art/cohub": "12.
|
|
21
|
+
"@neta-art/cohub": "12.5.0",
|
|
22
22
|
"@neta-art/generation": "^0.1.40",
|
|
23
23
|
"commander": "^15.0.0",
|
|
24
24
|
"sharp": "^0.35.4",
|