@intercom/cli 0.8.2 → 0.9.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.js +225 -43
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  View it from the CLI with `intercom changelog`.
9
9
 
10
+ ## [0.9.0] - 2026-07-03
11
+
12
+ ### Added
13
+
14
+ - `fin attributes upload <file>` creates or updates Fin custom attributes from a YAML file. Attributes were previously read-only (`list`). The file can be a list of attributes, a single attribute, or the full `type: attribute` / `attributes:` server shape — the CLI normalizes it and sets the routing type for you. Each attribute needs a dotted `name` (e.g. `user.order_status`) and a data `type` (`string`, `integer`, `decimal`, `float`, `boolean`, `list`, `date`, `object`, or `array`).
15
+ - `fin procedures get <id> [output] --with-simulations` downloads a procedure's simulations alongside it. With the flag, `[output]` is a directory (default: current directory) and the CLI writes both `procedure.yaml` and `simulations.yaml`. Without it, `[output]` is a single file for the procedure YAML (previously `get` could only print to stdout).
16
+ - `fin simulations upload <file>` re-uploads a simulation set (the `simulations.yaml` written by `fin procedures get --with-simulations`, or `fin simulations list` output), completing the export/edit/re-import round-trip for a procedure's tests.
17
+
18
+ ## [0.8.3] - 2026-06-18
19
+
20
+ ### Fixed
21
+
22
+ - `fin workflows upload` now works with workflow YAML that doesn't declare a top-level `type:`. The upload endpoint is shared with procedures and routes by that field, so a workflow file without `type: workflow` was being validated as a procedure (`object at root is missing required properties: name, trigger_description, procedure`). The CLI now sets `type: workflow` for you when it's absent.
23
+ - `fin workflows enable` and `fin workflows disable` no longer fail with `Resource not found`. They re-upload the workflow after changing its state, and the re-uploaded YAML was missing `type: workflow`, so the server looked for a procedure with that id and 404'd. The state-change upload now carries `type: workflow`.
24
+ - `fin workflows get <id>` now prints the workflow as YAML (the format `upload` expects) instead of a lossy JSON summary, and accepts an optional output file: `intercom fin workflows get 42 workflow.yaml`. `--json` still returns parsed JSON.
25
+
10
26
  ## [0.8.2] - 2026-06-17
11
27
 
12
28
  ### Fixed
package/dist/index.js CHANGED
@@ -2569,8 +2569,8 @@ Examples:
2569
2569
  import { writeFile as writeFile3 } from "fs/promises";
2570
2570
 
2571
2571
  // src/commands/fin/procedures.ts
2572
- import { readFile as readFile2 } from "fs/promises";
2573
- import { basename } from "path";
2572
+ import { readFile as readFile2, mkdir as mkdir2 } from "fs/promises";
2573
+ import { basename, join as join3 } from "path";
2574
2574
  import AdmZip from "adm-zip";
2575
2575
  function registerProceduresCommand(fin) {
2576
2576
  const procedures = fin.command("procedures").description("Manage Fin SDK procedures");
@@ -2591,7 +2591,21 @@ function registerProceduresCommand(fin) {
2591
2591
  return table({ columns: ["ID", "NAME"], rows });
2592
2592
  }, items);
2593
2593
  });
