@neta-art/cohub-cli 4.0.0 → 6.0.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 -51
- package/dist/app-download.d.ts +11 -0
- package/dist/{work-download.js → app-download.js} +23 -23
- package/dist/app-ref.d.ts +5 -0
- package/dist/app-ref.js +8 -0
- package/dist/board-export.js +5 -5
- package/dist/commands/app-commerce.d.ts +2 -0
- package/dist/commands/{work-commerce.js → app-commerce.js} +27 -27
- package/dist/commands/apps.d.ts +4 -0
- package/dist/commands/{works.js → apps.js} +136 -127
- package/dist/commands/board-domain.js +2 -0
- package/dist/commands/boards/animation.js +26 -21
- package/dist/commands/boards/appearance.js +28 -24
- package/dist/commands/boards/context.d.ts +17 -1
- package/dist/commands/boards/context.js +38 -1
- package/dist/commands/boards/examples.d.ts +4 -0
- package/dist/commands/boards/examples.js +224 -0
- package/dist/commands/boards/items.js +12 -16
- package/dist/commands/boards/nodes.js +5 -8
- package/dist/commands/boards.d.ts +6 -11
- package/dist/commands/boards.js +40 -140
- package/dist/commands/cron-jobs.js +1 -1
- package/dist/commands/desktop.d.ts +3 -0
- package/dist/commands/desktop.js +219 -0
- package/dist/commands/profile.js +5 -5
- package/dist/commands/tasks.js +1 -1
- package/dist/index.js +7 -6
- package/package.json +2 -2
- package/dist/commands/ui.d.ts +0 -2
- package/dist/commands/ui.js +0 -199
- package/dist/commands/work-commerce.d.ts +0 -2
- package/dist/commands/works.d.ts +0 -4
- package/dist/work-download.d.ts +0 -11
- package/dist/work-ref.d.ts +0 -5
- package/dist/work-ref.js +0 -8
package/dist/commands/ui.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { HttpError, } from "@neta-art/cohub";
|
|
3
|
-
import { parseWorkRef, UI_COMMAND_DEFAULT_TIMEOUT_MS, UI_COMMAND_MAX_TIMEOUT_MS, } from "@neta-art/cohub";
|
|
4
|
-
import { createClient } from "../client.js";
|
|
5
|
-
import { error, handleHttp, json as outJson, jsonRequested, ok } from "../output.js";
|
|
6
|
-
import { getWorkByRef } from "../work-ref.js";
|
|
7
|
-
const FILE_SCHEME = "file://";
|
|
8
|
-
const WORK_SCHEME = "work://";
|
|
9
|
-
function optionalSpaceId(command) {
|
|
10
|
-
let current = command;
|
|
11
|
-
while (current) {
|
|
12
|
-
const opts = current.opts();
|
|
13
|
-
if (typeof opts.space === "string" && opts.space.trim())
|
|
14
|
-
return opts.space.trim();
|
|
15
|
-
current = current.parent ?? null;
|
|
16
|
-
}
|
|
17
|
-
return process.env.COHUB_SPACE_ID?.trim() || undefined;
|
|
18
|
-
}
|
|
19
|
-
function parseFilePath(value) {
|
|
20
|
-
const path = value.slice(FILE_SCHEME.length).trim();
|
|
21
|
-
if (!path ||
|
|
22
|
-
path.startsWith("/") ||
|
|
23
|
-
path.includes("\0") ||
|
|
24
|
-
path.split("/").some((segment) => segment === "..") ||
|
|
25
|
-
path.includes("\\")) {
|
|
26
|
-
return error("Invalid file path", "Use a relative Space path after file://.");
|
|
27
|
-
}
|
|
28
|
-
return path;
|
|
29
|
-
}
|
|
30
|
-
function hasFileScheme(value) {
|
|
31
|
-
return value.toLowerCase().startsWith(FILE_SCHEME);
|
|
32
|
-
}
|
|
33
|
-
function hasWorkScheme(value) {
|
|
34
|
-
return value.toLowerCase().startsWith(WORK_SCHEME);
|
|
35
|
-
}
|
|
36
|
-
function readCallInput(opts) {
|
|
37
|
-
if (opts.data !== undefined && opts.input !== undefined) {
|
|
38
|
-
return error("Conflicting input", "Use either --data or --input, not both.");
|
|
39
|
-
}
|
|
40
|
-
const raw = opts.data !== undefined
|
|
41
|
-
? opts.data
|
|
42
|
-
: opts.input !== undefined
|
|
43
|
-
? opts.input === "-"
|
|
44
|
-
? readFileSync(0, "utf-8")
|
|
45
|
-
: readFileSync(opts.input, "utf-8")
|
|
46
|
-
: undefined;
|
|
47
|
-
if (raw === undefined)
|
|
48
|
-
return undefined;
|
|
49
|
-
try {
|
|
50
|
-
return JSON.parse(raw);
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return error("Invalid input", "Call input must be valid JSON.");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function parseTimeout(value) {
|
|
57
|
-
if (!value)
|
|
58
|
-
return UI_COMMAND_DEFAULT_TIMEOUT_MS;
|
|
59
|
-
const parsed = Math.floor(Number(value));
|
|
60
|
-
if (!Number.isFinite(parsed) || parsed <= 0 || parsed > UI_COMMAND_MAX_TIMEOUT_MS) {
|
|
61
|
-
return error("Invalid timeout", `--timeout-ms must be between 1 and ${UI_COMMAND_MAX_TIMEOUT_MS} milliseconds.`);
|
|
62
|
-
}
|
|
63
|
-
return parsed;
|
|
64
|
-
}
|
|
65
|
-
async function resolveWorkTarget(client, ref) {
|
|
66
|
-
const normalized = hasWorkScheme(ref) ? ref.slice(WORK_SCHEME.length) : ref;
|
|
67
|
-
const parsed = parseWorkRef(normalized);
|
|
68
|
-
const detail = await getWorkByRef(client, normalized);
|
|
69
|
-
return {
|
|
70
|
-
kind: "work",
|
|
71
|
-
workId: detail.work.id,
|
|
72
|
-
label: detail.work.slug,
|
|
73
|
-
launch: {
|
|
74
|
-
...(parsed.search ? { search: parsed.search } : {}),
|
|
75
|
-
...(parsed.hash ? { hash: parsed.hash } : {}),
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
async function resolvePreviewTarget(client, command, value) {
|
|
80
|
-
if (hasFileScheme(value))
|
|
81
|
-
return { kind: "file", path: parseFilePath(value) };
|
|
82
|
-
if (hasWorkScheme(value))
|
|
83
|
-
return resolveWorkTarget(client, value);
|
|
84
|
-
const spaceId = optionalSpaceId(command);
|
|
85
|
-
if (spaceId) {
|
|
86
|
-
try {
|
|
87
|
-
await client.space(spaceId).files.read(value);
|
|
88
|
-
return { kind: "file", path: value };
|
|
89
|
-
}
|
|
90
|
-
catch (cause) {
|
|
91
|
-
if (!(cause instanceof HttpError) || cause.status !== 404)
|
|
92
|
-
throw cause;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return resolveWorkTarget(client, value);
|
|
96
|
-
}
|
|
97
|
-
function reportDispatch(record) {
|
|
98
|
-
if (record.status !== "pending") {
|
|
99
|
-
reportOutcome(record, Boolean(record.command.request));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
ok(`UI command dispatched (${record.commandId})`);
|
|
103
|
-
}
|
|
104
|
-
function reportOutcome(record, called) {
|
|
105
|
-
if (record.status === "applied") {
|
|
106
|
-
ok(called ? "Work preview shown and method called" : "Preview shown");
|
|
107
|
-
if (record.result !== undefined) {
|
|
108
|
-
console.log(typeof record.result === "string" ? record.result : JSON.stringify(record.result, null, 2));
|
|
109
|
-
}
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
error(`UI command ${record.status}`, record.error?.message ?? "The Cohub frontend did not apply this command.");
|
|
113
|
-
}
|
|
114
|
-
export function registerUi(program) {
|
|
115
|
-
const ui = program
|
|
116
|
-
.command("ui")
|
|
117
|
-
.description("Drive the Cohub frontend that started this work")
|
|
118
|
-
.addHelpText("after", `
|
|
119
|
-
Commands reach only the frontend instance that originated the current chat,
|
|
120
|
-
resolved from request provenance. Nothing else can be targeted.
|
|
121
|
-
|
|
122
|
-
Examples:
|
|
123
|
-
cohub ui preview <work-or-file>
|
|
124
|
-
cohub ui preview file://src/main.ts
|
|
125
|
-
cohub ui preview work://alice/studio/launch
|
|
126
|
-
cohub ui preview alice/studio/launch
|
|
127
|
-
cohub ui preview https://cohub.live/alice/studio/w/launch?view=timeline
|
|
128
|
-
cohub ui preview <work-id> --call selection.get
|
|
129
|
-
cohub ui preview <work-id> --call board.focus --data '{"nodeId":"n1"}'
|
|
130
|
-
`);
|
|
131
|
-
const preview = ui
|
|
132
|
-
.command("preview <work-or-file>")
|
|
133
|
-
.description("Show a file or Work preview tab, optionally calling a Work method")
|
|
134
|
-
.option("--call <method>", "Method the Work registered via client.work.surface.handle()")
|
|
135
|
-
.option("--data <json>", "Inline JSON input for --call")
|
|
136
|
-
.option("-i, --input <file>", "JSON input file for --call; use - for stdin")
|
|
137
|
-
.option("--client <clientId>", "Target a specific frontend instance of your account")
|
|
138
|
-
.option("--command-id <id>", "Stable id so retries never dispatch twice")
|
|
139
|
-
.option("--no-wait", "Dispatch the command and exit without waiting for a result")
|
|
140
|
-
.option("--timeout-ms <ms>", `How long to wait for the frontend (default: ${UI_COMMAND_DEFAULT_TIMEOUT_MS}; max: ${UI_COMMAND_MAX_TIMEOUT_MS})`)
|
|
141
|
-
.option("--json", "Output as JSON")
|
|
142
|
-
.action(async (work, opts) => {
|
|
143
|
-
const callInput = opts.call ? readCallInput(opts) : undefined;
|
|
144
|
-
if (!opts.call && (opts.data !== undefined || opts.input !== undefined)) {
|
|
145
|
-
return error("Missing --call", "--data and --input only apply together with --call.");
|
|
146
|
-
}
|
|
147
|
-
if (opts.noWait && opts.timeoutMs !== undefined) {
|
|
148
|
-
return error("Conflicting wait options", "Use either --no-wait or --timeout-ms, not both.");
|
|
149
|
-
}
|
|
150
|
-
const timeoutMs = parseTimeout(opts.timeoutMs);
|
|
151
|
-
const client = createClient();
|
|
152
|
-
try {
|
|
153
|
-
const target = await resolvePreviewTarget(client, preview, work);
|
|
154
|
-
if (target.kind === "file" && opts.call) {
|
|
155
|
-
return error("Unsupported option", "--call only applies to Work previews.");
|
|
156
|
-
}
|
|
157
|
-
const request = opts.call
|
|
158
|
-
? { method: opts.call, ...(callInput === undefined ? {} : { input: callInput }) }
|
|
159
|
-
: undefined;
|
|
160
|
-
const input = {
|
|
161
|
-
command: {
|
|
162
|
-
type: "preview.show",
|
|
163
|
-
preview: target.kind === "file"
|
|
164
|
-
? target
|
|
165
|
-
: {
|
|
166
|
-
kind: "work",
|
|
167
|
-
workId: target.workId,
|
|
168
|
-
label: target.label,
|
|
169
|
-
...(target.launch.search || target.launch.hash ? { launch: target.launch } : {}),
|
|
170
|
-
},
|
|
171
|
-
...(request ? { request } : {}),
|
|
172
|
-
},
|
|
173
|
-
...(opts.client ? { targetClientId: opts.client } : {}),
|
|
174
|
-
...(opts.commandId ? { commandId: opts.commandId } : {}),
|
|
175
|
-
};
|
|
176
|
-
const record = opts.noWait
|
|
177
|
-
? (await client.ui.create(input)).command
|
|
178
|
-
: await client.ui.run(input, { timeoutMs });
|
|
179
|
-
if (jsonRequested(opts))
|
|
180
|
-
return outJson(record);
|
|
181
|
-
if (opts.noWait)
|
|
182
|
-
return reportDispatch(record);
|
|
183
|
-
reportOutcome(record, Boolean(request));
|
|
184
|
-
}
|
|
185
|
-
catch (e) {
|
|
186
|
-
if (e instanceof Error && e.name === "WorkRefParseError")
|
|
187
|
-
return error(e.message);
|
|
188
|
-
handleHttp(e);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
preview.addHelpText("after", `
|
|
192
|
-
Notes:
|
|
193
|
-
- Use file:// and work:// to make the target explicit.
|
|
194
|
-
- A plain target checks the current Space for a file before resolving a Work.
|
|
195
|
-
- Showing a preview is idempotent; repeating it re-activates the same tab.
|
|
196
|
-
- --call waits for the Work to announce readiness, then invokes the method.
|
|
197
|
-
- Which methods exist is up to the Work author.
|
|
198
|
-
`);
|
|
199
|
-
}
|
package/dist/commands/works.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { type CohubHttpClient, type WorkViewStatsResponse } from "@neta-art/cohub";
|
|
2
|
-
import type { Command } from "commander";
|
|
3
|
-
export declare function getWorkStatsByRef(client: CohubHttpClient, work: string): Promise<WorkViewStatsResponse>;
|
|
4
|
-
export declare function registerWorks(program: Command): void;
|
package/dist/work-download.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { WorkGetResponse } from "@neta-art/cohub";
|
|
2
|
-
type DownloadResult = {
|
|
3
|
-
workId: string;
|
|
4
|
-
version: number;
|
|
5
|
-
kind: "file" | "directory";
|
|
6
|
-
output: string;
|
|
7
|
-
files: number;
|
|
8
|
-
bytes: number;
|
|
9
|
-
};
|
|
10
|
-
export declare function downloadWork(detail: WorkGetResponse, outputOption?: string, fetcher?: typeof fetch): Promise<DownloadResult>;
|
|
11
|
-
export {};
|
package/dist/work-ref.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { CohubHttpClient, ParsedWorkRef, WorkGetResponse } from "@neta-art/cohub";
|
|
2
|
-
import { formatWorkRef, parseWorkRef } from "@neta-art/cohub";
|
|
3
|
-
export type { ParsedWorkRef };
|
|
4
|
-
export { formatWorkRef, parseWorkRef };
|
|
5
|
-
export declare function getWorkByRef(client: CohubHttpClient, input: string): Promise<WorkGetResponse>;
|
package/dist/work-ref.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { formatWorkRef, parseWorkRef } from "@neta-art/cohub";
|
|
2
|
-
export { formatWorkRef, parseWorkRef };
|
|
3
|
-
export function getWorkByRef(client, input) {
|
|
4
|
-
const ref = parseWorkRef(input);
|
|
5
|
-
return "id" in ref
|
|
6
|
-
? client.works.get(ref.id)
|
|
7
|
-
: client.works.getBySlug(ref.username, ref.spaceSlug, ref.workSlug);
|
|
8
|
-
}
|