Skip to content

Commit bb7422a

Browse files
fix(cli): Allow '=' as key-value separator for tags and extra flags (#1285)
Previously, the `parseKeyValue` function in `src/lib/envelope/event-builder.ts` only recognized the `KEY:VALUE` format, splitting exclusively on the first colon (`:`). This led to `ValidationError` when users or AI agents provided key-value pairs using the common `KEY=VALUE` format (e.g., `--tag component=app`). This change updates `parseKeyValue` to correctly identify and split on the first occurrence of either a colon (`:`) or an equals sign (`=`), whichever appears first and is not at the beginning of the string. This ensures that both `KEY:VALUE` and `KEY=VALUE` formats are accepted, improving flexibility and aligning with common CLI conventions, while preserving any subsequent separators within the value part. Fixes [CLI-21G](https://sentry.sentry.io/issues/7554746770/?seerDrawer=true) <sub>Comment `@sentry <feedback>` on this PR to have Autofix iterate on the changes.</sub> --------- Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> Co-authored-by: jared-outpost[bot] <jared-outpost[bot]@users.noreply.github.com>
1 parent cce4d63 commit bb7422a

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

src/lib/envelope/event-builder.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,17 @@ export type SendEventFlags = {
3434
const KNOWN_USER_FIELDS = new Set(["id", "email", "ip_address", "username"]);
3535

3636
/**
37-
* Parse a single KEY:VALUE string, splitting on the first colon.
37+
* Parse a single KEY:VALUE (or KEY=VALUE) string, splitting on the first
38+
* `:` or `=`, whichever appears first.
3839
*
39-
* Values may contain colons (e.g. `url:https://example.com`).
40+
* Values may contain further separators (e.g. `url:https://example.com`).
4041
* Throws ValidationError if the format is wrong.
4142
*/
4243
export function parseKeyValue(pair: string): [string, string] {
43-
const idx = pair.indexOf(":");
44+
const colonIdx = pair.indexOf(":");
45+
const equalsIdx = pair.indexOf("=");
46+
const found = [colonIdx, equalsIdx].filter((i) => i >= 0);
47+
const idx = found.length > 0 ? Math.min(...found) : -1;
4448
if (idx <= 0) {
4549
throw new ValidationError(
4650
`Expected KEY:VALUE format, got: ${JSON.stringify(pair)}`,

test/lib/envelope/event-builder.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ describe("parseKeyValue", () => {
3535
test("empty key → throws ValidationError", async () => {
3636
expect(() => parseKeyValue(":value")).toThrow(ValidationError);
3737
});
38+
39+
test("splits on first equals sign", async () => {
40+
expect(parseKeyValue("key=value")).toEqual(["key", "value"]);
41+
});
42+
43+
test("splits on whichever separator comes first", async () => {
44+
expect(parseKeyValue("key=a:b")).toEqual(["key", "a:b"]);
45+
expect(parseKeyValue("key:a=b")).toEqual(["key", "a=b"]);
46+
});
47+
48+
test("leading equals sign → throws ValidationError", async () => {
49+
expect(() => parseKeyValue("=value")).toThrow(ValidationError);
50+
});
51+
52+
test("leading colon before a later equals → throws ValidationError", async () => {
53+
expect(() => parseKeyValue(":key=value")).toThrow(ValidationError);
54+
});
3855
});
3956

4057
// ── parseUserFields ───────────────────────────────────────────────

0 commit comments

Comments
 (0)