@indigoai-us/hq-cli 5.11.0 → 5.12.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.
- package/CHANGELOG.md +59 -0
- package/dist/cli-version.d.ts +2 -0
- package/dist/cli-version.js +5 -0
- package/dist/commands/feedback.d.ts +16 -0
- package/dist/commands/feedback.js +98 -0
- package/dist/index.js +12 -3
- package/dist/sentry.js +4 -2
- package/dist/utils/breadcrumb-buffer.d.ts +4 -0
- package/dist/utils/breadcrumb-buffer.js +18 -0
- package/dist/utils/feedback-diagnostics.d.ts +22 -0
- package/dist/utils/feedback-diagnostics.js +95 -0
- package/dist/utils/vault-api.js +22 -4
- package/package.json +2 -1
- package/src/cli-version.ts +1 -0
- package/src/commands/feedback.test.ts +369 -0
- package/src/commands/feedback.ts +136 -0
- package/src/index.ts +11 -1
- package/src/sentry.ts +2 -0
- package/src/utils/breadcrumb-buffer.ts +18 -0
- package/src/utils/feedback-diagnostics.test.ts +172 -0
- package/src/utils/feedback-diagnostics.ts +115 -0
- package/src/utils/vault-api.test.ts +37 -1
- package/src/utils/vault-api.ts +20 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.12.1] — 2026-05-09
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **CREATED BY column in HQ Console Vault now populates for cloud-synced files.**
|
|
8
|
+
Pulls in `@indigoai-us/hq-cloud@5.11.3`, which stamps `created-by`,
|
|
9
|
+
`created-by-sub`, and `created-at` user metadata on every `PutObject` so the
|
|
10
|
+
vault listing's HEAD fan-out has identity to attribute. Files synced via
|
|
11
|
+
`hq cloud provision`, `hq files share`, and the watcher previously rendered
|
|
12
|
+
as `—` because only the Next.js upload route stamped author metadata.
|
|
13
|
+
|
|
14
|
+
## [5.12.0] — 2026-05-08
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`hq feedback` command group** — two subcommands `hq feedback bug` and
|
|
19
|
+
`hq feedback feature` let any logged-in user submit structured feedback without
|
|
20
|
+
leaving the terminal. Submissions are JWT-authenticated via the existing Cognito
|
|
21
|
+
session (no additional login step).
|
|
22
|
+
|
|
23
|
+
- **`--body-file <path>` flag** — pass a pre-written markdown file as the feedback
|
|
24
|
+
body. Multi-line input without shell quoting headaches. Use `--body-file -` to read
|
|
25
|
+
from stdin (useful for piped workflows). Body input is file-based by design (no
|
|
26
|
+
inline string flag).
|
|
27
|
+
|
|
28
|
+
- **`--company <slug>` flag (optional)** — attaches a company context to the submission.
|
|
29
|
+
Resolved automatically from `core/scripts/hq-session.sh get company_slug` inside the
|
|
30
|
+
`/feedback` skill; the flag is omitted when the slug is empty.
|
|
31
|
+
|
|
32
|
+
- **Diagnostics blob** — every submission includes a structured diagnostics payload
|
|
33
|
+
(`cliVersion`, `nodeVersion`, `os.platform`, `os.release`, `command` argv array,
|
|
34
|
+
`cwd`, `recentSentryBreadcrumbs`). Purely plain CLI/process context — no GHQ-OS-aware
|
|
35
|
+
identifiers.
|
|
36
|
+
|
|
37
|
+
- **Slack relay** — the vault-service backend best-effort posts a formatted card to
|
|
38
|
+
`#hq-feedback` after writing the DynamoDB row. Relay is fire-and-forget; Slack
|
|
39
|
+
failures do not affect the HTTP response.
|
|
40
|
+
|
|
41
|
+
### Example
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Interactive: title prompted if not supplied
|
|
45
|
+
hq feedback bug --title "search broken on mobile"
|
|
46
|
+
|
|
47
|
+
# Scripted: body from a pre-written file
|
|
48
|
+
hq feedback feature --title "dark mode" --body-file /tmp/feature-body.md
|
|
49
|
+
|
|
50
|
+
# Piped: read body from stdin
|
|
51
|
+
echo "Steps to reproduce: ..." | hq feedback bug --title "crash on login" --body-file -
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## [5.11.0] — 2026-05-07
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **`--personal` flag for `hq secrets`** — pin a secret to the per-user store rather
|
|
59
|
+
than the company store. See commit `b5ec9bd` ("release: hq-cli@5.11.0 — --personal
|
|
60
|
+
flag for secrets") for details.
|
|
61
|
+
|
|
3
62
|
## [5.10.0] — 2026-05-04
|
|
4
63
|
|
|
5
64
|
### Added
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f65738b2-fa67-5b68-a0c8-c73fba12c6c5")}catch(e){}}();
|
|
3
|
+
export const CLI_VERSION = "5.12.1";
|
|
4
|
+
//# sourceMappingURL=cli-version.js.map
|
|
5
|
+
//# debugId=f65738b2-fa67-5b68-a0c8-c73fba12c6c5
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
export declare const BODY_MAX_BYTES: number;
|
|
3
|
+
export interface FeedbackResult {
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
export interface FeedbackSubmitOptions {
|
|
7
|
+
type: "bug" | "feature";
|
|
8
|
+
title: string;
|
|
9
|
+
body: string;
|
|
10
|
+
company?: string;
|
|
11
|
+
token: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function readBodyFile(bodyFile: string, stdin?: NodeJS.ReadableStream): Promise<string>;
|
|
14
|
+
export declare function submitFeedback(opts: FeedbackSubmitOptions): Promise<FeedbackResult>;
|
|
15
|
+
export declare function registerFeedbackCommand(program: Command): void;
|
|
16
|
+
//# sourceMappingURL=feedback.d.ts.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3e8d95ee-bfb4-5ca3-8177-7bc3ca618bd4")}catch(e){}}();
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { ensureCognitoToken } from "../utils/cognito-session.js";
|
|
6
|
+
import { vaultApiFetch } from "../utils/vault-api.js";
|
|
7
|
+
import { collectDiagnostics } from "../utils/feedback-diagnostics.js";
|
|
8
|
+
export const BODY_MAX_BYTES = 64 * 1024;
|
|
9
|
+
export async function readBodyFile(bodyFile, stdin) {
|
|
10
|
+
if (bodyFile === "-") {
|
|
11
|
+
const stream = stdin ?? process.stdin;
|
|
12
|
+
if (stream.isTTY) {
|
|
13
|
+
throw new Error("--body-file - requires piped stdin (got interactive terminal).");
|
|
14
|
+
}
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let data = "";
|
|
17
|
+
stream.setEncoding("utf8");
|
|
18
|
+
stream.on("data", (chunk) => {
|
|
19
|
+
data += chunk;
|
|
20
|
+
});
|
|
21
|
+
stream.on("end", () => resolve(data));
|
|
22
|
+
stream.on("error", reject);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return fs.promises.readFile(bodyFile, "utf-8");
|
|
26
|
+
}
|
|
27
|
+
export async function submitFeedback(opts) {
|
|
28
|
+
if (opts.body.trim().length === 0) {
|
|
29
|
+
throw new Error("body must not be empty. Provide at least one non-whitespace character.");
|
|
30
|
+
}
|
|
31
|
+
const bodyBytes = Buffer.byteLength(opts.body, "utf8");
|
|
32
|
+
if (bodyBytes > BODY_MAX_BYTES) {
|
|
33
|
+
throw new Error(`Body exceeds 64 KiB limit (${bodyBytes} bytes). Reduce the body size before submitting.`);
|
|
34
|
+
}
|
|
35
|
+
const diagnostics = collectDiagnostics();
|
|
36
|
+
const requestBody = {
|
|
37
|
+
type: opts.type,
|
|
38
|
+
title: opts.title,
|
|
39
|
+
body: opts.body,
|
|
40
|
+
diagnostics,
|
|
41
|
+
};
|
|
42
|
+
if (opts.company) {
|
|
43
|
+
requestBody.company = opts.company;
|
|
44
|
+
}
|
|
45
|
+
const res = await vaultApiFetch({
|
|
46
|
+
token: opts.token,
|
|
47
|
+
path: "/v1/feedback",
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: requestBody,
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const data = await res.json().catch(() => ({}));
|
|
53
|
+
const errMsg = data &&
|
|
54
|
+
typeof data === "object" &&
|
|
55
|
+
!Array.isArray(data) &&
|
|
56
|
+
typeof data.error === "string"
|
|
57
|
+
? data.error
|
|
58
|
+
: res.statusText;
|
|
59
|
+
throw new Error(`Failed to submit feedback: ${errMsg}`);
|
|
60
|
+
}
|
|
61
|
+
const data = (await res.json());
|
|
62
|
+
return { id: data.id };
|
|
63
|
+
}
|
|
64
|
+
function registerSubcommand(feedbackCmd, type) {
|
|
65
|
+
feedbackCmd
|
|
66
|
+
.command(type)
|
|
67
|
+
.description(type === "bug" ? "Report a bug" : "Request a feature")
|
|
68
|
+
.requiredOption("--title <text>", "Short title for the report")
|
|
69
|
+
.requiredOption("--body-file <path>", "Path to a markdown file with the body; use - to read from stdin")
|
|
70
|
+
.option("--company <slug>", "Company slug to associate with the report")
|
|
71
|
+
.action(async (opts) => {
|
|
72
|
+
try {
|
|
73
|
+
const token = await ensureCognitoToken({ interactive: false });
|
|
74
|
+
const body = await readBodyFile(opts.bodyFile);
|
|
75
|
+
const result = await submitFeedback({
|
|
76
|
+
type,
|
|
77
|
+
title: opts.title,
|
|
78
|
+
body,
|
|
79
|
+
company: opts.company,
|
|
80
|
+
token,
|
|
81
|
+
});
|
|
82
|
+
console.log(`Submitted: ${result.id}`);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
console.error(chalk.red("Error:"), err instanceof Error ? err.message : String(err));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export function registerFeedbackCommand(program) {
|
|
91
|
+
const feedbackCmd = program
|
|
92
|
+
.command("feedback")
|
|
93
|
+
.description("Submit a bug report or feature request to HQ");
|
|
94
|
+
registerSubcommand(feedbackCmd, "bug");
|
|
95
|
+
registerSubcommand(feedbackCmd, "feature");
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=feedback.js.map
|
|
98
|
+
//# debugId=3e8d95ee-bfb4-5ca3-8177-7bc3ca618bd4
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* HQ CLI - Module management, package management, and cloud sync for HQ
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
6
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="65033669-3ba8-5aac-8a98-49827f627ff9")}catch(e){}}();
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import { initSentry, Sentry } from "./sentry.js";
|
|
9
9
|
import { registerAddCommand } from "./commands/add.js";
|
|
@@ -28,12 +28,14 @@ import { registerRunCommand } from "./commands/run.js";
|
|
|
28
28
|
import { registerGroupsCommand } from "./commands/groups.js";
|
|
29
29
|
import { registerFilesCommand } from "./commands/files.js";
|
|
30
30
|
import { registerMembersCommand } from "./commands/members.js";
|
|
31
|
+
import { registerFeedbackCommand } from "./commands/feedback.js";
|
|
32
|
+
import { sanitizeArgv } from "./utils/feedback-diagnostics.js";
|
|
31
33
|
initSentry();
|
|
32
34
|
const program = new Command();
|
|
33
35
|
program
|
|
34
36
|
.name("hq")
|
|
35
37
|
.description("HQ management CLI — modules, packages, and cloud sync")
|
|
36
|
-
.version("5.
|
|
38
|
+
.version("5.12.1");
|
|
37
39
|
// Module management subcommand group
|
|
38
40
|
const modulesCmd = program
|
|
39
41
|
.command("modules")
|
|
@@ -86,8 +88,15 @@ registerFilesCommand(program);
|
|
|
86
88
|
registerMembersCommand(program);
|
|
87
89
|
// Onboarding (top-level — Cognito + vault-service provisioning)
|
|
88
90
|
registerOnboardCommand(program);
|
|
91
|
+
// Feedback (subcommand group — hq feedback bug|feature)
|
|
92
|
+
registerFeedbackCommand(program);
|
|
89
93
|
(async () => {
|
|
90
94
|
try {
|
|
95
|
+
Sentry.addBreadcrumb({
|
|
96
|
+
category: "command",
|
|
97
|
+
message: sanitizeArgv(process.argv.slice(2)).join(" "),
|
|
98
|
+
level: "info",
|
|
99
|
+
});
|
|
91
100
|
await program.parseAsync();
|
|
92
101
|
}
|
|
93
102
|
catch (err) {
|
|
@@ -99,4 +108,4 @@ registerOnboardCommand(program);
|
|
|
99
108
|
}
|
|
100
109
|
})();
|
|
101
110
|
//# sourceMappingURL=index.js.map
|
|
102
|
-
//# debugId=
|
|
111
|
+
//# debugId=65033669-3ba8-5aac-8a98-49827f627ff9
|
package/dist/sentry.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="508ac88d-5683-5d1f-9857-80a8a74e03e2")}catch(e){}}();
|
|
3
3
|
import * as Sentry from "@sentry/node";
|
|
4
4
|
import { BUNDLED_DSN } from "./sentry-dsn.generated.js";
|
|
5
5
|
import { beforeSend } from "./sentry-before-send.js";
|
|
6
|
+
import { beforeBreadcrumb } from "./utils/breadcrumb-buffer.js";
|
|
6
7
|
export function initSentry() {
|
|
7
8
|
const dsn = BUNDLED_DSN || process.env.SENTRY_DSN;
|
|
8
9
|
if (!dsn)
|
|
@@ -15,8 +16,9 @@ export function initSentry() {
|
|
|
15
16
|
tags: { repo: "hq-cli" },
|
|
16
17
|
},
|
|
17
18
|
beforeSend,
|
|
19
|
+
beforeBreadcrumb,
|
|
18
20
|
});
|
|
19
21
|
}
|
|
20
22
|
export { Sentry };
|
|
21
23
|
//# sourceMappingURL=sentry.js.map
|
|
22
|
-
//# debugId=
|
|
24
|
+
//# debugId=508ac88d-5683-5d1f-9857-80a8a74e03e2
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6a54e8f0-10de-59c2-82d9-22de94d9e6f2")}catch(e){}}();
|
|
3
|
+
const BUFFER_SIZE = 20;
|
|
4
|
+
const _buffer = [];
|
|
5
|
+
// Sentry beforeBreadcrumb hook: records every breadcrumb in a ring buffer
|
|
6
|
+
// and returns it unchanged so Sentry still processes it normally.
|
|
7
|
+
export function beforeBreadcrumb(breadcrumb) {
|
|
8
|
+
_buffer.push(breadcrumb);
|
|
9
|
+
if (_buffer.length > BUFFER_SIZE) {
|
|
10
|
+
_buffer.shift();
|
|
11
|
+
}
|
|
12
|
+
return breadcrumb;
|
|
13
|
+
}
|
|
14
|
+
export function getRecentBreadcrumbs() {
|
|
15
|
+
return [..._buffer];
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=breadcrumb-buffer.js.map
|
|
18
|
+
//# debugId=6a54e8f0-10de-59c2-82d9-22de94d9e6f2
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface GitContext {
|
|
2
|
+
branch: string | null;
|
|
3
|
+
head: string | null;
|
|
4
|
+
dirty: boolean;
|
|
5
|
+
remoteUrl: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface DiagnosticsBlob {
|
|
8
|
+
cliVersion: string;
|
|
9
|
+
nodeVersion: string;
|
|
10
|
+
os: {
|
|
11
|
+
platform: string;
|
|
12
|
+
release: string;
|
|
13
|
+
arch: string;
|
|
14
|
+
};
|
|
15
|
+
command: string[];
|
|
16
|
+
cwd: string;
|
|
17
|
+
git: GitContext;
|
|
18
|
+
recentSentryBreadcrumbs: unknown[];
|
|
19
|
+
}
|
|
20
|
+
export declare function sanitizeArgv(argv: string[]): string[];
|
|
21
|
+
export declare function collectDiagnostics(): DiagnosticsBlob;
|
|
22
|
+
//# sourceMappingURL=feedback-diagnostics.d.ts.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ee39c63b-ddaa-553d-b5db-77633d323d88")}catch(e){}}();
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
import { execFileSync } from "child_process";
|
|
5
|
+
import { getRecentBreadcrumbs } from "./breadcrumb-buffer.js";
|
|
6
|
+
import { CLI_VERSION } from "../cli-version.js";
|
|
7
|
+
const SECRET_FLAGS = new Set([
|
|
8
|
+
"--token",
|
|
9
|
+
"--secret",
|
|
10
|
+
"--password",
|
|
11
|
+
"--key",
|
|
12
|
+
"--api-key",
|
|
13
|
+
"--access-token",
|
|
14
|
+
"--auth-token",
|
|
15
|
+
]);
|
|
16
|
+
export function sanitizeArgv(argv) {
|
|
17
|
+
const result = [];
|
|
18
|
+
for (let i = 0; i < argv.length; i++) {
|
|
19
|
+
const arg = argv[i];
|
|
20
|
+
if (arg.startsWith("--") && arg.includes("=")) {
|
|
21
|
+
const eqIdx = arg.indexOf("=");
|
|
22
|
+
const flag = arg.slice(0, eqIdx);
|
|
23
|
+
if (SECRET_FLAGS.has(flag)) {
|
|
24
|
+
result.push(`${flag}=***`);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
result.push(arg);
|
|
29
|
+
if (SECRET_FLAGS.has(arg) && i + 1 < argv.length) {
|
|
30
|
+
result.push("***");
|
|
31
|
+
i++;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
function sanitizeRemoteUrl(url) {
|
|
37
|
+
return url.replace(/https?:\/\/[^@]+@/, "https://***@");
|
|
38
|
+
}
|
|
39
|
+
function runGit(args) {
|
|
40
|
+
return execFileSync("git", args, {
|
|
41
|
+
encoding: "utf-8",
|
|
42
|
+
timeout: 2000,
|
|
43
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
44
|
+
}).trim();
|
|
45
|
+
}
|
|
46
|
+
function collectGitContext() {
|
|
47
|
+
let branch = null;
|
|
48
|
+
let head = null;
|
|
49
|
+
let dirty = false;
|
|
50
|
+
let remoteUrl = null;
|
|
51
|
+
try {
|
|
52
|
+
branch = runGit(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return { branch: null, head: null, dirty: false, remoteUrl: null };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
head = runGit(["rev-parse", "--short", "HEAD"]);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// best-effort
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const statusOut = runGit(["status", "--porcelain"]);
|
|
65
|
+
dirty = statusOut.length > 0;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// best-effort
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const raw = runGit(["remote", "get-url", "origin"]);
|
|
72
|
+
remoteUrl = sanitizeRemoteUrl(raw);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// no origin remote
|
|
76
|
+
}
|
|
77
|
+
return { branch, head, dirty, remoteUrl };
|
|
78
|
+
}
|
|
79
|
+
export function collectDiagnostics() {
|
|
80
|
+
return {
|
|
81
|
+
cliVersion: CLI_VERSION,
|
|
82
|
+
nodeVersion: process.version,
|
|
83
|
+
os: {
|
|
84
|
+
platform: os.platform(),
|
|
85
|
+
release: os.release(),
|
|
86
|
+
arch: os.arch(),
|
|
87
|
+
},
|
|
88
|
+
command: sanitizeArgv(process.argv.slice(2)),
|
|
89
|
+
cwd: process.cwd(),
|
|
90
|
+
git: collectGitContext(),
|
|
91
|
+
recentSentryBreadcrumbs: getRecentBreadcrumbs(),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=feedback-diagnostics.js.map
|
|
95
|
+
//# debugId=ee39c63b-ddaa-553d-b5db-77633d323d88
|
package/dist/utils/vault-api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e1ca2b83-1de0-5000-ab66-f573000a579b")}catch(e){}}();
|
|
3
3
|
import { DEFAULT_VAULT_API_URL } from './cognito-session.js';
|
|
4
|
+
import { Sentry } from '../sentry.js';
|
|
4
5
|
export async function vaultApiFetch(opts) {
|
|
5
6
|
const url = new URL(opts.path, DEFAULT_VAULT_API_URL);
|
|
6
7
|
if (opts.query) {
|
|
@@ -8,14 +9,31 @@ export async function vaultApiFetch(opts) {
|
|
|
8
9
|
url.searchParams.set(k, v);
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const method = opts.method ?? 'GET';
|
|
13
|
+
const safeUrl = url.search ? `${url.origin}${url.pathname}?<redacted>` : `${url.origin}${url.pathname}`;
|
|
14
|
+
Sentry.addBreadcrumb({
|
|
15
|
+
category: "http",
|
|
16
|
+
message: `${method} ${opts.path}`,
|
|
17
|
+
level: "info",
|
|
18
|
+
data: { url: safeUrl, method },
|
|
19
|
+
});
|
|
20
|
+
const response = await fetch(url.toString(), {
|
|
21
|
+
method,
|
|
13
22
|
headers: {
|
|
14
23
|
Authorization: `Bearer ${opts.token}`,
|
|
15
24
|
'Content-Type': 'application/json',
|
|
16
25
|
},
|
|
17
26
|
body: opts.body ? JSON.stringify(opts.body) : undefined,
|
|
18
27
|
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
Sentry.addBreadcrumb({
|
|
30
|
+
category: "http",
|
|
31
|
+
message: `${method} ${opts.path} → ${response.status}`,
|
|
32
|
+
level: "warning",
|
|
33
|
+
data: { url: safeUrl, status: response.status },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return response;
|
|
19
37
|
}
|
|
20
38
|
async function resolveCompanyUid(token, slug) {
|
|
21
39
|
const res = await vaultApiFetch({
|
|
@@ -88,4 +106,4 @@ export async function getEntityUid(token, opts) {
|
|
|
88
106
|
return getCompanyUid(token, opts.companySlug);
|
|
89
107
|
}
|
|
90
108
|
//# sourceMappingURL=vault-api.js.map
|
|
91
|
-
//# debugId=
|
|
109
|
+
//# debugId=e1ca2b83-1de0-5000-ab66-f573000a579b
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.12.1",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"build": "node scripts/generate-dsn.mjs && tsc",
|
|
12
12
|
"typecheck": "tsc --noEmit",
|
|
13
13
|
"test": "vitest run",
|
|
14
|
+
"vitest": "vitest",
|
|
14
15
|
"clean": "rm -rf dist"
|
|
15
16
|
},
|
|
16
17
|
"dependencies": {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CLI_VERSION = "5.12.1";
|