conduyt 1.49.0 → 1.50.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 (2) hide show
  1. package/dist/index.js +21 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -468,6 +468,7 @@ deals
468
468
  if (opts.json !== undefined)
469
469
  Object.assign(body, jsonArg(opts.json, "--json"));
470
470
  assertFiniteValue(body.value);
471
+ assertDealSource(body);
471
472
  return client.post("/api/v1/deals", body);
472
473
  }));
473
474
  deals
@@ -477,6 +478,19 @@ deals
477
478
  assertUuid(id, "deal id");
478
479
  return client.get(`/api/v1/deals/${encodeURIComponent(id)}`);
479
480
  }));
481
+ // Conduyt #129: every deal carries a source — it can be changed, never cleared. Validated on the FINAL merged body
482
+ // (flags and --json alike) so the CLI fails locally instead of shipping a guaranteed 422. An omitted source on
483
+ // create is fine: the server derives it (explicit → trigger → contact → "Unknown (created via api)").
484
+ function assertDealSource(body) {
485
+ if (!("source" in body))
486
+ return;
487
+ const v = body.source;
488
+ if (v === null || typeof v !== "string" || v.trim() === "" || v.trim().toLowerCase() === "null") {
489
+ throw new Error("A deal's source can be changed, never cleared (every deal carries a source). Pass a non-blank source string, or omit it.");
490
+ }
491
+ if (v.length > 500)
492
+ throw new Error("source must be at most 500 characters.");
493
+ }
480
494
  deals
481
495
  .command("update <id>")
482
496
  .description("Update a deal (PATCH — only the fields you pass change). --stage moves the deal (won/lost status auto-derives from the target stage's flags)")
@@ -487,7 +501,7 @@ deals
487
501
  .option("--pipeline <id>", "move to this pipeline UUID")
488
502
  .option("--contact <id>", "primary contact UUID")
489
503
  .option("--status <status>", "explicit status (open|won|lost); overrides the status auto-derived from --stage")
490
- .option("--source <source>", "attribution source for THIS deal (pass 'null' to clear it)")
504
+ .option("--source <source>", "attribution source for THIS deal (can be changed, never cleared — every deal carries a source)")
491
505
  .option("--lost-reason <reason>", "reason for a lost/disqualified deal — some stages REQUIRE it on entry; when the stage has a configured dropdown the API 422 lists the valid lostReasonOptions, resend with one of those exact values")
492
506
  .option("--json <json>", "full JSON body, merged over the flags")
493
507
  .action(run(async (client, id, opts) => {
@@ -512,14 +526,14 @@ deals
512
526
  if (opts.status !== undefined)
513
527
  body.status = opts.status;
514
528
  if (opts.source !== undefined) {
515
- // Mirror the API validator (blank rejected, 500-char cap) so the CLI
516
- // fails locally rather than shipping a guaranteed 422.
517
- if (opts.source.trim() === "") {
518
- throw new Error("--source was provided but is blank. Omit it, or pass 'null' to clear the source.");
529
+ // Mirror the API validator (Conduyt #129: a deal's source can change, never be cleared; blank rejected,
530
+ // 500-char cap) so the CLI fails locally rather than shipping a guaranteed 422.
531
+ if (opts.source.trim() === "" || opts.source.trim().toLowerCase() === "null") {
532
+ throw new Error("A deal's source can be changed, never cleared (every deal carries a source). Pass the new source, or omit --source.");
519
533
  }
520
534
  if (opts.source.length > 500)
521
535
  throw new Error("--source must be at most 500 characters.");
522
- body.source = opts.source === "null" ? null : opts.source;
536
+ body.source = opts.source;
523
537
  }
524
538
  if (opts.stage !== undefined) {
525
539
  if (opts.stage.trim() === "")
@@ -534,6 +548,7 @@ deals
534
548
  if (opts.json !== undefined)
535
549
  Object.assign(body, jsonArg(opts.json, "--json"));
536
550
  assertFiniteValue(body.value);
551
+ assertDealSource(body);
537
552
  if (Object.keys(body).length === 0)
538
553
  throw new Error("Nothing to update. Pass at least one field flag or --json.");
539
554
  return client.patch(`/api/v1/deals/${encodeURIComponent(id)}`, body);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conduyt",
3
- "version": "1.49.0",
3
+ "version": "1.50.0",
4
4
  "description": "Command-line interface for Conduyt CRM — manage contacts, deals, pipelines, and run insight queries from your terminal.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",