@indigoai-us/hq-cli 5.231.0 → 5.231.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 CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.231.1] — 2026-09-27
6
+
7
+ ### Fixed
8
+
9
+ - `hq crm entity upsert` checks CRM settings first and prints the enable hint without sending a write when CRM is disabled.
10
+
5
11
  ## [5.231.0] — 2026-09-27
6
12
 
7
13
  ### Added
@@ -19,6 +19,54 @@ const CRM_ENTITY_TYPES = [
19
19
  "invoice",
20
20
  "company",
21
21
  ];
22
+ const CRM_SETTINGS_PRECHECK_TIMEOUT_MS = 3_000;
23
+ const CRM_DISABLED_HINT_PREFIX = "CRM is not enabled for this company. Enable it first: ";
24
+ function printCrmDisabledHint(companySlug) {
25
+ console.error(chalk.red(CRM_DISABLED_HINT_PREFIX +
26
+ `hq company settings set --company ${companySlug} --crm-enabled true`));
27
+ process.exit(1);
28
+ }
29
+ function isRecord(value) {
30
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31
+ }
32
+ /**
33
+ * CRM settings are a best-effort precheck. Only an explicit false prevents the
34
+ * write; unavailable or malformed settings leave hq-pro authoritative.
35
+ */
36
+ async function crmIsExplicitlyDisabled(token, companyUid) {
37
+ try {
38
+ const response = await vaultApiFetch({
39
+ token,
40
+ path: "/company-settings",
41
+ query: { companyUid },
42
+ signal: AbortSignal.timeout(CRM_SETTINGS_PRECHECK_TIMEOUT_MS),
43
+ });
44
+ if (!response.ok) {
45
+ console.error(chalk.red(`CRM settings precheck returned HTTP ${response.status}; continuing to let the server decide.`));
46
+ return false;
47
+ }
48
+ let body;
49
+ try {
50
+ body = await response.json();
51
+ }
52
+ catch (err) {
53
+ const errorName = err instanceof Error ? err.name : "unknown error";
54
+ console.error(chalk.red(`CRM settings precheck returned invalid JSON (${errorName}); continuing to let the server decide.`));
55
+ return false;
56
+ }
57
+ if (!isRecord(body))
58
+ return false;
59
+ const settings = isRecord(body.companySettings)
60
+ ? body.companySettings
61
+ : body;
62
+ return settings.crmEnabled === false;
63
+ }
64
+ catch (err) {
65
+ const errorName = err instanceof Error ? err.name : "unknown error";
66
+ console.error(chalk.red(`CRM settings precheck failed (${errorName}); continuing to let the server decide.`));
67
+ return false;
68
+ }
69
+ }
22
70
  /**
23
71
  * Read the `--json <file|->` payload: a single entity object or an array of
24
72
  * entities. `-` reads from stdin. Returns the entities array (always
@@ -127,6 +175,9 @@ export function registerCrmCommand(program) {
127
175
  }
128
176
  const token = await ensureCognitoToken();
129
177
  const companyUid = await getEntityUid(token, { companySlug });
178
+ if (await crmIsExplicitlyDisabled(token, companyUid)) {
179
+ printCrmDisabledHint(companySlug);
180
+ }
130
181
  const res = await vaultApiFetch({
131
182
  token,
132
183
  path: "/crm/entities",
@@ -137,9 +188,7 @@ export function registerCrmCommand(program) {
137
188
  const body = (await res.json().catch(() => ({})));
138
189
  // CrmDisabledError surfaces as a 403 with a helpful message.
139
190
  if (res.status === 403 && body.code === "CRM_DISABLED") {
140
- console.error(chalk.red("CRM is not enabled for this company. Enable it first: " +
141
- `hq company settings set --company ${companySlug} --crm-enabled true`));
142
- process.exit(1);
191
+ printCrmDisabledHint(companySlug);
143
192
  }
144
193
  console.error(chalk.red(`Failed to upsert entities: ${body.error ?? res.statusText}`));
145
194
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.231.0",
3
+ "version": "5.231.1",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {