conduyt 1.2.1 → 1.3.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 +25 -0
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -99,6 +99,13 @@ contacts
99
99
  Object.assign(body, jsonArg(opts.json, "--json"));
100
100
  return client.post("/api/v1/contacts", body);
101
101
  }));
102
+ contacts
103
+ .command("delete <id>")
104
+ .description("Delete a contact by id (soft-delete; retained for audit, the contact's deals are unaffected)")
105
+ .action(run(async (client, id) => {
106
+ assertUuid(id, "contact id");
107
+ return client.del(`/api/v1/contacts/${encodeURIComponent(id)}`);
108
+ }));
102
109
  // ---- deals ----
103
110
  const deals = program.command("deals").description("Manage deals");
104
111
  deals
@@ -265,6 +272,13 @@ deals
265
272
  assertFiniteValue(body.value);
266
273
  return client.post("/api/v1/deals", body);
267
274
  }));
275
+ deals
276
+ .command("delete <id>")
277
+ .description("Delete a deal by id (soft-delete; drops out of lists/boards and pipeline totals, retained for audit)")
278
+ .action(run(async (client, id) => {
279
+ assertUuid(id, "deal id");
280
+ return client.del(`/api/v1/deals/${encodeURIComponent(id)}`);
281
+ }));
268
282
  // ---- pipelines ----
269
283
  // Default action preserves the original published `conduyt pipelines` (list)
270
284
  // invocation now that pipelines is a group — without it, commander prints help
@@ -485,6 +499,17 @@ function assertFiniteValue(v) {
485
499
  throw new Error("value must be a finite number.");
486
500
  }
487
501
  }
502
+ // Validate an id is a UUID before it is interpolated into a DELETE path, so a
503
+ // malformed value with slashes can't form a different (destructive) subroute.
504
+ // The path is also URL-encoded at the call site as defence in depth. The regex
505
+ // is inlined (not a module-level const) so it isn't in the temporal dead zone
506
+ // when an action callback runs during program.parse().
507
+ function assertUuid(id, label = "id") {
508
+ const uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
509
+ if (!uuidRe.test(id.trim())) {
510
+ throw new Error(`${label} must be a UUID.`);
511
+ }
512
+ }
488
513
  // Reject prototype-polluting keys in untrusted JSON. JSON.parse creates an OWN
489
514
  // "__proto__" property, but Object.assign'ing it onto a {} body invokes the
490
515
  // setter and changes the body's PROTOTYPE — so a validator could read an
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "conduyt",
3
- "version": "1.2.1",
4
- "description": "Command-line interface for Conduyt CRM \u2014 manage contacts, deals, pipelines, and run insight queries from your terminal.",
3
+ "version": "1.3.0",
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",
7
7
  "bin": {