@b3os/cli 0.0.0-stage → 0.0.1

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.
@@ -0,0 +1,205 @@
1
+ // b3os scrape | screenshot | video: vision.scrape, render.createScreenshot and render.createVideo.
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { EXIT, intFlag, pairs, parse, UsageError } from "../ctx.js";
4
+ const FORMATS = ["markdown", "html", "raw_html", "text", "links", "metadata", "screenshot", "json"];
5
+ export async function scrape(ctx, argv) {
6
+ const a = parse(argv, {
7
+ format: { type: "string", short: "f", multiple: true },
8
+ "all-content": { type: "boolean" },
9
+ engine: { type: "string" },
10
+ "wait-for": { type: "string" },
11
+ "max-age": { type: "string" },
12
+ "no-cache": { type: "boolean" },
13
+ header: { type: "string", multiple: true },
14
+ profile: { type: "string" },
15
+ out: { type: "string", short: "o" },
16
+ });
17
+ ctx.applyGlobals(a.values);
18
+ const url = a.positionals[0];
19
+ if (!url || a.values.help) {
20
+ ctx.out("usage: b3os scrape <url> [--format markdown|html|raw_html|text|links|json ...] [--all-content]\n" +
21
+ " [--engine auto|fetch|browser] [--wait-for MS] [--max-age MS|--no-cache]\n" +
22
+ " [--header K=V ...] [--profile NAME] [--out FILE] [--json]");
23
+ return url ? EXIT.OK : EXIT.USAGE;
24
+ }
25
+ const formats = (a.values.format ?? ["markdown"]).flatMap((f) => f.split(","));
26
+ for (const f of formats) {
27
+ if (!FORMATS.includes(f))
28
+ throw new UsageError(`unknown format "${f}" (${FORMATS.join(", ")})`);
29
+ }
30
+ const body = { url, formats: formats };
31
+ if (a.values["all-content"])
32
+ body.only_main_content = false;
33
+ if (typeof a.values.engine === "string")
34
+ body.engine = a.values.engine;
35
+ const wait = intFlag(a.values["wait-for"], "--wait-for");
36
+ if (wait !== undefined)
37
+ body.wait_for_ms = wait;
38
+ const maxAge = a.values["no-cache"] ? 0 : intFlag(a.values["max-age"], "--max-age");
39
+ if (maxAge !== undefined)
40
+ body.max_age_ms = maxAge;
41
+ if (a.values.header)
42
+ body.headers = pairs(a.values.header, "--header");
43
+ if (typeof a.values.profile === "string")
44
+ body.profile = a.values.profile;
45
+ const { data: page, response } = await ctx.client().vision.scrape(body).withResponse();
46
+ const single = formats.length === 1 ? formats[0] : undefined;
47
+ let text;
48
+ if (single === "markdown" || single === "html" || single === "raw_html" || single === "text") {
49
+ text = page[single] ?? "";
50
+ }
51
+ else if (single === "links") {
52
+ text = (page.links ?? []).join("\n");
53
+ }
54
+ if (typeof a.values.out === "string") {
55
+ writeFileSync(a.values.out, ctx.json || text === undefined ? JSON.stringify(page, null, 2) : text);
56
+ ctx.info(`Wrote ${a.values.out}`);
57
+ }
58
+ else if (ctx.json || text === undefined) {
59
+ ctx.printJson(page);
60
+ }
61
+ else {
62
+ ctx.out(text);
63
+ }
64
+ const t = response.timing.total_ms;
65
+ ctx.info(`${page.status_code} ${page.final_url} via ${page.tier} (cache ${page.cache.state})${t === null ? "" : `, server ${t} ms`}`);
66
+ return EXIT.OK;
67
+ }
68
+ export async function screenshot(ctx, argv) {
69
+ const a = parse(argv, {
70
+ out: { type: "string", short: "o" },
71
+ format: { type: "string" },
72
+ width: { type: "string" },
73
+ height: { type: "string" },
74
+ dpr: { type: "string" },
75
+ "full-page": { type: "boolean" },
76
+ selector: { type: "string" },
77
+ background: { type: "string" },
78
+ frame: { type: "string" },
79
+ theme: { type: "string" },
80
+ "wait-for": { type: "string" },
81
+ hide: { type: "string", multiple: true },
82
+ profile: { type: "string" },
83
+ html: { type: "string" },
84
+ });
85
+ ctx.applyGlobals(a.values);
86
+ const url = a.positionals[0];
87
+ if ((!url && !a.values.html) || a.values.help) {
88
+ ctx.out("usage: b3os screenshot <url> [--out FILE] [--format webp|png|jpeg] [--width W --height H] [--dpr 1|2|3]\n" +
89
+ " [--full-page] [--selector CSS] [--background PRESET] [--frame PRESET]\n" +
90
+ " [--theme light|dark] [--wait-for MS] [--hide CSS ...] [--html FILE] [--json]");
91
+ return url || a.values.html ? EXIT.OK : EXIT.USAGE;
92
+ }
93
+ const format = a.values.format ?? "png";
94
+ const body = { format };
95
+ if (url)
96
+ body.url = url;
97
+ if (typeof a.values.html === "string")
98
+ body.html = readFileSync(a.values.html, "utf8");
99
+ const w = intFlag(a.values.width, "--width");
100
+ const h = intFlag(a.values.height, "--height");
101
+ if (w !== undefined || h !== undefined)
102
+ body.viewport = { width: w ?? 1600, height: h ?? 900 };
103
+ const dpr = intFlag(a.values.dpr, "--dpr");
104
+ if (dpr !== undefined)
105
+ body.dpr = dpr;
106
+ if (a.values["full-page"])
107
+ body.full_page = true;
108
+ if (typeof a.values.selector === "string")
109
+ body.target = { selector: a.values.selector };
110
+ if (a.values.background || a.values.frame) {
111
+ body.style = {};
112
+ if (typeof a.values.background === "string")
113
+ body.style.background = a.values.background;
114
+ if (typeof a.values.frame === "string")
115
+ body.style.frame = a.values.frame;
116
+ }
117
+ if (typeof a.values.theme === "string")
118
+ body.theme = a.values.theme;
119
+ const wait = intFlag(a.values["wait-for"], "--wait-for");
120
+ if (wait !== undefined)
121
+ body.wait_for_ms = wait;
122
+ if (a.values.hide)
123
+ body.hide = a.values.hide;
124
+ if (typeof a.values.profile === "string")
125
+ body.profile = a.values.profile;
126
+ const b3 = ctx.client();
127
+ if (ctx.json) {
128
+ ctx.printJson(await b3.render.createScreenshot(body));
129
+ return EXIT.OK;
130
+ }
131
+ const accept = format === "jpeg" ? "image/jpeg" : format === "webp" ? "image/webp" : "image/png";
132
+ const { data, response } = await b3.render.createScreenshot(body, { accept }).withResponse();
133
+ const out = typeof a.values.out === "string" ? a.values.out : `screenshot.${format === "jpeg" ? "jpg" : format}`;
134
+ writeFileSync(out, data);
135
+ const t = response.timing.total_ms;
136
+ ctx.out(out);
137
+ ctx.info(`${data.byteLength} bytes${t === null ? "" : `, server ${t} ms`}`);
138
+ return EXIT.OK;
139
+ }
140
+ function readJsonFile(path) {
141
+ const text = readFileSync(path, "utf8");
142
+ try {
143
+ return JSON.parse(text);
144
+ }
145
+ catch (e) {
146
+ throw new UsageError(`${path} is not JSON (${e.message}); video scripts are VideoCreateRequest JSON`);
147
+ }
148
+ }
149
+ export async function video(ctx, argv) {
150
+ const a = parse(argv, {
151
+ out: { type: "string", short: "o" },
152
+ "no-wait": { type: "boolean" },
153
+ kind: { type: "string" },
154
+ });
155
+ ctx.applyGlobals(a.values);
156
+ const file = a.positionals[0];
157
+ if (!file || a.values.help) {
158
+ ctx.out("usage: b3os video <script.json> [--out FILE] [--kind mp4|gif|poster|vtt] [--no-wait] [--json]\n" +
159
+ " script.json is a render video request (render.yaml VideoCreateRequest: source, beats, voice, style, ...)");
160
+ return file ? EXIT.OK : EXIT.USAGE;
161
+ }
162
+ const body = readJsonFile(file);
163
+ const b3 = ctx.client();
164
+ if (a.values["no-wait"]) {
165
+ const job = await b3.render.createVideo(body);
166
+ ctx.result(job, () => ctx.out(job.id));
167
+ return EXIT.OK;
168
+ }
169
+ const stream = b3.render.createVideo(body).events();
170
+ for await (const ev of stream) {
171
+ if (ctx.json)
172
+ ctx.printJsonLine(ev);
173
+ else
174
+ logVideoEvent(ctx, ev);
175
+ }
176
+ const done = await stream.result;
177
+ if (done.status !== "succeeded") {
178
+ ctx.warn(`video ${done.id} ${done.status}: ${done.error?.detail ?? ""}`);
179
+ return EXIT.FAILED;
180
+ }
181
+ const kind = a.values.kind ?? "mp4";
182
+ const art = done.result?.artifacts.find((x) => x.kind === kind);
183
+ if (!art?.url) {
184
+ ctx.warn(`video ${done.id} has no ${kind} artifact`);
185
+ return EXIT.FAILED;
186
+ }
187
+ const out = typeof a.values.out === "string" ? a.values.out : `${done.id}.${kind === "poster" ? "jpg" : kind}`;
188
+ const res = await fetch(art.url);
189
+ if (!res.ok)
190
+ throw new Error(`download of ${art.url} answered ${res.status}`);
191
+ writeFileSync(out, new Uint8Array(await res.arrayBuffer()));
192
+ if (!ctx.json)
193
+ ctx.out(out);
194
+ return EXIT.OK;
195
+ }
196
+ function logVideoEvent(ctx, ev) {
197
+ const e = ev;
198
+ if (e.type === "video.phase" && e.phase)
199
+ ctx.info(`${e.phase}...`);
200
+ else if (e.type === "job.progress" && e.progress)
201
+ ctx.info(`${e.progress.completed}/${e.progress.total ?? "?"}`);
202
+ else if (e.type.startsWith("job."))
203
+ ctx.info(e.type.slice(4));
204
+ }
205
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface StoredCredentials {
2
+ /** `b3os_pat_…` from the device login. */
3
+ token: string;
4
+ base_url: string;
5
+ org_id?: string;
6
+ project_id?: string;
7
+ scope?: string;
8
+ /** RFC 3339; when the token stops working. */
9
+ expires_at?: string | null;
10
+ created_at: string;
11
+ }
12
+ export declare function configDir(): string;
13
+ export declare function credentialsPath(): string;
14
+ export declare function loadCredentials(): StoredCredentials | null;
15
+ /**
16
+ * Writes the token to a new 0600 file next to the target and renames it over the old one, so the token is never
17
+ * in a file with wider permissions (an existing file keeps its mode under writeFileSync), and a crash leaves either
18
+ * the old file or the new one.
19
+ */
20
+ export declare function saveCredentials(c: StoredCredentials): string;
21
+ export declare function deleteCredentials(): boolean;
package/dist/config.js ADDED
@@ -0,0 +1,71 @@
1
+ // Stored login: `b3os login` keeps the device-flow token in $XDG_CONFIG_HOME/b3os/credentials.json (default
2
+ // ~/.config/b3os/), mode 0600 in a 0700 directory. B3OS_API_KEY and --api-key always win over it.
3
+ import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeSync, } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { dirname, join } from "node:path";
6
+ export function configDir() {
7
+ const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
8
+ return join(base, "b3os");
9
+ }
10
+ export function credentialsPath() {
11
+ return process.env.B3OS_CREDENTIALS_FILE || join(configDir(), "credentials.json");
12
+ }
13
+ export function loadCredentials() {
14
+ const p = credentialsPath();
15
+ if (!existsSync(p))
16
+ return null;
17
+ try {
18
+ const c = JSON.parse(readFileSync(p, "utf8"));
19
+ if (typeof c.token !== "string" || !c.token)
20
+ return null;
21
+ if (c.expires_at && Date.parse(c.expires_at) < Date.now())
22
+ return null;
23
+ return c;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ /**
30
+ * Writes the token to a new 0600 file next to the target and renames it over the old one, so the token is never
31
+ * in a file with wider permissions (an existing file keeps its mode under writeFileSync), and a crash leaves either
32
+ * the old file or the new one.
33
+ */
34
+ export function saveCredentials(c) {
35
+ const p = credentialsPath();
36
+ const dir = dirname(p);
37
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
38
+ if (!process.env.B3OS_CREDENTIALS_FILE) {
39
+ try {
40
+ chmodSync(dir, 0o700); // our own directory: tighten one that was created by hand or by an older version
41
+ }
42
+ catch {
43
+ // Not ours to change; the file itself is still 0600.
44
+ }
45
+ }
46
+ const tmp = `${p}.${process.pid}.${Date.now()}.tmp`;
47
+ const fd = openSync(tmp, "wx", 0o600);
48
+ try {
49
+ writeSync(fd, `${JSON.stringify(c, null, 2)}\n`);
50
+ fsyncSync(fd);
51
+ }
52
+ finally {
53
+ closeSync(fd);
54
+ }
55
+ try {
56
+ renameSync(tmp, p);
57
+ }
58
+ catch (e) {
59
+ rmSync(tmp, { force: true });
60
+ throw e;
61
+ }
62
+ return p;
63
+ }
64
+ export function deleteCredentials() {
65
+ const p = credentialsPath();
66
+ if (!existsSync(p))
67
+ return false;
68
+ rmSync(p);
69
+ return true;
70
+ }
71
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/ctx.d.ts ADDED
@@ -0,0 +1,112 @@
1
+ import { type ParseArgsConfig } from "node:util";
2
+ import { B3OS, type ClientOptions } from "@b3os/sdk";
3
+ /** Exit codes. Stable: scripts may rely on them (documented in packages/cli/README.md). */
4
+ export declare const EXIT: {
5
+ readonly OK: 0;
6
+ readonly ERROR: 1;
7
+ readonly USAGE: 2;
8
+ readonly AUTH: 3;
9
+ readonly NOT_FOUND: 4;
10
+ readonly INVALID: 5;
11
+ readonly LIMITED: 6;
12
+ readonly SERVER: 7;
13
+ readonly TIMEOUT: 8;
14
+ readonly CONNECTION: 9;
15
+ readonly FAILED: 10;
16
+ readonly INTERRUPTED: 130;
17
+ };
18
+ export declare class UsageError extends Error {
19
+ constructor(message: string);
20
+ }
21
+ /** Options every command takes. */
22
+ export declare const GLOBAL_OPTIONS: {
23
+ readonly json: {
24
+ readonly type: "boolean";
25
+ };
26
+ readonly yes: {
27
+ readonly type: "boolean";
28
+ readonly short: "y";
29
+ };
30
+ readonly quiet: {
31
+ readonly type: "boolean";
32
+ readonly short: "q";
33
+ };
34
+ readonly help: {
35
+ readonly type: "boolean";
36
+ readonly short: "h";
37
+ };
38
+ readonly "api-key": {
39
+ readonly type: "string";
40
+ };
41
+ readonly "base-url": {
42
+ readonly type: "string";
43
+ };
44
+ readonly timeout: {
45
+ readonly type: "string";
46
+ };
47
+ };
48
+ export type Options = NonNullable<ParseArgsConfig["options"]>;
49
+ export interface Parsed {
50
+ values: Record<string, string | boolean | string[] | boolean[] | undefined>;
51
+ positionals: string[];
52
+ }
53
+ export declare function parse(argv: string[], options?: Options): Parsed;
54
+ export interface Streams {
55
+ stdout: {
56
+ write(s: string | Uint8Array): unknown;
57
+ isTTY?: boolean;
58
+ };
59
+ stderr: {
60
+ write(s: string): unknown;
61
+ isTTY?: boolean;
62
+ };
63
+ stdin: NodeJS.ReadableStream & {
64
+ isTTY?: boolean;
65
+ };
66
+ }
67
+ export declare class Ctx {
68
+ json: boolean;
69
+ yes: boolean;
70
+ quiet: boolean;
71
+ apiKey: string | undefined;
72
+ baseUrl: string | undefined;
73
+ timeoutMs: number | undefined;
74
+ private cached;
75
+ readonly io: Streams;
76
+ /** Extra client options (tests). */
77
+ clientOptions: ClientOptions;
78
+ constructor(io: Streams);
79
+ applyGlobals(v: Parsed["values"]): void;
80
+ get isTTY(): boolean;
81
+ /** The API key in effect: --api-key, B3OS_API_KEY, then the stored login. */
82
+ credential(): {
83
+ key: string | null;
84
+ source: string;
85
+ baseUrl: string;
86
+ };
87
+ /**
88
+ * The base URL the user chose (--base-url, B3OS_BASE_URL, or a stored login's non-default host), else undefined.
89
+ * Only a chosen one is passed to the SDK: a base URL turns off its default-socket detection on a node.
90
+ */
91
+ configuredBaseUrl(): string | undefined;
92
+ client(): B3OS;
93
+ out(s: string): void;
94
+ /** Progress and notes go to stderr so stdout stays data. Silent with --quiet or --json. */
95
+ info(s: string): void;
96
+ warn(s: string): void;
97
+ printJson(v: unknown): void;
98
+ /** One JSON document per line (streams with --json). */
99
+ printJsonLine(v: unknown): void;
100
+ /** --json prints `data`; otherwise `human()` decides. */
101
+ result(data: unknown, human: () => void): void;
102
+ table(rows: Array<Record<string, unknown>>, columns: string[]): void;
103
+ /** Asks before a destructive action. Never prompts without a TTY: then --yes is required. */
104
+ confirm(question: string): Promise<boolean>;
105
+ }
106
+ export declare function exitCodeFor(e: unknown): number;
107
+ /** The error as printed: one readable line (plus validation items), or a JSON object with --json. */
108
+ export declare function renderError(e: unknown, json: boolean): string;
109
+ /** Reads `k=v` pairs (`--env A=1`). */
110
+ export declare function pairs(list: unknown, flag: string): Record<string, string>;
111
+ export declare function intFlag(v: unknown, flag: string): number | undefined;
112
+ export declare function jsonFlag(v: unknown, flag: string): unknown;