@indigoai-us/hq-cli 5.150.0 → 5.151.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/CHANGELOG.md +4 -0
- package/dist/commands/report.d.ts +15 -1
- package/dist/commands/report.js +41 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.151.0] — 2026-09-23
|
|
6
|
+
|
|
7
|
+
- `hq report publish` no longer fails when another app it cannot see holds the report's address. It publishes at the next free address (`<slug>-2`, then `-3`) and saves that address on the report.
|
|
8
|
+
|
|
5
9
|
## [5.150.0] — 2026-09-23
|
|
6
10
|
|
|
7
11
|
### Fixed
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { buildReportTarball, deployOrgContext, type ChannelReport, type DeployAccessPolicy, type ReportDeployment, type ReportPatch } from "../lib/report-publish.js";
|
|
2
|
+
import { buildReportTarball, deployOrgContext, type ChannelReport, type DeployAccessPolicy, type ReportDeployment, type ReportPatch, ReportPublishError } from "../lib/report-publish.js";
|
|
3
3
|
type ChannelRow = {
|
|
4
4
|
channelId?: string;
|
|
5
5
|
scope?: string;
|
|
@@ -17,7 +17,21 @@ export declare function withChannelCompany(report: ChannelReport, channels: Chan
|
|
|
17
17
|
/** Explicit context has priority; discovery is the authenticated fallback for normal CLI use. */
|
|
18
18
|
export declare function resolveReport(token: string, reportId: string, requestedChannelId?: string): Promise<ChannelReport>;
|
|
19
19
|
export declare function patchReport(token: string, report: ChannelReport, patch: ReportPatchInput): Promise<ChannelReport>;
|
|
20
|
+
/** hq-deploy refused the subdomain: another app, not visible to this caller, holds it. */
|
|
21
|
+
export declare class SubdomainTakenError extends ReportPublishError {
|
|
22
|
+
constructor();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Subdomains to try, in order. The first is the report's own slug; the rest
|
|
26
|
+
* are used only when an app the caller cannot see already holds it (for
|
|
27
|
+
* example, one left by an earlier publish under a different account).
|
|
28
|
+
*/
|
|
29
|
+
export declare function candidateSlugs(slug: string, attempts?: number): string[];
|
|
20
30
|
export declare function resolveCompanySlug(token: string, companyUid: string): Promise<string>;
|
|
31
|
+
export declare function findOrCreateApp(token: string, slug: string, org: ReturnType<typeof deployOrgContext>): Promise<{
|
|
32
|
+
id: string;
|
|
33
|
+
subdomain: string;
|
|
34
|
+
}>;
|
|
21
35
|
export declare function deployReportStatic(token: string, input: {
|
|
22
36
|
slug: string;
|
|
23
37
|
files: Parameters<typeof buildReportTarball>[0];
|
package/dist/commands/report.js
CHANGED
|
@@ -232,10 +232,28 @@ async function deployJson(token, route, method, body, extraHeaders = {}) {
|
|
|
232
232
|
catch {
|
|
233
233
|
throw new ReportPublishError("Could not reach hq-deploy.");
|
|
234
234
|
}
|
|
235
|
-
if (!res.ok)
|
|
235
|
+
if (!res.ok) {
|
|
236
|
+
const failure = await res.json().catch(() => ({}));
|
|
237
|
+
if (failure?.error?.code === "SUBDOMAIN_DUPLICATE")
|
|
238
|
+
throw new SubdomainTakenError();
|
|
236
239
|
throw new ReportPublishError("hq-deploy rejected the report deployment.");
|
|
240
|
+
}
|
|
237
241
|
return await res.json();
|
|
238
242
|
}
|
|
243
|
+
/** hq-deploy refused the subdomain: another app, not visible to this caller, holds it. */
|
|
244
|
+
export class SubdomainTakenError extends ReportPublishError {
|
|
245
|
+
constructor() {
|
|
246
|
+
super("hq-deploy rejected the report deployment.");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Subdomains to try, in order. The first is the report's own slug; the rest
|
|
251
|
+
* are used only when an app the caller cannot see already holds it (for
|
|
252
|
+
* example, one left by an earlier publish under a different account).
|
|
253
|
+
*/
|
|
254
|
+
export function candidateSlugs(slug, attempts = 3) {
|
|
255
|
+
return [slug, ...Array.from({ length: attempts }, (_, i) => `${slug}-${i + 2}`)];
|
|
256
|
+
}
|
|
239
257
|
export async function resolveCompanySlug(token, companyUid) {
|
|
240
258
|
const res = await vaultApiFetch({ token, path: `/entity/${encodeURIComponent(companyUid)}` });
|
|
241
259
|
if (!res.ok)
|
|
@@ -250,12 +268,29 @@ async function orgFor(token, report) {
|
|
|
250
268
|
const slug = report.companyUid ? await resolveCompanySlug(token, report.companyUid) : undefined;
|
|
251
269
|
return deployOrgContext(report, slug);
|
|
252
270
|
}
|
|
253
|
-
async function findOrCreateApp(token, slug, org) {
|
|
271
|
+
export async function findOrCreateApp(token, slug, org) {
|
|
254
272
|
const listed = await deployJson(token, "/api/apps", "GET", undefined, org.headers);
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const
|
|
273
|
+
const apps = Array.isArray(listed.apps) ? listed.apps : [];
|
|
274
|
+
const mine = (name) => apps.find((app) => !!app && typeof app === "object" && (app.subdomain === name || app.name === name));
|
|
275
|
+
let app;
|
|
276
|
+
for (const name of candidateSlugs(slug)) {
|
|
277
|
+
const existing = mine(name);
|
|
278
|
+
if (existing) {
|
|
279
|
+
app = existing;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
app = await deployJson(token, "/api/apps", "POST", { name, type: "static" }, org.headers);
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
if (error instanceof SubdomainTakenError)
|
|
288
|
+
continue;
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (!app)
|
|
293
|
+
throw new ReportPublishError("Every address for this report is taken on hq-deploy.");
|
|
259
294
|
const id = typeof app.id === "string" ? app.id : undefined;
|
|
260
295
|
const subdomain = typeof app.subdomain === "string" ? app.subdomain : undefined;
|
|
261
296
|
if (!id || !subdomain)
|