@koda-sl/baker-cli 0.208.1 → 0.209.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/README.md CHANGED
@@ -3000,7 +3000,7 @@ baker history list --category ads --full # ad writes with raw metadata
3000
3000
 
3001
3001
  ---
3002
3002
 
3003
- ### `baker hubspot forms list | view | submissions` · `baker hubspot workflows list` · `baker hubspot pipelines list` · `baker hubspot contacts summary | lookup` · `baker hubspot meetings list | view`
3003
+ ### `baker hubspot forms list | view | submissions` · `baker hubspot workflows list | view` · `baker hubspot pipelines list` · `baker hubspot contacts summary | lookup` · `baker hubspot meetings list | view`
3004
3004
 
3005
3005
  Read-only view of the company's **connected HubSpot account** — the forms and meeting links (calendars) that live there, the leads those forms received, and the workflows, deal pipelines, and contact records a lead runs through afterwards. Fetched from HubSpot live on every call; nothing is cached and nothing is ever written back.
3006
3006
 
@@ -3016,6 +3016,8 @@ baker hubspot forms view <formId> --as-node # the form.external blob for a f
3016
3016
  baker hubspot forms submissions <formId> # how many leads it received, and when
3017
3017
  baker hubspot forms submissions <formId> --days 90 --full
3018
3018
  baker hubspot workflows list --enabled-only # what runs after a lead is captured
3019
+ baker hubspot workflows view <workflowId> # enrolment, branches in order, what each step writes
3020
+ baker hubspot workflows view <workflowId> --full # + the values each branch compares
3019
3021
  baker hubspot pipelines list # where a lead lands, and the stages after it
3020
3022
  baker hubspot contacts summary --days 30 # are recent leads being worked? (counts only)
3021
3023
  baker hubspot contacts lookup lead@example.com # was this one lead picked up?
@@ -3028,6 +3030,7 @@ baker hubspot meetings view <slug> --as-node # the form.external blob for a f
3028
3030
  **`forms view`:** positional `<formId>`; `--full` adds the untouched HubSpot payload; `--as-node` returns the resource blob instead of the readable view.
3029
3031
  **`forms submissions`:** positional `<formId>`; `--days <1-365>` (default 30) sets the window; `--full` adds each submission's field values. The default response is counts and dates only — `total`, `inWindow`, `lastSubmittedAt`, and per-day counts — because submissions carry the lead's own contact details. `truncated: true` means the page budget ran out before the window was covered, so `inWindow` is a floor rather than an exact count.
3030
3032
  **`workflows list` flags:** `--search <text>`, `--enabled-only`. Disabled workflows are listed too — a form wired to one that is off looks connected and does nothing.
3033
+ **`workflows view`:** positional `<workflowId>` (the id from `workflows list`, and the one in HubSpot's own URL — the command translates it to HubSpot's separate internal flow id for you). Returns the enrolment criteria and whether it re-enrols (`null` = HubSpot does not report it for that criteria type, so it is unknown rather than off), plus every step with the property it writes. On a `LIST_BRANCH` step, branches come back in **evaluation order** (`order: 1` wins over `order: 2`) — a broad branch above a narrower one silently swallows the records the narrow one was written for, and HubSpot reports nothing. A `STATIC_BRANCH` matches on a value rather than top down, so its `order` is display only. `steps` is **not** in execution order; follow `nextActionId`. `--full` adds the raw payload, the only place the branch filter criteria (which property is compared to which value) can be read.
3031
3034
  **`pipelines list`:** no flags; stages come back in the order they run in HubSpot.
3032
3035
  **`contacts summary` flags:** `--days <1-365>` (default 30) over contact creation date. Returns counts only — total contacts, how many have an owner, and the lifecycle-stage split — never a name or an email. `truncated: true` means the page budget ran out, so the counts are floors.
3033
3036
  **`contacts lookup`:** positional `<email>`; returns that contact's lifecycle stage, owner, the account (company) it was filed under, and associated deals with their stage. `dealsReadable: false` / `companyReadable: false` mean the connection does not cover deals or accounts, so an empty `deals` or a null `company` is unknown rather than absent. `found: false` means no contact with that email — the lead never reached the CRM, which is a finding rather than an error.
package/dist/cli.js CHANGED
@@ -4794,6 +4794,60 @@ var hubspotWorkflowsListResponseSchema = z12.object({
4794
4794
  ok: z12.literal(true),
4795
4795
  data: z12.object({ workflows: z12.array(hubspotWorkflowSummarySchema) })
4796
4796
  });
