@revfleet/hscli 0.8.4 → 0.8.5

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
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.5 - 2026-04-23
4
+
5
+ **Multi-step workflow creation via CLI — legacy v3 unlock.** The v4
6
+ `/automation/v4/flows` endpoint rejects populated `actions[]` on
7
+ create (500) / update (405), which we previously classified as a
8
+ HubSpot platform block. **It isn't.** HubSpot's legacy v3 API
9
+ (`/automation/v3/workflows`) accepts a fully-populated `actions[]`
10
+ array on create — DELAY, EMAIL, SET_CONTACT_PROPERTY, BRANCH,
11
+ WEBHOOK, UPDATE_LIST, TASK, TICKET, DEAL, NOTIFICATION — and
12
+ workflows created via v3 are dual-backed: they surface in v4
13
+ (`migrationStatus.flowId`) and render in HubSpot's modern canvas UI
14
+ with all action nodes visible. Verified live on portal 147975758
15
+ with a 5-step welcome onboarding flow (Trigger → Delay → Send email
16
+ → Delay → Set property → Branch).
17
+
18
+ ### Added
19
+
20
+ - **`hscli workflows v3`** subcommand suite:
21
+ - `v3 list` / `v3 get <id>` — read legacy workflows (includes full
22
+ `actions[]` tree, which v4 GET omits).
23
+ - `v3 create --data '{...}'` — create contact-based workflow with
24
+ populated multi-step actions. One CLI call replaces an entire
25
+ clicking-through-canvas UI session.
26
+ - `v3 delete <id>` — archive a workflow.
27
+ - `v3 enroll <id> <email>` / `v3 unenroll <id> <email>` — manage
28
+ contact enrollment (automation membership).
29
+ - `v3 enrollments <email>` — list a contact's current workflow
30
+ memberships.
31
+
32
+ ### Fixes
33
+
34
+ - **[docs/CAPABILITY_LIBRARY.md](docs/CAPABILITY_LIBRARY.md)** §5
35
+ Automation — workflow-action creation reclassified from ❌
36
+ "API-locked" to ✅ via v3. Full `type`-value catalogue added.
37
+ §10 blocked-list entry amended: the ❌ on v4 remains, but v3
38
+ provides the missing workaround.
39
+
3
40
  ## 0.8.4 - 2026-04-23
4
41
 
5
42
  **Drag-and-drop library access + polish.** A batch of capability-surface
@@ -1,5 +1,23 @@
1
1
  /**
2
- * `hscli workflows` — v4 flows + legacy v2/v3 workflow enrollment.
2
+ * `hscli workflows` — v4 flows + legacy v3 workflows.
3
+ *
4
+ * Two workflow APIs ship side-by-side on every Marketing-Hub portal:
5
+ *
6
+ * - **v4 `/automation/v4/flows`** (current) — returns 500 on POST
7
+ * with populated `actions[]` (schema undocumented; verified
8
+ * 2026-04-23). Works for create-metadata + enrollment triggers
9
+ * only.
10
+ * - **v3 `/automation/v3/workflows`** (legacy, still live) —
11
+ * **accepts a populated `actions[]` array with DELAY,
12
+ * SET_CONTACT_PROPERTY, BRANCH, EMAIL, WEBHOOK,
13
+ * UPDATE_LIST, TASK, TICKET, DEAL, NOTIFICATION, WEBHOOK,
14
+ * and more.** Workflows created via v3 are dual-backed: they
15
+ * surface in v4 (`migrationStatus.flowId`) and render in the
16
+ * modern HubSpot canvas UI with visible action nodes.
17
+ *
18
+ * Use `hscli workflows flows` for the v4 surface (enrollment criteria
19
+ * + metadata) and `hscli workflows v3` for creating multi-step
20
+ * workflows with real action nodes.
3
21
  */
4
22
  import { Command } from "commander";
5
23
  import type { CliContext } from "../../core/output.js";
@@ -1,13 +1,93 @@
1
+ import { createClient } from "../../core/http.js";
2
+ import { printResult } from "../../core/output.js";
1
3
  import { registerResource } from "../domains/shared.js";