2594
- procedures.command("get <id>").description("Download a procedure by ID and print its YAML content").option("--verbose", "Show HTTP request/response details").action(async function(id) {
2594
+ procedures.command("get <id> [output]").description("Download a procedure by ID as YAML (writes to [output], or stdout)").option("--with-simulations", "Also download the procedure's simulations").option("--verbose", "Show HTTP request/response details").addHelpText(
2595
+ "after",
2596
+ `
2597
+ Examples:
2598
+ $ intercom fin procedures get proc-1 # print YAML to stdout
2599
+ $ intercom fin procedures get proc-1 procedure.yaml # write YAML to a file
2600
+ $ intercom fin procedures get proc-1 ./out --with-simulations
2601
+ # writes ./out/procedure.yaml and ./out/simulations.yaml
2602
+
2603
+ With --with-simulations, [output] is treated as a directory (default: current
2604
+ directory). Without it, [output] is a single file for the procedure YAML.
2605
+
2606
+ Re-import the pieces with \`intercom fin procedures upload <procedure.yaml>\`
2607
+ and \`intercom fin simulations upload <simulations.yaml>\`.`
2608
+ ).action(async function(id, output) {
2595
2609
  const opts = this.optsWithGlobals();
2596
2610
  const client = await resolveClient(opts);
2597
2611
  const buffer = await client.getBuffer(`/fin-sdk/procedures/${id}/download`);
@@ -2600,7 +2614,28 @@ function registerProceduresCommand(fin) {
2600
2614
  if (!entry) {
2601
2615
  throw new Error("procedure.yaml not found in downloaded ZIP");
2602
2616
  }
2603
- console.log(zip.readAsText(entry));
2617
+ const procedureYaml = zip.readAsText(entry);
2618
+ let simulationsYaml;
2619
+ if (opts.withSimulations) {
2620
+ simulationsYaml = await client.getText(`/fin-sdk/procedures/${id}/simulations`);
2621
+ }
2622
+ if (opts.withSimulations) {
2623
+ const dir = output ?? ".";
2624
+ await mkdir2(dir, { recursive: true });
2625
+ const procedurePath = join3(dir, "procedure.yaml");
2626
+ const simulationsPath = join3(dir, "simulations.yaml");
2627
+ await atomicWriteFile(procedurePath, procedureYaml, 420);
2628
+ await atomicWriteFile(simulationsPath, simulationsYaml ?? "", 420);
2629
+ console.error(`Wrote procedure ${id} to ${procedurePath}`);
2630
+ console.error(`Wrote simulations to ${simulationsPath}`);
2631
+ return;
2632
+ }
2633
+ if (output) {
2634
+ await atomicWriteFile(output, procedureYaml, 420);
2635
+ console.error(`Wrote procedure ${id} to ${output}`);
2636
+ } else {
2637
+ console.log(procedureYaml);
2638
+ }
2604
2639
  });
2605
2640
  procedures.command("upload <file>").description("Upload a procedure file to Fin SDK").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function(filePath) {
2606
2641
  const opts = this.optsWithGlobals();
@@ -2766,6 +2801,29 @@ Optional fields: state (live or paused, default: paused), audiences`
2766
2801
  }
2767
2802
 
2768
2803
  // src/commands/fin/attributes.ts
2804
+ import { readFile as readFile3 } from "fs/promises";
2805
+ import { basename as basename2 } from "path";
2806
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
2807
+ var ATTRIBUTE_TYPE = "attribute";
2808
+ function buildAttributesUploadBody(raw) {
2809
+ let parsed;
2810
+ try {
2811
+ parsed = parseYaml(raw);
2812
+ } catch {
2813
+ return raw;
2814
+ }
2815
+ if (Array.isArray(parsed)) {
2816
+ return stringifyYaml({ type: ATTRIBUTE_TYPE, attributes: parsed });
2817
+ }
2818
+ if (parsed == null || typeof parsed !== "object") {
2819
+ return raw;
2820
+ }
2821
+ const obj = parsed;
2822
+ if (Array.isArray(obj.attributes)) {
2823
+ return stringifyYaml({ ...obj, type: ATTRIBUTE_TYPE });
2824
+ }
2825
+ return stringifyYaml({ type: ATTRIBUTE_TYPE, attributes: [obj] });
2826
+ }
2769
2827
  function registerAttributesCommand(fin) {
2770
2828
  const attributes = fin.command("attributes").description("Manage Fin SDK attributes");
2771
2829
  attributes.command("list").description("List Fin SDK attributes").option("--json", "Output as JSON").option("--verbose", "Show HTTP request/response details").action(async function() {
@@ -2785,6 +2843,49 @@ function registerAttributesCommand(fin) {
2785
2843
  return table({ columns: ["NAME", "TYPE", "DESCRIPTION"], rows });
2786
2844
  }, items);
2787
2845
  });
2846
+ attributes.command("upload <file>").description("Upload attributes from a YAML file (creates or updates)").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").addHelpText(
2847
+ "after",
2848
+ `
2849
+ The file holds one or more attributes. The CLI wraps them in the bulk shape the
2850
+ server expects and sets the routing type for you, so any of these work:
2851
+
2852
+ # a list of attributes
2853
+ - name: user.order_status # name must contain a dot
2854
+ type: string # data type: string, integer, decimal, float,
2855
+ description: Order state # boolean, list, date, object, or array
2856
+
2857
+ # ...or a single attribute
2858
+ name: company.tier
2859
+ type: string
2860
+
2861
+ # ...or the full server shape
2862
+ type: attribute
2863
+ attributes:
2864
+ - name: user.order_status
2865
+ type: string
2866
+
2867
+ Examples:
2868
+ $ intercom fin attributes upload ./attributes.yaml
2869
+ $ intercom fin attributes upload ./attributes.yaml --json`
2870
+ ).action(async function(filePath) {
2871
+ const opts = this.optsWithGlobals();
2872
+ const client = await resolveClient(opts);
2873
+ const fileContent = await readFile3(filePath, "utf8");
2874
+ const yamlBody = buildAttributesUploadBody(fileContent);
2875
+ const formData = new FormData();
2876
+ const blob = new Blob([yamlBody], { type: "application/x-yaml" });
2877
+ formData.append("file_data", blob, basename2(filePath));
2878
+ const result = await client.postFormData("/fin-sdk/upload", formData);
2879
+ render(
2880
+ result,
2881
+ opts,
2882
+ () => detail({
2883
+ "ID": result.id != null ? String(result.id) : void 0,
2884
+ "Type": result.type != null ? String(result.type) : void 0,
2885
+ "Message": result.message != null ? String(result.message) : void 0
2886
+ })
2887
+ );
2888
+ });
2788
2889
  }
2789
2890
 
2790
2891
  // src/commands/fin/audiences.ts
@@ -2809,11 +2910,29 @@ function registerAudiencesCommand(fin) {
2809
2910
  }
2810
2911
 
2811
2912
  // src/commands/fin/workflows.ts
2812
- import { readFile as readFile3 } from "fs/promises";
2813
- import { basename as basename2 } from "path";
2814
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
2913
+ import { readFile as readFile4 } from "fs/promises";
2914
+ import { basename as basename3 } from "path";
2915
+ import { parse as parseYaml2, stringify as stringifyYaml2 } from "yaml";
2815
2916
  var STATE_LIVE = "live";
2816
2917
  var STATE_PAUSED = "paused";
2918
+ var WORKFLOW_TYPE = "workflow";
2919
+ function ensureWorkflowType(raw) {
2920
+ let parsed;
2921
+ try {
2922
+ parsed = parseYaml2(raw);
2923
+ } catch {
2924
+ return raw;
2925
+ }
2926
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
2927
+ return raw;
2928
+ }
2929
+ const obj = parsed;
2930
+ if (obj.type != null && obj.type !== "") {
2931
+ return raw;
2932
+ }
2933
+ obj.type = WORKFLOW_TYPE;
2934
+ return stringifyYaml2(obj);
2935
+ }
2817
2936
  function registerWorkflowsCommand(fin) {
2818
2937
  const workflows = fin.command("workflows").description("Manage Fin SDK workflows");
2819
2938
  workflows.command("list").description("List Fin SDK workflows").option("--json", "Output as JSON").option("--verbose", "Show HTTP request/response details").action(async function() {
@@ -2834,22 +2953,31 @@ function registerWorkflowsCommand(fin) {
2834
2953
  return table({ columns: ["ID", "TITLE", "STATE", "TRIGGER"], rows });
2835
2954
  }, items);
2836
2955
  });
2837
- workflows.command("get <id>").description("Get a workflow by ID").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").action(async function(id) {
2956
+ workflows.command("get <id> [output]").description("Get a workflow by ID as YAML (writes to [output] file, or stdout)").option("--json", "Output as parsed JSON instead of YAML").option("--jq <expr>", "Filter parsed-JSON output with a jq expression").option("--verbose", "Show HTTP request/response details").addHelpText(
2957
+ "after",
2958
+ `
2959
+ Examples:
2960
+ $ intercom fin workflows get 42 workflow.yaml # write YAML to a file
2961
+ $ intercom fin workflows get 42 > workflow.yaml # or redirect stdout
2962
+ $ intercom fin workflows get 42 --json | jq .state
2963
+
2964
+ The YAML it prints is ready to edit and re-upload with
2965
+ \`intercom fin workflows upload\`.`
2966
+ ).action(async function(id, output) {
2838
2967
  const opts = this.optsWithGlobals();
2839
2968
  const client = await resolveClient(opts);
2840
2969
  const text = await client.getText(`/fin-sdk/workflows/${id}`);
2841
- const parsed = parseYaml(text);
2842
- render(
2843
- parsed,
2844
- opts,
2845
- () => detail({
2846
- "ID": String(parsed.id ?? ""),
2847
- "Title": String(parsed.title ?? ""),
2848
- "State": String(parsed.state ?? ""),
2849
- "Version": parsed.version != null ? String(parsed.version) : void 0,
2850
- "Trigger": parsed.trigger_type != null ? String(parsed.trigger_type) : void 0
2851
- })
2852
- );
2970
+ if (opts.json || opts.jq || opts.agent) {
2971
+ const parsed = parseYaml2(text);
2972
+ render(parsed, opts, () => formatJson(parsed));
2973
+ return;
2974
+ }
2975
+ if (output) {
2976
+ await atomicWriteFile(output, text, 420);
2977
+ console.error(`Wrote workflow ${id} to ${output}`);
2978
+ } else {
2979
+ console.log(text.replace(/\n+$/, ""));
2980
+ }
2853
2981
  });
2854
2982
  workflows.command("upload <file>").description('Upload a workflow YAML file (creates if id is "new", updates if numeric)').option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").addHelpText(
2855
2983
  "after",
@@ -2865,10 +2993,11 @@ The YAML file's id field determines whether this creates or updates:
2865
2993
  ).action(async function(filePath) {
2866
2994
  const opts = this.optsWithGlobals();
2867
2995
  const client = await resolveClient(opts);
2868
- const fileContent = await readFile3(filePath);
2996
+ const fileContent = await readFile4(filePath, "utf8");
2997
+ const yamlBody = ensureWorkflowType(fileContent);
2869
2998
  const formData = new FormData();
2870
- const blob = new Blob([fileContent], { type: "application/x-yaml" });
2871
- formData.append("file_data", blob, basename2(filePath));
2999
+ const blob = new Blob([yamlBody], { type: "application/x-yaml" });
3000
+ formData.append("file_data", blob, basename3(filePath));
2872
3001
  const result = await client.postFormData("/fin-sdk/upload", formData);
2873
3002
  render(
2874
3003
  result,
@@ -2897,12 +3026,13 @@ overwritten (the server does not expose a concurrency token).`
2897
3026
  const text = await client.getText(`/fin-sdk/workflows/${id}`);
2898
3027
  let parsed;
2899
3028
  try {
2900
- parsed = parseYaml(text);
3029
+ parsed = parseYaml2(text);
2901
3030
  } catch (err) {
2902
3031
  throw new Error(`server returned unparseable YAML for workflow ${id}: ${err.message}`);
2903
3032
  }
3033
+ parsed.type = WORKFLOW_TYPE;
2904
3034
  parsed.state = STATE_LIVE;
2905
- const yamlBody = stringifyYaml(parsed);
3035
+ const yamlBody = stringifyYaml2(parsed);
2906
3036
  const formData = new FormData();
2907
3037
  const blob = new Blob([yamlBody], { type: "application/x-yaml" });
2908
3038
  formData.append("file_data", blob, `workflow-${id}.yaml`);
@@ -2933,12 +3063,13 @@ overwritten (the server does not expose a concurrency token).`
2933
3063
  const text = await client.getText(`/fin-sdk/workflows/${id}`);
2934
3064
  let parsed;
2935
3065
  try {
2936
- parsed = parseYaml(text);
3066
+ parsed = parseYaml2(text);
2937
3067
  } catch (err) {
2938
3068
  throw new Error(`server returned unparseable YAML for workflow ${id}: ${err.message}`);
2939
3069
  }
3070
+ parsed.type = WORKFLOW_TYPE;
2940
3071
  parsed.state = STATE_PAUSED;
2941
- const yamlBody = stringifyYaml(parsed);
3072
+ const yamlBody = stringifyYaml2(parsed);
2942
3073
  const formData = new FormData();
2943
3074
  const blob = new Blob([yamlBody], { type: "application/x-yaml" });
2944
3075
  formData.append("file_data", blob, `workflow-${id}.yaml`);
@@ -2956,6 +3087,27 @@ overwritten (the server does not expose a concurrency token).`
2956
3087
  }
2957
3088
 
2958
3089
  // src/commands/fin/simulations.ts
3090
+ import { readFile as readFile5 } from "fs/promises";
3091
+ import { basename as basename4 } from "path";
3092
+ import { parse as parseYaml3, stringify as stringifyYaml3 } from "yaml";
3093
+ var SIMULATION_SET_TYPE = "simulation_set";
3094
+ function ensureSimulationSetType(raw) {
3095
+ let parsed;
3096
+ try {
3097
+ parsed = parseYaml3(raw);
3098
+ } catch {
3099
+ return raw;
3100
+ }
3101
+ if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
3102
+ return raw;
3103
+ }
3104
+ const obj = parsed;
3105
+ if (obj.type != null && obj.type !== "") {
3106
+ return raw;
3107
+ }
3108
+ obj.type = SIMULATION_SET_TYPE;
3109
+ return stringifyYaml3(obj);
3110
+ }
2959
3111
  function registerSimulationsCommand(fin) {
2960
3112
  const simulations = fin.command("simulations").description("Manage Fin SDK simulations");
2961
3113
  simulations.command("list <procedure_id>").description("List simulations for a procedure (displays YAML)").option("--verbose", "Show HTTP request/response details").action(async function(procedureId) {
@@ -2964,6 +3116,36 @@ function registerSimulationsCommand(fin) {
2964
3116
  const text = await client.getText(`/fin-sdk/procedures/${procedureId}/simulations`);
2965
3117
  console.log(text);
2966
3118
  });
3119
+ simulations.command("upload <file>").description("Upload a simulation set YAML file for its procedure").option("--json", "Output as JSON").option("--jq <expr>", "Filter JSON output with jq expression").option("--verbose", "Show HTTP request/response details").addHelpText(
3120
+ "after",
3121
+ `
3122
+ The file is a simulation set carrying its own procedure_id, as produced by
3123
+ \`intercom fin procedures get <id> ./out --with-simulations\` (writes
3124
+ ./out/simulations.yaml) or \`intercom fin simulations list <procedure_id>\`.
3125
+ This completes the export/edit/re-import round-trip for a procedure's tests.
3126
+
3127
+ Example:
3128
+ $ intercom fin simulations upload ./out/simulations.yaml`
3129
+ ).action(async function(filePath) {
3130
+ const opts = this.optsWithGlobals();
3131
+ const client = await resolveClient(opts);
3132
+ const fileContent = await readFile5(filePath, "utf8");
3133
+ const yamlBody = ensureSimulationSetType(fileContent);
3134
+ const formData = new FormData();
3135
+ const blob = new Blob([yamlBody], { type: "application/x-yaml" });
3136
+ formData.append("file_data", blob, basename4(filePath));
3137
+ const result = await client.postFormData("/fin-sdk/upload", formData);
3138
+ render(
3139
+ result,
3140
+ opts,
3141
+ () => detail({
3142
+ "ID": result.id != null ? String(result.id) : void 0,
3143
+ "Procedure ID": result.procedure_id != null ? String(result.procedure_id) : void 0,
3144
+ "Type": result.type != null ? String(result.type) : void 0,
3145
+ "Message": result.message != null ? String(result.message) : void 0
3146
+ })
3147
+ );
3148
+ });
2967
3149
  simulations.command("run <procedure_id> [test_id]").description("Run one or all simulations for a procedure").option("--json", "Output as JSON").option("--verbose", "Show HTTP request/response details").action(async function(procedureId, testId) {
2968
3150
  const opts = this.optsWithGlobals();
2969
3151
  const client = await resolveClient(opts);
@@ -3193,8 +3375,8 @@ Fin is live on workspace ${appId}`);
3193
3375
  }
3194
3376
 
3195
3377
  // src/commands/fin/monitors.ts
3196
- import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
3197
- import { join as join3, relative, dirname } from "path";
3378
+ import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
3379
+ import { join as join4, relative, dirname } from "path";
3198
3380
  import { stringify } from "yaml";
3199
3381
  async function resolveMonitorId(client, nameOrId) {
3200
3382
  if (/^\d+$/.test(nameOrId)) {
@@ -3275,14 +3457,14 @@ Examples:
3275
3457
  );
3276
3458
  return;
3277
3459
  }
3278
- const outputPath = opts.output ?? join3(
3460
+ const outputPath = opts.output ?? join4(
3279
3461
  process.cwd(),
3280
3462
  "src",
3281
3463
  "qa",
3282
3464
  "bulk-actions",
3283
3465
  "flagged-conversations.yaml"
3284
3466
  );
3285
- await mkdir2(dirname(outputPath), { recursive: true });
3467
+ await mkdir3(dirname(outputPath), { recursive: true });
3286
3468
  await writeFile2(outputPath, buildWorkingSetYaml(result, since), "utf-8");
3287
3469
  const relPath = relative(process.cwd(), outputPath);
3288
3470
  console.log(
@@ -3300,8 +3482,8 @@ Examples:
3300
3482
  }
3301
3483
 
3302
3484
  // src/commands/fin/conversation.ts
3303
- import { readFile as readFile4 } from "fs/promises";
3304
- import { join as join4 } from "path";
3485
+ import { readFile as readFile6 } from "fs/promises";
3486
+ import { join as join5 } from "path";
3305
3487
  import { parse } from "yaml";
3306
3488
  var PLACEHOLDER_MESSAGE = "Your message here \u2014 this will be sent to all conversations listed below.";
3307
3489
  function validateWorkingSet(ws) {
@@ -3351,7 +3533,7 @@ function registerConversationCommand(fin) {
3351
3533
  ).option(
3352
3534
  "--file <path>",
3353
3535
  "Path to the working set YAML file",
3354
- join4(process.cwd(), "src", "qa", "bulk-actions", "flagged-conversations.yaml")
3536
+ join5(process.cwd(), "src", "qa", "bulk-actions", "flagged-conversations.yaml")
3355
3537
  ).option("--dry-run", "Preview actions without sending").option("--yes", "Skip confirmation prompt (required in TTY mode)").option(
3356
3538
  "--json",
3357
3539
  "Output result as JSON"
@@ -3365,7 +3547,7 @@ Examples:
3365
3547
  $ fin conversation bulk-send --json`
3366
3548
  ).action(async function() {
3367
3549
  const opts = this.optsWithGlobals();
3368
- const filePath = opts.file ?? join4(
3550
+ const filePath = opts.file ?? join5(
3369
3551
  process.cwd(),
3370
3552
  "src",
3371
3553
  "qa",
@@ -3374,7 +3556,7 @@ Examples:
3374
3556
  );
3375
3557
  let raw;
3376
3558
  try {
3377
- raw = await readFile4(filePath, "utf-8");
3559
+ raw = await readFile6(filePath, "utf-8");
3378
3560
  } catch (err) {
3379
3561
  const e = err;
3380
3562
  if (e.code === "ENOENT") {
@@ -3535,7 +3717,7 @@ Examples:
3535
3717
 
3536
3718
  // src/commands/setup.ts
3537
3719
  import { readdirSync, readFileSync as readFileSync4, statSync } from "fs";
3538
- import { join as join5, basename as basename3 } from "path";
3720
+ import { join as join6, basename as basename5 } from "path";
3539
3721
  function isGreenfield(opts) {
3540
3722
  return !!(opts.email && opts.name && (process.env.INTERCOM_PASSWORD || opts.passwordStdin));
3541
3723
  }
@@ -3593,8 +3775,8 @@ function buildPlan(opts) {
3593
3775
  }
3594
3776
  if (mdFiles.length > 0) {
3595
3777
  const articleCommands = mdFiles.map((file) => {
3596
- const title = basename3(file, ".md").replace(/-/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
3597
- return `intercom articles create -f title="${title}" -F body=@${join5(opts.articlesFrom, file)} -f author_id=$(intercom me --json | jq -r .id)`;
3778
+ const title = basename5(file, ".md").replace(/-/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
3779
+ return `intercom articles create -f title="${title}" -F body=@${join6(opts.articlesFrom, file)} -f author_id=$(intercom me --json | jq -r .id)`;
3598
3780
  });
3599
3781
  steps.push({
3600
3782
  step: stepNum++,
@@ -3660,8 +3842,8 @@ async function runPostAuthSteps(client, opts, results, appId) {
3660
3842
  let created = 0;
3661
3843
  let skipped = 0;
3662
3844
  for (const file of mdFiles) {
3663
- const title = basename3(file, ".md").replace(/-/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
3664
- const body = readFileSync4(join5(opts.articlesFrom, file), "utf-8");
3845
+ const title = basename5(file, ".md").replace(/-/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
3846
+ const body = readFileSync4(join6(opts.articlesFrom, file), "utf-8");
3665
3847
  if (existingTitles.has(title)) {
3666
3848
  skipped++;
3667
3849
  } else {
@@ -4138,7 +4320,7 @@ function registerPricingCommand(program) {
4138
4320
  }
4139
4321
 
4140
4322
  // src/commands/config.ts
4141
- import { join as join6 } from "path";
4323
+ import { join as join7 } from "path";
4142
4324
  var SUPPORTED_KEYS = ["default_workspace", "timeout"];
4143
4325
  function configDir() {
4144
4326
  return process.env.INTERCOM_CONFIG_DIR ?? defaultConfigDir();
@@ -4227,7 +4409,7 @@ function registerConfigCommand(program) {
4227
4409
  console.log(`Set ${key} = ${value}`);
4228
4410
  });
4229
4411
  cmd.command("path").description("Show configuration file path").action(async function() {
4230
- console.log(join6(configDir(), "config.json"));
4412
+ console.log(join7(configDir(), "config.json"));
4231
4413
  });
4232
4414
  }
4233
4415
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intercom/cli",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "CLI tool for managing Intercom workspaces",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.23.0",