@indigoai-us/hq-cli 5.345.32 → 5.345.33
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 +8 -0
- package/dist/command-catalog.generated.d.ts +92 -3
- package/dist/command-catalog.generated.js +111 -3
- package/dist/commands/db-dump.d.ts +8 -0
- package/dist/commands/db-dump.js +50 -0
- package/dist/commands/db-provision.d.ts +3 -10
- package/dist/commands/db-provision.js +26 -47
- package/dist/commands/db-remote-deps.d.ts +18 -0
- package/dist/commands/db-remote-deps.js +59 -0
- package/dist/commands/db-sql.d.ts +2 -1
- package/dist/commands/db-sql.js +30 -5
- package/dist/commands/db-usage.d.ts +7 -0
- package/dist/commands/db-usage.js +28 -0
- package/dist/commands/db.js +4 -0
- package/dist/commands/files.js +33 -5
- package/dist/commands/lanes-message.js +40 -8
- package/dist/commands/lanes-questions.d.ts +6 -1
- package/dist/commands/lanes-questions.js +19 -7
- package/dist/commands/lanes-resume.js +17 -6
- package/dist/commands/lanes-shared.d.ts +6 -1
- package/dist/commands/lanes.js +74 -1
- package/dist/commands/mesh.js +150 -26
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +68 -604
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/db/control-plane.d.ts +32 -0
- package/dist/lib/db/control-plane.js +50 -0
- package/dist/lib/db/redact.d.ts +4 -0
- package/dist/lib/db/redact.js +17 -0
- package/dist/lib/db/remote-engine.d.ts +67 -0
- package/dist/lib/db/remote-engine.js +165 -0
- package/dist/lib/db/usage-format.d.ts +4 -0
- package/dist/lib/db/usage-format.js +41 -0
- package/dist/lib/lanes/keep-alive.d.ts +12 -0
- package/dist/lib/lanes/keep-alive.js +25 -6
- package/dist/lib/mesh/api.d.ts +2 -0
- package/dist/lib/mesh/project-board.d.ts +17 -0
- package/dist/lib/mesh/project-board.js +28 -0
- package/dist/lib/mesh/story-status.d.ts +16 -0
- package/dist/lib/mesh/story-status.js +32 -7
- package/dist/utils/self-update.d.ts +2 -0
- package/dist/utils/self-update.js +61 -23
- package/dist/utils/version-check.d.ts +1 -1
- package/dist/utils/version-check.js +2 -2
- package/dist/utils/version-gate.d.ts +21 -14
- package/dist/utils/version-gate.js +119 -28
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.345.33] — 2026-10-06
|
|
6
|
+
- Map each PRD ledger state to a Board column and send its original value in `ledgerState`; `hq mesh project reconcile` reports status drift and notes when the Board omits that field.
|
|
7
|
+
|
|
8
|
+
- Prevent pnpm self-updates from changing Corepack's project-selected version, and restore and verify the existing CLI after an unsuccessful update.
|
|
9
|
+
- Let creators and company admins remove empty file-sharing ACL patterns without naming a grantee. Creating a private folder now clears an empty conflicting sharing pattern automatically.
|
|
10
|
+
- `hq db provision` now creates the company's remote database and reports whether it is ready or already exists. `hq db sql --app <app>` runs read-only SQL in an app's remote schema (add `--write` to change data), `hq db usage` shows this month's compute and storage against both caps, and `hq db dump --app <app>` exports the schema and data to a local SQL file. No command prints tokens, passwords, or connection strings.
|
|
11
|
+
- `hq lanes message` now lets an active keep-alive lane record win over a stale retired-registry entry, warns with the exact registry row, and `hq lanes doctor` reports retired, superseded, and awaiting-input recovery findings.
|
|
12
|
+
|
|
5
13
|
## [5.345.32] — 2026-10-06
|
|
6
14
|
- `hq integrations list --usable` lists only the apps you can use right now: connected, shared with you under the same access rule the HQ gateway applies, and backed by a provider the gateway has registered. Each row shows the app name, its website domain, and the flag that selects exactly that connection in `hq integrations tools` and `call` (`--provider <slug>`, or `--connection <id>` when two connections share a provider). `--json` returns `{companyUid, viewerAccessKnown, apps}`. `--no-login` makes `list` fail instead of opening a browser sign-in, for hooks and scripts.
|
|
7
15
|
|
|
@@ -1875,7 +1875,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
1875
1875
|
readonly subcommands: readonly [];
|
|
1876
1876
|
}, {
|
|
1877
1877
|
readonly name: "sql";
|
|
1878
|
-
readonly description: "Run SQL against the company vault DB (local; read-only by default
|
|
1878
|
+
readonly description: "Run SQL against the company vault DB (local) or an app's remote database (--app); read-only by default";
|
|
1879
1879
|
readonly aliases: readonly [];
|
|
1880
1880
|
readonly hidden: false;
|
|
1881
1881
|
readonly helpOption: true;
|
|
@@ -1892,6 +1892,10 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
1892
1892
|
readonly flags: "--company <slug>";
|
|
1893
1893
|
readonly description: "Company slug (tenant scope; required)";
|
|
1894
1894
|
readonly hidden: false;
|
|
1895
|
+
}, {
|
|
1896
|
+
readonly flags: "--app <app>";
|
|
1897
|
+
readonly description: "Run against this app's remote database schema";
|
|
1898
|
+
readonly hidden: false;
|
|
1895
1899
|
}, {
|
|
1896
1900
|
readonly flags: "--write";
|
|
1897
1901
|
readonly description: "Allow write/DDL statements (discouraged for ad-hoc DDL)";
|
|
@@ -1953,7 +1957,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
1953
1957
|
readonly subcommands: readonly [];
|
|
1954
1958
|
}, {
|
|
1955
1959
|
readonly name: "provision";
|
|
1956
|
-
readonly description: "
|
|
1960
|
+
readonly description: "Create the company remote database (Team plan)";
|
|
1957
1961
|
readonly aliases: readonly [];
|
|
1958
1962
|
readonly hidden: false;
|
|
1959
1963
|
readonly helpOption: true;
|
|
@@ -1972,6 +1976,46 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
1972
1976
|
readonly defaultValue: "us-east-1";
|
|
1973
1977
|
}];
|
|
1974
1978
|
readonly subcommands: readonly [];
|
|
1979
|
+
}, {
|
|
1980
|
+
readonly name: "usage";
|
|
1981
|
+
readonly description: "Show this month's remote database usage against the compute and storage caps";
|
|
1982
|
+
readonly aliases: readonly [];
|
|
1983
|
+
readonly hidden: false;
|
|
1984
|
+
readonly helpOption: true;
|
|
1985
|
+
readonly helpCommand: false;
|
|
1986
|
+
readonly usage: "[options]";
|
|
1987
|
+
readonly helpText: readonly [];
|
|
1988
|
+
readonly arguments: readonly [];
|
|
1989
|
+
readonly options: readonly [{
|
|
1990
|
+
readonly flags: "--company <slug>";
|
|
1991
|
+
readonly description: "Company slug";
|
|
1992
|
+
readonly hidden: false;
|
|
1993
|
+
}];
|
|
1994
|
+
readonly subcommands: readonly [];
|
|
1995
|
+
}, {
|
|
1996
|
+
readonly name: "dump";
|
|
1997
|
+
readonly description: "Export an app's remote database schema and data to a SQL file";
|
|
1998
|
+
readonly aliases: readonly [];
|
|
1999
|
+
readonly hidden: false;
|
|
2000
|
+
readonly helpOption: true;
|
|
2001
|
+
readonly helpCommand: false;
|
|
2002
|
+
readonly usage: "[options]";
|
|
2003
|
+
readonly helpText: readonly [];
|
|
2004
|
+
readonly arguments: readonly [];
|
|
2005
|
+
readonly options: readonly [{
|
|
2006
|
+
readonly flags: "--company <slug>";
|
|
2007
|
+
readonly description: "Company slug";
|
|
2008
|
+
readonly hidden: false;
|
|
2009
|
+
}, {
|
|
2010
|
+
readonly flags: "--app <app>";
|
|
2011
|
+
readonly description: "App id";
|
|
2012
|
+
readonly hidden: false;
|
|
2013
|
+
}, {
|
|
2014
|
+
readonly flags: "--out <file>";
|
|
2015
|
+
readonly description: "Output file (default: <app>.sql)";
|
|
2016
|
+
readonly hidden: false;
|
|
2017
|
+
}];
|
|
2018
|
+
readonly subcommands: readonly [];
|
|
1975
2019
|
}];
|
|
1976
2020
|
}, {
|
|
1977
2021
|
readonly name: "api-keys";
|
|
@@ -2441,7 +2485,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
2441
2485
|
readonly subcommands: readonly [];
|
|
2442
2486
|
}, {
|
|
2443
2487
|
readonly name: "unshare";
|
|
2444
|
-
readonly description: "Remove a file access grant
|
|
2488
|
+
readonly description: "Remove a named file access grant, or remove an empty ACL row without --with.";
|
|
2445
2489
|
readonly aliases: readonly [];
|
|
2446
2490
|
readonly hidden: false;
|
|
2447
2491
|
readonly helpOption: true;
|
|
@@ -9320,6 +9364,35 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
9320
9364
|
readonly hidden: false;
|
|
9321
9365
|
}];
|
|
9322
9366
|
readonly subcommands: readonly [];
|
|
9367
|
+
}, {
|
|
9368
|
+
readonly name: "reconcile";
|
|
9369
|
+
readonly description: "Read the project Board and report drift from a PRD ledger";
|
|
9370
|
+
readonly aliases: readonly [];
|
|
9371
|
+
readonly hidden: false;
|
|
9372
|
+
readonly helpOption: true;
|
|
9373
|
+
readonly helpCommand: false;
|
|
9374
|
+
readonly usage: "[options] <projectId>";
|
|
9375
|
+
readonly helpText: readonly [];
|
|
9376
|
+
readonly arguments: readonly [{
|
|
9377
|
+
readonly name: "projectId";
|
|
9378
|
+
readonly required: true;
|
|
9379
|
+
readonly variadic: false;
|
|
9380
|
+
readonly description: "";
|
|
9381
|
+
}];
|
|
9382
|
+
readonly options: readonly [{
|
|
9383
|
+
readonly flags: "--company <slug|uid>";
|
|
9384
|
+
readonly description: "Company slug or cloud uid";
|
|
9385
|
+
readonly hidden: false;
|
|
9386
|
+
}, {
|
|
9387
|
+
readonly flags: "--stories-file <path>";
|
|
9388
|
+
readonly description: "PRD JSON file with userStories";
|
|
9389
|
+
readonly hidden: false;
|
|
9390
|
+
}, {
|
|
9391
|
+
readonly flags: "--json";
|
|
9392
|
+
readonly description: "Print machine-readable mismatch records";
|
|
9393
|
+
readonly hidden: false;
|
|
9394
|
+
}];
|
|
9395
|
+
readonly subcommands: readonly [];
|
|
9323
9396
|
}, {
|
|
9324
9397
|
readonly name: "register";
|
|
9325
9398
|
readonly description: "Register an existing Board and bind its project channel; use project ensure to create or repair a Board";
|
|
@@ -11613,6 +11686,22 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
11613
11686
|
readonly hidden: false;
|
|
11614
11687
|
}];
|
|
11615
11688
|
readonly subcommands: readonly [];
|
|
11689
|
+
}, {
|
|
11690
|
+
readonly name: "doctor";
|
|
11691
|
+
readonly description: "Report active keep-alive lanes blocked by retired, superseded, or pending-question state";
|
|
11692
|
+
readonly aliases: readonly [];
|
|
11693
|
+
readonly hidden: false;
|
|
11694
|
+
readonly helpOption: true;
|
|
11695
|
+
readonly helpCommand: false;
|
|
11696
|
+
readonly usage: "[options]";
|
|
11697
|
+
readonly helpText: readonly [];
|
|
11698
|
+
readonly arguments: readonly [];
|
|
11699
|
+
readonly options: readonly [{
|
|
11700
|
+
readonly flags: "--json";
|
|
11701
|
+
readonly description: "JSON on stdout (always)";
|
|
11702
|
+
readonly hidden: false;
|
|
11703
|
+
}];
|
|
11704
|
+
readonly subcommands: readonly [];
|
|
11616
11705
|
}, {
|
|
11617
11706
|
readonly name: "list";
|
|
11618
11707
|
readonly description: "List lanes";
|
|
@@ -2249,7 +2249,7 @@ export const COMMAND_CATALOG = [
|
|
|
2249
2249
|
},
|
|
2250
2250
|
{
|
|
2251
2251
|
"name": "sql",
|
|
2252
|
-
"description": "Run SQL against the company vault DB (local; read-only by default
|
|
2252
|
+
"description": "Run SQL against the company vault DB (local) or an app's remote database (--app); read-only by default",
|
|
2253
2253
|
"aliases": [],
|
|
2254
2254
|
"hidden": false,
|
|
2255
2255
|
"helpOption": true,
|
|
@@ -2270,6 +2270,11 @@ export const COMMAND_CATALOG = [
|
|
|
2270
2270
|
"description": "Company slug (tenant scope; required)",
|
|
2271
2271
|
"hidden": false
|
|
2272
2272
|
},
|
|
2273
|
+
{
|
|
2274
|
+
"flags": "--app <app>",
|
|
2275
|
+
"description": "Run against this app's remote database schema",
|
|
2276
|
+
"hidden": false
|
|
2277
|
+
},
|
|
2273
2278
|
{
|
|
2274
2279
|
"flags": "--write",
|
|
2275
2280
|
"description": "Allow write/DDL statements (discouraged for ad-hoc DDL)",
|
|
@@ -2344,7 +2349,7 @@ export const COMMAND_CATALOG = [
|
|
|
2344
2349
|
},
|
|
2345
2350
|
{
|
|
2346
2351
|
"name": "provision",
|
|
2347
|
-
"description": "
|
|
2352
|
+
"description": "Create the company remote database (Team plan)",
|
|
2348
2353
|
"aliases": [],
|
|
2349
2354
|
"hidden": false,
|
|
2350
2355
|
"helpOption": true,
|
|
@@ -2366,6 +2371,54 @@ export const COMMAND_CATALOG = [
|
|
|
2366
2371
|
}
|
|
2367
2372
|
],
|
|
2368
2373
|
"subcommands": []
|
|
2374
|
+
},
|
|
2375
|
+
{
|
|
2376
|
+
"name": "usage",
|
|
2377
|
+
"description": "Show this month's remote database usage against the compute and storage caps",
|
|
2378
|
+
"aliases": [],
|
|
2379
|
+
"hidden": false,
|
|
2380
|
+
"helpOption": true,
|
|
2381
|
+
"helpCommand": false,
|
|
2382
|
+
"usage": "[options]",
|
|
2383
|
+
"helpText": [],
|
|
2384
|
+
"arguments": [],
|
|
2385
|
+
"options": [
|
|
2386
|
+
{
|
|
2387
|
+
"flags": "--company <slug>",
|
|
2388
|
+
"description": "Company slug",
|
|
2389
|
+
"hidden": false
|
|
2390
|
+
}
|
|
2391
|
+
],
|
|
2392
|
+
"subcommands": []
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
"name": "dump",
|
|
2396
|
+
"description": "Export an app's remote database schema and data to a SQL file",
|
|
2397
|
+
"aliases": [],
|
|
2398
|
+
"hidden": false,
|
|
2399
|
+
"helpOption": true,
|
|
2400
|
+
"helpCommand": false,
|
|
2401
|
+
"usage": "[options]",
|
|
2402
|
+
"helpText": [],
|
|
2403
|
+
"arguments": [],
|
|
2404
|
+
"options": [
|
|
2405
|
+
{
|
|
2406
|
+
"flags": "--company <slug>",
|
|
2407
|
+
"description": "Company slug",
|
|
2408
|
+
"hidden": false
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
"flags": "--app <app>",
|
|
2412
|
+
"description": "App id",
|
|
2413
|
+
"hidden": false
|
|
2414
|
+
},
|
|
2415
|
+
{
|
|
2416
|
+
"flags": "--out <file>",
|
|
2417
|
+
"description": "Output file (default: <app>.sql)",
|
|
2418
|
+
"hidden": false
|
|
2419
|
+
}
|
|
2420
|
+
],
|
|
2421
|
+
"subcommands": []
|
|
2369
2422
|
}
|
|
2370
2423
|
]
|
|
2371
2424
|
},
|
|
@@ -2932,7 +2985,7 @@ export const COMMAND_CATALOG = [
|
|
|
2932
2985
|
},
|
|
2933
2986
|
{
|
|
2934
2987
|
"name": "unshare",
|
|
2935
|
-
"description": "Remove a file access grant
|
|
2988
|
+
"description": "Remove a named file access grant, or remove an empty ACL row without --with.",
|
|
2936
2989
|
"aliases": [],
|
|
2937
2990
|
"hidden": false,
|
|
2938
2991
|
"helpOption": true,
|
|
@@ -11303,6 +11356,42 @@ export const COMMAND_CATALOG = [
|
|
|
11303
11356
|
],
|
|
11304
11357
|
"subcommands": []
|
|
11305
11358
|
},
|
|
11359
|
+
{
|
|
11360
|
+
"name": "reconcile",
|
|
11361
|
+
"description": "Read the project Board and report drift from a PRD ledger",
|
|
11362
|
+
"aliases": [],
|
|
11363
|
+
"hidden": false,
|
|
11364
|
+
"helpOption": true,
|
|
11365
|
+
"helpCommand": false,
|
|
11366
|
+
"usage": "[options] <projectId>",
|
|
11367
|
+
"helpText": [],
|
|
11368
|
+
"arguments": [
|
|
11369
|
+
{
|
|
11370
|
+
"name": "projectId",
|
|
11371
|
+
"required": true,
|
|
11372
|
+
"variadic": false,
|
|
11373
|
+
"description": ""
|
|
11374
|
+
}
|
|
11375
|
+
],
|
|
11376
|
+
"options": [
|
|
11377
|
+
{
|
|
11378
|
+
"flags": "--company <slug|uid>",
|
|
11379
|
+
"description": "Company slug or cloud uid",
|
|
11380
|
+
"hidden": false
|
|
11381
|
+
},
|
|
11382
|
+
{
|
|
11383
|
+
"flags": "--stories-file <path>",
|
|
11384
|
+
"description": "PRD JSON file with userStories",
|
|
11385
|
+
"hidden": false
|
|
11386
|
+
},
|
|
11387
|
+
{
|
|
11388
|
+
"flags": "--json",
|
|
11389
|
+
"description": "Print machine-readable mismatch records",
|
|
11390
|
+
"hidden": false
|
|
11391
|
+
}
|
|
11392
|
+
],
|
|
11393
|
+
"subcommands": []
|
|
11394
|
+
},
|
|
11306
11395
|
{
|
|
11307
11396
|
"name": "register",
|
|
11308
11397
|
"description": "Register an existing Board and bind its project channel; use project ensure to create or repair a Board",
|
|
@@ -14114,6 +14203,25 @@ export const COMMAND_CATALOG = [
|
|
|
14114
14203
|
],
|
|
14115
14204
|
"subcommands": []
|
|
14116
14205
|
},
|
|
14206
|
+
{
|
|
14207
|
+
"name": "doctor",
|
|
14208
|
+
"description": "Report active keep-alive lanes blocked by retired, superseded, or pending-question state",
|
|
14209
|
+
"aliases": [],
|
|
14210
|
+
"hidden": false,
|
|
14211
|
+
"helpOption": true,
|
|
14212
|
+
"helpCommand": false,
|
|
14213
|
+
"usage": "[options]",
|
|
14214
|
+
"helpText": [],
|
|
14215
|
+
"arguments": [],
|
|
14216
|
+
"options": [
|
|
14217
|
+
{
|
|
14218
|
+
"flags": "--json",
|
|
14219
|
+
"description": "JSON on stdout (always)",
|
|
14220
|
+
"hidden": false
|
|
14221
|
+
}
|
|
14222
|
+
],
|
|
14223
|
+
"subcommands": []
|
|
14224
|
+
},
|
|
14117
14225
|
{
|
|
14118
14226
|
"name": "list",
|
|
14119
14227
|
"description": "List lanes",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hq db dump — export one app's remote schema (DDL) and data (INSERTs) to a local file.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { type DbRemoteCommandDeps } from "./db-remote-deps.js";
|
|
6
|
+
export declare function describeSessionGap(error: unknown): string | null;
|
|
7
|
+
export declare function registerDbDumpCommand(db: Command, depsFactory?: () => DbRemoteCommandDeps): void;
|
|
8
|
+
//# sourceMappingURL=db-dump.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hq db dump — export one app's remote schema (DDL) and data (INSERTs) to a local file.
|
|
3
|
+
*/
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import { safeErrorMessage } from "../lib/db/redact.js";
|
|
7
|
+
import { dumpRemoteSchema, openRemoteAppConnection } from "../lib/db/remote-engine.js";
|
|
8
|
+
import { isPlanGateError } from "../utils/plan-gate-error.js";
|
|
9
|
+
import { defaultRemoteDeps, describeRemoteError, remoteEngineDeps, } from "./db-remote-deps.js";
|
|
10
|
+
export function describeSessionGap(error) {
|
|
11
|
+
const status = error.status;
|
|
12
|
+
if (status === 404 || status === 405) {
|
|
13
|
+
return "Remote database access for apps is not available yet. The HQ API has no database session route.";
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
export function registerDbDumpCommand(db, depsFactory = defaultRemoteDeps) {
|
|
18
|
+
db.command("dump")
|
|
19
|
+
.description("Export an app's remote database schema and data to a SQL file")
|
|
20
|
+
.requiredOption("--company <slug>", "Company slug")
|
|
21
|
+
.requiredOption("--app <app>", "App id")
|
|
22
|
+
.option("--out <file>", "Output file (default: <app>.sql)")
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
try {
|
|
25
|
+
const deps = depsFactory();
|
|
26
|
+
const resolved = await deps.resolveCompany(String(opts.company ?? "").trim());
|
|
27
|
+
const conn = await openRemoteAppConnection(remoteEngineDeps(deps), {
|
|
28
|
+
companyUid: resolved.companyUid,
|
|
29
|
+
appId: opts.app,
|
|
30
|
+
});
|
|
31
|
+
const outPath = opts.out ?? `${opts.app}.sql`;
|
|
32
|
+
const fd = fs.openSync(outPath, "w");
|
|
33
|
+
try {
|
|
34
|
+
const summary = await dumpRemoteSchema(conn, (text) => fs.writeSync(fd, text));
|
|
35
|
+
console.log(`Wrote ${summary.tables} table(s) and ${summary.rows} row(s) to ${outPath}.`);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
fs.closeSync(fd);
|
|
39
|
+
await conn.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (isPlanGateError(error))
|
|
44
|
+
throw error;
|
|
45
|
+
console.error(chalk.red("Error:"), describeSessionGap(error) ?? describeRemoteError(error) ?? safeErrorMessage(error));
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=db-dump.js.map
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hq db provision —
|
|
2
|
+
* hq db provision — create the company remote database through the HQ control plane.
|
|
3
3
|
*/
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
companyUid: string;
|
|
8
|
-
companySlug: string;
|
|
9
|
-
}>;
|
|
10
|
-
getAccessToken: () => Promise<string>;
|
|
11
|
-
apiBaseUrl: string;
|
|
12
|
-
fetchImpl?: typeof fetch;
|
|
13
|
-
}
|
|
5
|
+
import { type DbRemoteCommandDeps } from "./db-remote-deps.js";
|
|
6
|
+
export type DbProvisionCommandDeps = DbRemoteCommandDeps;
|
|
14
7
|
export declare function registerDbProvisionCommand(db: Command, depsFactory?: () => DbProvisionCommandDeps): void;
|
|
15
8
|
//# sourceMappingURL=db-provision.d.ts.map
|
|
@@ -1,34 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hq db provision —
|
|
2
|
+
* hq db provision — create the company remote database through the HQ control plane.
|
|
3
3
|
*/
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { ControlPlaneDbClient } from "../lib/db/control-plane.js";
|
|
6
|
-
import {
|
|
6
|
+
import { safeErrorMessage } from "../lib/db/redact.js";
|
|
7
7
|
import { isPlanGateError } from "../utils/plan-gate-error.js";
|
|
8
|
-
import {
|
|
9
|
-
const defaultDeps =
|
|
10
|
-
async resolveCompany(slug) {
|
|
11
|
-
if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1") {
|
|
12
|
-
return { companyUid: `cmp_${slug}`, companySlug: slug };
|
|
13
|
-
}
|
|
14
|
-
const token = await ensureCognitoToken({ interactive: false });
|
|
15
|
-
const companyUid = await getCompanyUid(token, slug);
|
|
16
|
-
return { companyUid, companySlug: slug.trim().toLowerCase() };
|
|
17
|
-
},
|
|
18
|
-
async getAccessToken() {
|
|
19
|
-
if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1") {
|
|
20
|
-
return "mock-token";
|
|
21
|
-
}
|
|
22
|
-
return ensureCognitoToken({ interactive: false });
|
|
23
|
-
},
|
|
24
|
-
apiBaseUrl: process.env.HQ_VAULT_API_URL ||
|
|
25
|
-
process.env.HQ_API_BASE_URL ||
|
|
26
|
-
process.env.HQ_CLOUD_API_URL ||
|
|
27
|
-
DEFAULT_VAULT_API_URL,
|
|
28
|
-
});
|
|
8
|
+
import { defaultRemoteDeps, describeRemoteError, } from "./db-remote-deps.js";
|
|
9
|
+
const defaultDeps = defaultRemoteDeps;
|
|
29
10
|
export function registerDbProvisionCommand(db, depsFactory = defaultDeps) {
|
|
30
11
|
db.command("provision")
|
|
31
|
-
.description("
|
|
12
|
+
.description("Create the company remote database (Team plan)")
|
|
32
13
|
.requiredOption("--company <slug>", "Company slug")
|
|
33
14
|
.option("--region <region>", "AWS region", "us-east-1")
|
|
34
15
|
.action(async (opts) => {
|
|
@@ -51,38 +32,36 @@ export function registerDbProvisionCommand(db, depsFactory = defaultDeps) {
|
|
|
51
32
|
companySlug: resolved.companySlug,
|
|
52
33
|
region: opts.region,
|
|
53
34
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
if (result.status === "provisioning") {
|
|
36
|
+
console.log(`The remote database for ${result.companySlug} is still being set up. Run this again in a minute.`);
|
|
37
|
+
}
|
|
38
|
+
else if (result.idempotent || result.status === "existing") {
|
|
39
|
+
console.log(`The remote database for ${result.companySlug} already exists and is ready (${result.region}).`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(`The remote database for ${result.companySlug} is ready (${result.region}).`);
|
|
43
|
+
}
|
|
61
44
|
}
|
|
62
45
|
catch (error) {
|
|
63
46
|
// Let main.ts render the shared, non-stacktrace plan-gate message.
|
|
64
47
|
if (isPlanGateError(error))
|
|
65
48
|
throw error;
|
|
66
|
-
const
|
|
49
|
+
const described = describeRemoteError(error);
|
|
67
50
|
const status = error.status;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
51
|
+
if (described) {
|
|
52
|
+
console.error(chalk.red("Error:"), described);
|
|
53
|
+
if (status === 501 || error.code === "REMOTE_DB_NOT_AVAILABLE") {
|
|
54
|
+
console.error(chalk.dim("Local hq db status|sql|migrate still work offline."));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.error(chalk.dim("Local databases still work: hq db status|sql|migrate."));
|
|
58
|
+
}
|
|
72
59
|
}
|
|
73
|
-
else if (status ===
|
|
74
|
-
console.error(chalk.red("Error:"), "
|
|
75
|
-
console.error(chalk.dim("Local databases still work: hq db status|sql|migrate — no HQ Workforce plan required."));
|
|
76
|
-
}
|
|
77
|
-
else if (status === 404 || /Unknown route|Not Found/i.test(msg)) {
|
|
78
|
-
console.error(chalk.red("Error:"), "Remote DB control plane is not available yet (routes not deployed).");
|
|
79
|
-
console.error(chalk.dim("Local hq db status|sql|migrate still work offline."));
|
|
60
|
+
else if (status === 404) {
|
|
61
|
+
console.error(chalk.red("Error:"), "The HQ API does not know the remote database routes. Update the CLI or check HQ_VAULT_API_URL.");
|
|
80
62
|
}
|
|
81
63
|
else {
|
|
82
|
-
console.error(chalk.red("Error:"),
|
|
83
|
-
}
|
|
84
|
-
if (/postgres:\/\//i.test(msg)) {
|
|
85
|
-
console.error(chalk.red("Error: refused to print secret material"));
|
|
64
|
+
console.error(chalk.red("Error:"), safeErrorMessage(error));
|
|
86
65
|
}
|
|
87
66
|
process.exitCode = 1;
|
|
88
67
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ControlPlaneDbClient } from "../lib/db/control-plane.js";
|
|
2
|
+
import { type RemoteEngineDeps } from "../lib/db/remote-engine.js";
|
|
3
|
+
export interface DbRemoteCommandDeps {
|
|
4
|
+
resolveCompany: (slug: string) => Promise<{
|
|
5
|
+
companyUid: string;
|
|
6
|
+
companySlug: string;
|
|
7
|
+
}>;
|
|
8
|
+
getAccessToken: () => Promise<string>;
|
|
9
|
+
apiBaseUrl: string;
|
|
10
|
+
fetchImpl?: typeof fetch;
|
|
11
|
+
engine?: Partial<Pick<RemoteEngineDeps, "tokenFactory" | "clientFactory" | "provider">>;
|
|
12
|
+
}
|
|
13
|
+
export declare function defaultRemoteDeps(): DbRemoteCommandDeps;
|
|
14
|
+
export declare function controlPlaneClient(deps: DbRemoteCommandDeps): ControlPlaneDbClient;
|
|
15
|
+
export declare function remoteEngineDeps(deps: DbRemoteCommandDeps): RemoteEngineDeps;
|
|
16
|
+
/** Plain-language message for a failed remote call, or null when the error is not recognized. */
|
|
17
|
+
export declare function describeRemoteError(error: unknown): string | null;
|
|
18
|
+
//# sourceMappingURL=db-remote-deps.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ControlPlaneDbClient } from "../lib/db/control-plane.js";
|
|
2
|
+
import { controlPlaneCredentialProvider, } from "../lib/db/remote-engine.js";
|
|
3
|
+
import { DEFAULT_VAULT_API_URL, ensureCognitoToken, } from "../utils/cognito-session.js";
|
|
4
|
+
import { getCompanyUid } from "../utils/vault-api.js";
|
|
5
|
+
export function defaultRemoteDeps() {
|
|
6
|
+
return {
|
|
7
|
+
async resolveCompany(slug) {
|
|
8
|
+
if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1") {
|
|
9
|
+
return { companyUid: `cmp_${slug}`, companySlug: slug };
|
|
10
|
+
}
|
|
11
|
+
const token = await ensureCognitoToken({ interactive: false });
|
|
12
|
+
const companyUid = await getCompanyUid(token, slug);
|
|
13
|
+
return { companyUid, companySlug: slug.trim().toLowerCase() };
|
|
14
|
+
},
|
|
15
|
+
async getAccessToken() {
|
|
16
|
+
if (process.env.HQ_DB_MOCK_CONTROL_PLANE === "1")
|
|
17
|
+
return "mock-token";
|
|
18
|
+
return ensureCognitoToken({ interactive: false });
|
|
19
|
+
},
|
|
20
|
+
apiBaseUrl: process.env.HQ_VAULT_API_URL ||
|
|
21
|
+
process.env.HQ_API_BASE_URL ||
|
|
22
|
+
process.env.HQ_CLOUD_API_URL ||
|
|
23
|
+
DEFAULT_VAULT_API_URL,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function controlPlaneClient(deps) {
|
|
27
|
+
return new ControlPlaneDbClient({
|
|
28
|
+
baseUrl: deps.apiBaseUrl,
|
|
29
|
+
getAccessToken: deps.getAccessToken,
|
|
30
|
+
fetchImpl: deps.fetchImpl,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function remoteEngineDeps(deps) {
|
|
34
|
+
return {
|
|
35
|
+
provider: deps.engine?.provider ?? controlPlaneCredentialProvider(controlPlaneClient(deps)),
|
|
36
|
+
tokenFactory: deps.engine?.tokenFactory,
|
|
37
|
+
clientFactory: deps.engine?.clientFactory,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Plain-language message for a failed remote call, or null when the error is not recognized. */
|
|
41
|
+
export function describeRemoteError(error) {
|
|
42
|
+
const status = error.status;
|
|
43
|
+
const code = error.code;
|
|
44
|
+
if (code === "REMOTE_DB_NOT_AVAILABLE" || status === 501) {
|
|
45
|
+
return "Remote databases are not available yet.";
|
|
46
|
+
}
|
|
47
|
+
if (status === 402 || code === "PLAN_REQUIRED") {
|
|
48
|
+
return "Remote databases require the Team plan.";
|
|
49
|
+
}
|
|
50
|
+
if (status === 403)
|
|
51
|
+
return "You are not a member of this company, or this app belongs to another company.";
|
|
52
|
+
if (status === 409)
|
|
53
|
+
return "This company has no remote database yet. Run hq db provision first.";
|
|
54
|
+
if (status === 404 && code === "DB_USAGE_NOT_PROVISIONED") {
|
|
55
|
+
return "This company has no remote database yet. Run hq db provision first.";
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=db-remote-deps.js.map
|
|
@@ -5,5 +5,6 @@
|
|
|
5
5
|
* Never prints remote connection strings.
|
|
6
6
|
*/
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
-
|
|
8
|
+
import { type DbRemoteCommandDeps } from "./db-remote-deps.js";
|
|
9
|
+
export declare function registerDbSqlCommand(db: Command, remoteDepsFactory?: () => DbRemoteCommandDeps): void;
|
|
9
10
|
//# sourceMappingURL=db-sql.d.ts.map
|