@botiverse/hands-cli 0.4.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 +71 -0
- package/dist/commands/apps.d.ts +7 -0
- package/dist/commands/apps.js +71 -0
- package/dist/commands/apps.js.map +1 -0
- package/dist/commands/builds.d.ts +14 -0
- package/dist/commands/builds.js +611 -0
- package/dist/commands/builds.js.map +1 -0
- package/dist/commands/deploy_tokens.d.ts +12 -0
- package/dist/commands/deploy_tokens.js +98 -0
- package/dist/commands/deploy_tokens.js.map +1 -0
- package/dist/commands/feedback.d.ts +7 -0
- package/dist/commands/feedback.js +141 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/login.d.ts +22 -0
- package/dist/commands/login.js +129 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/releases.d.ts +5 -0
- package/dist/commands/releases.js +200 -0
- package/dist/commands/releases.js.map +1 -0
- package/dist/commands/whoami.d.ts +5 -0
- package/dist/commands/whoami.js +43 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +25 -0
- package/dist/lib/api.js +126 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +22 -0
- package/dist/lib/config.js +71 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/env.d.ts +7 -0
- package/dist/lib/env.js +10 -0
- package/dist/lib/env.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @botiverse/hands-cli
|
|
2
|
+
|
|
3
|
+
Hands CLI — manage apps, builds, releases from the terminal.
|
|
4
|
+
|
|
5
|
+
Status: **alpha**. The npm package is public as `@botiverse/hands-cli`; v1 ships
|
|
6
|
+
`login`, `logout`, `whoami`, `apps list/get`, `builds list/get`, and
|
|
7
|
+
`builds publish-android`. Other commands listed in `docs/cli-reference.md` land
|
|
8
|
+
incrementally as backend endpoints become available.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @botiverse/hands-cli
|
|
14
|
+
hands --help
|
|
15
|
+
|
|
16
|
+
# Or run without installing globally:
|
|
17
|
+
npm exec --package @botiverse/hands-cli@0.3.2 -- hands --help
|
|
18
|
+
|
|
19
|
+
# Local repo development:
|
|
20
|
+
pnpm --filter @botiverse/hands-cli build
|
|
21
|
+
pnpm --filter @botiverse/hands-cli start -- whoami
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. Log in. The CLI prints a URL you must open in a browser.
|
|
28
|
+
hands login
|
|
29
|
+
|
|
30
|
+
# 2. Verify who you are.
|
|
31
|
+
hands whoami
|
|
32
|
+
|
|
33
|
+
# 3. List your apps.
|
|
34
|
+
hands apps list
|
|
35
|
+
|
|
36
|
+
# 4. List builds for an app (by slug or id).
|
|
37
|
+
hands builds list myapp-android
|
|
38
|
+
|
|
39
|
+
# 5. Publish an Android APK release.
|
|
40
|
+
hands builds publish-android raft-android \
|
|
41
|
+
--channel main \
|
|
42
|
+
--apk ./app-release.apk \
|
|
43
|
+
--version-name 1.0.3 \
|
|
44
|
+
--version-code 1000300
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## CI mode
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export QUIVER_API=https://quiver.oranix.io
|
|
51
|
+
export QUIVER_SESSION_COOKIE=... # paste from browser DevTools
|
|
52
|
+
hands whoami
|
|
53
|
+
hands builds list myapp-android
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## How auth works (v1)
|
|
57
|
+
|
|
58
|
+
Raft OAuth today only supports the browser-redirect flow with HttpOnly
|
|
59
|
+
cookies. The CLI can't intercept the redirect, so `hands login` asks
|
|
60
|
+
you to:
|
|
61
|
+
|
|
62
|
+
1. Open the printed URL in any browser.
|
|
63
|
+
2. Sign in with Raft.
|
|
64
|
+
3. Copy the `quiver_session` cookie value from DevTools.
|
|
65
|
+
4. Paste it back into the CLI.
|
|
66
|
+
|
|
67
|
+
The token is saved to `$XDG_CONFIG_HOME/quiver/auth.json` (mode 0600).
|
|
68
|
+
For CI, pass it via `QUIVER_SESSION_COOKIE` instead.
|
|
69
|
+
|
|
70
|
+
v2 will swap this for a true headless flow (Raft Device Flow or a
|
|
71
|
+
`--token-stdin` service-user mode). See `publish-tasks.md` P3.4.x.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quiver apps` — list / inspect apps in the caller's org.
|
|
3
|
+
*
|
|
4
|
+
* Wires GET /api/apps + GET /api/apps/:appId.
|
|
5
|
+
*/
|
|
6
|
+
import { apiRequest } from "../lib/api.js";
|
|
7
|
+
export function registerAppCommands(program) {
|
|
8
|
+
const apps = program.command("apps").description("Manage apps in your org.");
|
|
9
|
+
apps
|
|
10
|
+
.command("list")
|
|
11
|
+
.alias("ls")
|
|
12
|
+
.description("List apps in the current org.")
|
|
13
|
+
.option("--include-archived", "Include archived (soft-deleted) apps.", false)
|
|
14
|
+
.option("--json", "Output JSON.", false)
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
const res = await apiRequest("/api/apps", {
|
|
17
|
+
query: { include_archived: opts.includeArchived ? "1" : "0" },
|
|
18
|
+
});
|
|
19
|
+
if (opts.json) {
|
|
20
|
+
console.log(JSON.stringify(res, null, 2));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (res.apps.length === 0) {
|
|
24
|
+
console.log("No apps. Create one in the admin UI first.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(["SLUG", "PLATFORM", "ARCHIVED", "DEFAULT_CHANNEL", "ID"].join("\t"));
|
|
28
|
+
for (const a of res.apps) {
|
|
29
|
+
console.log([
|
|
30
|
+
a.slug,
|
|
31
|
+
a.platform,
|
|
32
|
+
a.archived ? "yes" : "no",
|
|
33
|
+
a.default_channel_slug ?? "—",
|
|
34
|
+
a.id.slice(0, 8),
|
|
35
|
+
].join("\t"));
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
apps
|
|
39
|
+
.command("get <appIdOrSlug>")
|
|
40
|
+
.description("Show details for a single app.")
|
|
41
|
+
.option("--json", "Output JSON.", false)
|
|
42
|
+
.action(async (appIdOrSlug, opts) => {
|
|
43
|
+
// The Worker endpoint accepts UUID; for slug we list + filter.
|
|
44
|
+
// Cheap heuristic: 36-char with dashes = UUID.
|
|
45
|
+
const isUuid = appIdOrSlug.length === 36 && appIdOrUuidDash(appIdOrSlug);
|
|
46
|
+
let id = appIdOrSlug;
|
|
47
|
+
if (!isUuid) {
|
|
48
|
+
const res = await apiRequest("/api/apps");
|
|
49
|
+
const match = res.apps.find((a) => a.slug === appIdOrSlug);
|
|
50
|
+
if (!match) {
|
|
51
|
+
console.error(`No app with slug '${appIdOrSlug}'.`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
id = match.id;
|
|
55
|
+
}
|
|
56
|
+
const app = await apiRequest(`/api/apps/${id}`);
|
|
57
|
+
if (opts.json) {
|
|
58
|
+
console.log(JSON.stringify(app, null, 2));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.log(`${app.name} (${app.platform})`);
|
|
62
|
+
console.log(` id: ${app.id}`);
|
|
63
|
+
console.log(` slug: ${app.slug}`);
|
|
64
|
+
console.log(` archived: ${app.archived ? "yes" : "no"}`);
|
|
65
|
+
console.log(` default_channel: ${app.default_channel_slug ?? "(none)"}`);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function appIdOrUuidDash(s) {
|
|
69
|
+
return s.split("-").length === 5;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `quiver builds` — list / inspect builds inside an app.
|
|
3
|
+
*
|
|
4
|
+
* Wires GET /api/apps/:appId/builds + GET /api/apps/:appId/builds/:buildId.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from "commander";
|
|
7
|
+
export declare function parseChangelogOptions(opts: {
|
|
8
|
+
changelog?: string | string[];
|
|
9
|
+
changelogFile?: string | string[];
|
|
10
|
+
}): string | null;
|
|
11
|
+
export declare function registerBuildCommands(program: Command): void;
|
|
12
|
+
export declare function inferElectronPlatform(filePath: string | undefined): string;
|
|
13
|
+
export declare function inferElectronFiletype(filePath: string): string;
|
|
14
|
+
export declare function inferIosFiletype(filePath: string): string;
|