4797
+ var hubspotWorkflowsViewRequestSchema = z12.object({
4798
+ /** The id from `workflows list`. Resolved to HubSpot's internal flow id server-side. */
4799
+ workflowId: z12.string().min(1),
4800
+ /**
4801
+ * Include the untouched HubSpot payload — the only place the branch filter
4802
+ * criteria (which property is compared to which value) can be read.
4803
+ */
4804
+ full: z12.boolean().optional()
4805
+ });
4806
+ var hubspotWorkflowBranchSchema = z12.object({
4807
+ /**
4808
+ * 1-based position in the order HubSpot lists the branches. On a `LIST_BRANCH`
4809
+ * that is precedence — branch 1 wins over branch 2. On a `STATIC_BRANCH` it is
4810
+ * only display order; those match on the value in `name`, not top down.
4811
+ */
4812
+ order: z12.number().int(),
4813
+ name: z12.string(),
4814
+ nextActionId: z12.string().nullable()
4815
+ });
4816
+ var hubspotWorkflowStepSchema = z12.object({
4817
+ actionId: z12.string(),
4818
+ /** HubSpot's action kind: LIST_BRANCH, SINGLE_CONNECTION, CUSTOM_CODE, WEBHOOK... */
4819
+ type: z12.string(),
4820
+ actionTypeId: z12.string().nullable(),
4821
+ /** The step's configured inputs — for a property-setting step, what it writes and where. */
4822
+ fields: z12.record(z12.string(), z12.unknown()).nullable(),
4823
+ nextActionId: z12.string().nullable(),
4824
+ /** Present only on branch steps, in evaluation order. */
4825
+ branches: z12.array(hubspotWorkflowBranchSchema).nullable(),
4826
+ defaultBranch: z12.object({ name: z12.string().nullable(), nextActionId: z12.string().nullable() }).nullable()
4827
+ });
4828
+ var hubspotWorkflowDetailSchema = z12.object({
4829
+ /** HubSpot's internal flow id, which differs from the workflow id. */
4830
+ id: z12.string(),
4831
+ /** The id this workflow is known by in `workflows list` and in HubSpot's own URLs. */
4832
+ workflowId: z12.string(),
4833
+ name: z12.string(),
4834
+ enabled: z12.boolean(),
4835
+ flowType: z12.string().nullable(),
4836
+ /** The record type it runs on: "0-1" contacts, "0-2" companies, "0-3" deals. */
4837
+ objectTypeId: z12.string().nullable(),
4838
+ enrollment: z12.object({
4839
+ type: z12.string().nullable(),
4840
+ /** Null means HubSpot's criteria shape does not report it — unknown, not off. */
4841
+ reEnrollment: z12.boolean().nullable()
4842
+ }),
4843
+ /** Every step. Execution order follows `nextActionId`, not the array index. */
4844
+ steps: z12.array(hubspotWorkflowStepSchema),
4845
+ raw: z12.record(z12.string(), z12.unknown()).optional()
4846
+ });
4847
+ var hubspotWorkflowsViewResponseSchema = z12.object({
4848
+ ok: z12.literal(true),
4849
+ data: z12.object({ workflow: hubspotWorkflowDetailSchema })
4850
+ });
4797
4851
  var hubspotContactsSummaryRequestSchema = z12.object({
4798
4852
  /** Window in days, counted back from now, over contact creation date. */
4799
4853
  days: z12.number().int().min(1).max(365).default(30)
@@ -29872,6 +29926,23 @@ registerSchema({
29872
29926
  "enabled-only": { type: "boolean", description: "Only workflows that are on", required: false, default: false }
29873
29927
  }
29874
29928
  });
29929
+ registerSchema({
29930
+ command: "hubspot.workflows.view",
29931
+ description: "One workflow's actual configuration: what enrols a record, whether it re-enrols, and every step with the property it writes. Read it before saying a workflow is correct \u2014 `workflows list` only tells you it exists and whether it is on. Branches come back in HubSpot's order, and on a LIST_BRANCH step that is evaluation order (`order: 1` wins over `order: 2`) \u2014 which is where this kind of setup silently breaks: a broad branch placed above a narrow one swallows the records the narrow one was written for, and nothing reports it. A STATIC_BRANCH matches on a value instead, so its order carries no precedence. Steps are NOT in execution order \u2014 follow `nextActionId` from step to step. Add --full for the branch filter criteria (which property is compared to which value).",
29932
+ args: {
29933
+ workflowId: {
29934
+ type: "positional",
29935
+ description: "Workflow id (from `baker hubspot workflows list`)",
29936
+ required: true
29937
+ },
29938
+ full: {
29939
+ type: "boolean",
29940
+ description: "Include the raw HubSpot payload \u2014 the only place the branch filter criteria can be read",
29941
+ required: false,
29942
+ default: false
29943
+ }
29944
+ }
29945
+ });
29875
29946
  registerSchema({
29876
29947
  command: "hubspot.pipelines.list",
29877
29948
  description: "The account's deal pipelines and their stages, in the order they run. Use it to answer where a lead lands once captured and whether it moved \u2014 the 'have these leads been worked?' half of a form audit.",
@@ -30171,6 +30242,62 @@ var workflowsListCommand = defineCommand120({
30171
30242
  }
30172
30243
  }
30173
30244
  });
30245
+ function workflowViewHints(workflow) {
30246
+ const hints = [];
30247
+ if (!workflow.enabled) {
30248
+ hints.push(
30249
+ "This workflow is switched off, so nothing below it is running now \u2014 it may still have run while it was on. Say so before reporting on what it does."
30250
+ );
30251
+ }
30252
+ const ordered = workflow.steps.filter((step) => step.type === "LIST_BRANCH" && (step.branches?.length ?? 0) > 1);
30253
+ if (ordered.length > 0) {
30254
+ hints.push(
30255
+ "Branches are listed in evaluation order and the first match wins. Check that no broad branch sits above a narrower one \u2014 if it does, the narrow branch never runs and nothing in HubSpot reports it."
30256
+ );
30257
+ }
30258
+ if (workflow.raw === void 0 && ordered.length > 0) {
30259
+ hints.push(
30260
+ "This view names the branches but not what they compare. Re-run with --full to read the filter criteria before judging whether a branch matches what it was meant to match."
30261
+ );
30262
+ }
30263
+ if (workflow.enrollment.reEnrollment === false) {
30264
+ hints.push(
30265
+ "Re-enrolment is off: a record that meets the criteria a second time will not run through this again. That is a real choice, not necessarily a fault \u2014 but confirm it is the intended one."
30266
+ );
30267
+ } else if (workflow.enrollment.reEnrollment === null) {
30268
+ hints.push(
30269
+ "Whether this re-enrols is not reported for this kind of enrolment, so do not state it either way \u2014 read it in HubSpot if it matters."
30270
+ );
30271
+ }
30272
+ return hints;
30273
+ }
30274
+ var workflowsViewCommand = defineCommand120({
30275
+ meta: {
30276
+ name: "view",
30277
+ description: "Read one workflow's real configuration \u2014 enrolment, branches in order, and what each step writes. Example: baker hubspot workflows view 121183594 --full"
30278
+ },
30279
+ args: {
30280
+ workflowId: {
30281
+ type: "positional",
30282
+ description: "Workflow id (from `baker hubspot workflows list`)",
30283
+ required: true
30284
+ },
30285
+ full: { type: "boolean", description: "Include the raw HubSpot payload with the filter criteria", required: false }
30286
+ },
30287
+ run: async ({ args }) => {
30288
+ try {
30289
+ const response = await apiPost("/api/hubspot/workflows/view", {
30290
+ workflowId: args.workflowId,
30291
+ ...args.full ? { full: true } : {}
30292
+ });
30293
+ const { workflow } = response.data;
30294
+ const hints = workflowViewHints(workflow);
30295
+ writeJson({ ...response, meta: { count: workflow.steps.length }, ...hints.length > 0 ? { hints } : {} });
30296
+ } catch (err) {
30297
+ failNotConnected(err);
30298
+ }
30299
+ }
30300
+ });
30174
30301
  var pipelinesListCommand = defineCommand120({
30175
30302
  meta: {
30176
30303
  name: "list",
@@ -30292,7 +30419,7 @@ var formsCommand = defineCommand120({
30292
30419
  });
30293
30420
  var workflowsCommand = defineCommand120({
30294
30421
  meta: { name: "workflows", description: "HubSpot workflows on the connected account." },
30295
- subCommands: { list: workflowsListCommand }
30422
+ subCommands: { list: workflowsListCommand, view: workflowsViewCommand }
30296
30423
  });
30297
30424
  var pipelinesCommand = defineCommand120({
30298
30425
  meta: { name: "pipelines", description: "HubSpot deal pipelines on the connected account." },
@@ -30315,6 +30442,7 @@ Examples:
30315
30442
  baker hubspot forms view <formId> --as-node # the form.external blob -> write into the step
30316
30443
  baker hubspot forms submissions <formId> # how many leads it got, and when
30317
30444
  baker hubspot workflows list --enabled-only # what runs after a lead is captured
30445
+ baker hubspot workflows view <workflowId> # its real branches, in order, and what each step writes
30318
30446
  baker hubspot pipelines list # where a lead lands, and the stages after it
30319
30447
  baker hubspot contacts summary --days 30 # are recent leads being worked? (counts only)
30320
30448
  baker hubspot contacts lookup a@b.com # was this one lead picked up?