4
+ import { encodePathSegment, maybeWrite, parseJsonPayload, parseNumberFlag } from "../crm/shared.js";
2
5
  export function registerWorkflows(program, getCtx) {
3
6
  const workflows = program.command("workflows").description("HubSpot Workflow Automation APIs");
4
7
  registerResource(workflows, getCtx, {
5
8
  name: "flows",
6
- description: "Automation flows",
9
+ description: "Automation flows (v4 API)",
7
10
  listPath: "/automation/v4/flows",
8
11
  itemPath: (id) => `/automation/v4/flows/${id}`,
9
12
  createPath: "/automation/v4/flows",
10
13
  updatePath: (id) => `/automation/v4/flows/${id}`,
11
14
  });
15
+ // Legacy v3 workflows — the only public API that accepts
16
+ // populated multi-step actions on create. Contact-based only.
17
+ const v3 = workflows.command("v3").description("Legacy v3 workflows API (accepts populated actions[] — contact-based only)");
18
+ v3.command("list")
19
+ .option("--limit <n>", "Max workflows (client-side cap; endpoint returns all)", "50")
20
+ .description("List all v3 workflows")
21
+ .action(async (o) => {
22
+ const ctx = getCtx();
23
+ const client = createClient(ctx.profile);
24
+ const limit = parseNumberFlag(o.limit, "--limit");
25
+ const res = (await client.request(`/automation/v3/workflows`));
26
+ const workflowsArr = (res.workflows) || (res.data?.workflows) || [];
27
+ printResult(ctx, { total: workflowsArr.length, workflows: workflowsArr.slice(0, limit) });
28
+ });
29
+ v3.command("get")
30
+ .argument("<workflowId>")
31
+ .description("Get a v3 workflow by id (includes full actions tree)")
32
+ .action(async (workflowId) => {
33
+ const ctx = getCtx();
34
+ const client = createClient(ctx.profile);
35
+ const id = encodePathSegment(workflowId, "workflowId");
36
+ const res = await client.request(`/automation/v3/workflows/${id}`);
37
+ printResult(ctx, res);
38
+ });
39
+ v3.command("create")
40
+ .requiredOption("--data <payload>", "JSON payload. Required: name, type (DRIP_DELAY|STATIC_ANCHOR|PROPERTY_ANCHOR), actions[]. Actions support: DELAY, SET_CONTACT_PROPERTY, BRANCH, EMAIL, WEBHOOK, UPDATE_LIST, TASK, TICKET, DEAL, NOTIFICATION. See https://legacydocs.hubspot.com/docs/methods/workflows/v3/create_workflow")
41
+ .description("Create a v3 workflow with populated actions (multi-step)")
42
+ .action(async (o) => {
43
+ const ctx = getCtx();
44
+ const client = createClient(ctx.profile);
45
+ const res = await maybeWrite(ctx, client, "POST", `/automation/v3/workflows`, parseJsonPayload(o.data));
46
+ printResult(ctx, res);
47
+ });
48
+ v3.command("delete")
49
+ .argument("<workflowId>")
50
+ .description("Delete a v3 workflow")
51
+ .action(async (workflowId) => {
52
+ const ctx = getCtx();
53
+ const client = createClient(ctx.profile);
54
+ const id = encodePathSegment(workflowId, "workflowId");
55
+ const res = await maybeWrite(ctx, client, "DELETE", `/automation/v3/workflows/${id}`);
56
+ printResult(ctx, res);
57
+ });
58
+ v3.command("enroll")
59
+ .argument("<workflowId>")
60
+ .argument("<email>")
61
+ .description("Enroll a contact (by email) in a v3 workflow")
62
+ .action(async (workflowId, email) => {
63
+ const ctx = getCtx();
64
+ const client = createClient(ctx.profile);
65
+ const id = encodePathSegment(workflowId, "workflowId");
66
+ const e = encodePathSegment(email, "email");
67
+ const res = await maybeWrite(ctx, client, "POST", `/automation/v3/workflows/${id}/enrollments/contacts/${e}`);
68
+ printResult(ctx, res);
69
+ });
70
+ v3.command("unenroll")
71
+ .argument("<workflowId>")
72
+ .argument("<email>")
73
+ .description("Remove a contact (by email) from a v3 workflow")
74
+ .action(async (workflowId, email) => {
75
+ const ctx = getCtx();
76
+ const client = createClient(ctx.profile);
77
+ const id = encodePathSegment(workflowId, "workflowId");
78
+ const e = encodePathSegment(email, "email");
79
+ const res = await maybeWrite(ctx, client, "DELETE", `/automation/v3/workflows/${id}/enrollments/contacts/${e}`);
80
+ printResult(ctx, res);
81
+ });
82
+ v3.command("enrollments")
83
+ .argument("<email>")
84
+ .description("Get current workflow enrollments for a contact (by email)")
85
+ .action(async (email) => {
86
+ const ctx = getCtx();
87
+ const client = createClient(ctx.profile);
88
+ const e = encodePathSegment(email, "email");
89
+ const res = await client.request(`/automation/v3/contacts/${e}/workflowEnrollments`);
90
+ printResult(ctx, res);
91
+ });
12
92
  }
13
93
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/workflows/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,UAAU,iBAAiB,CAAC,OAAgB,EAAE,MAAwB;IAC1E,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC;IAE/F,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE;QAClC,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,kBAAkB;QAC/B,QAAQ,EAAE,sBAAsB;QAChC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,wBAAwB,EAAE,EAAE;QAC9C,UAAU,EAAE,sBAAsB;QAClC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,wBAAwB,EAAE,EAAE;KACjD,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/workflows/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revfleet/hscli",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "Agentic HubSpot CLI + MCP server. 100% public API coverage (1180 endpoints, 55+ command domains) — full portal, no UI dependency. Enterprise safety rails, self-hosted.",
5
5
  "type": "module",
6
6
  "bin": {