jiradc-cli 1.0.34 → 1.0.35

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 +55 -16
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2014,22 +2014,35 @@ var WILDCARD = "*";
2014
2014
  var NEGATION = "-";
2015
2015
  function buildFieldNameIndex(fields) {
2016
2016
  const ids = /* @__PURE__ */ new Set();
2017
+ const idsByLower = /* @__PURE__ */ new Map();
2017
2018
  const byName = /* @__PURE__ */ new Map();
2019
+ const record = (alias, id) => {
2020
+ const key = alias.toLowerCase();
2021
+ const already = byName.get(key);
2022
+ if (!already) {
2023
+ byName.set(key, [id]);
2024
+ return;
2025
+ }
2026
+ if (!already.includes(id)) already.push(id);
2027
+ };
2018
2028
  for (const field of fields) {
2019
2029
  ids.add(field.id);
2020
- byName.set(field.name.toLowerCase(), field.id);
2021
- for (const clause of field.clauseNames ?? []) byName.set(clause.toLowerCase(), field.id);
2030
+ idsByLower.set(field.id.toLowerCase(), field.id);
2031
+ record(field.name, field.id);
2032
+ for (const clause of field.clauseNames ?? []) record(clause, field.id);
2022
2033
  }
2023
- for (const field of fields) byName.set(field.id.toLowerCase(), field.id);
2024
- return { ids, byName };
2034
+ return { ids, idsByLower, byName };
2025
2035
  }
2026
- function resolveOne(token, index) {
2027
- if (index.ids.has(token)) return token;
2028
- return index.byName.get(token.toLowerCase());
2036
+ function candidatesFor(token, index) {
2037
+ if (index.ids.has(token)) return [token];
2038
+ const byId = index.idsByLower.get(token.toLowerCase());
2039
+ if (byId !== void 0) return [byId];
2040
+ return index.byName.get(token.toLowerCase()) ?? [];
2029
2041
  }
2030
2042
  function resolveFieldSelectors(tokens, index) {
2031
2043
  const resolved = [];
2032
2044
  const unresolved = [];
2045
+ const ambiguous = [];
2033
2046
  for (const token of tokens) {
2034
2047
  if (token.startsWith(WILDCARD)) {
2035
2048
  resolved.push(token);
@@ -2037,22 +2050,48 @@ function resolveFieldSelectors(tokens, index) {
2037
2050
  }
2038
2051
  const negated = token.startsWith(NEGATION);
2039
2052
  const bare = negated ? token.slice(1) : token;
2040
- const id = resolveOne(bare, index);
2041
- if (id === void 0) {
2053
+ const candidates = candidatesFor(bare, index);
2054
+ if (candidates.length === 0) {
2042
2055
  unresolved.push(token);
2043
2056
  continue;
2044
2057
  }
2045
- resolved.push(negated ? `${NEGATION}${id}` : id);
2058
+ if (candidates.length > 1) {
2059
+ ambiguous.push({ name: bare, candidates });
2060
+ continue;
2061
+ }
2062
+ resolved.push(negated ? `${NEGATION}${candidates[0]}` : candidates[0]);
2063
+ }
2064
+ if (unresolved.length > 0 || ambiguous.length > 0) {
2065
+ throw new CliUsageError(describeFailure(unresolved, ambiguous), recoveryFor(unresolved, ambiguous), {
2066
+ ...unresolved.length > 0 ? { unresolved } : {},
2067
+ ...ambiguous.length > 0 ? { ambiguous } : {}
2068
+ });
2069
+ }
2070
+ return [...new Set(resolved)];
2071
+ }
2072
+ function describeFailure(unresolved, ambiguous) {
2073
+ const parts = [];
2074
+ if (unresolved.length > 0) {
2075
+ parts.push(`Unknown field name${unresolved.length > 1 ? "s" : ""}: ${unresolved.join(", ")}`);
2076
+ }
2077
+ for (const { name, candidates } of ambiguous) {
2078
+ parts.push(`'${name}' matches ${candidates.length} fields on this instance: ${candidates.join(", ")}`);
2046
2079
  }
2080
+ return parts.join(". ");
2081
+ }
2082
+ function recoveryFor(unresolved, ambiguous) {
2083
+ const parts = [];
2047
2084
  if (unresolved.length > 0) {
2048
- const plural = unresolved.length > 1 ? "s" : "";
2049
- throw new CliUsageError(
2050
- `Unknown field name${plural}: ${unresolved.join(", ")}`,
2051
- `Jira selects fields by id, and these matched no field id, name or JQL clause name on this instance. Run jiradc field search <keyword> to find the right name or id. Left unresolved these would be dropped silently, returning an answer missing the field${plural} you asked for.`,
2052
- { unresolved }
2085
+ parts.push(
2086
+ "Jira selects fields by id, and these matched no field id, name or JQL clause name on this instance. Run jiradc field search <keyword> to find the right name or id."
2053
2087
  );
2054
2088
  }
2055
- return [...new Set(resolved)];
2089
+ if (ambiguous.length > 0) {
2090
+ parts.push(
2091
+ `Field names are not unique on a Jira instance. Re-run with the id you mean \u2014 ${ambiguous.map((a) => a.candidates.join(" or ")).join("; ")} \u2014 or run jiradc issue get <key> --all-fields to see which one this issue carries. Choosing one for you would return an answer that looks complete and names no field it dropped.`
2092
+ );
2093
+ }
2094
+ return parts.join(" ");
2056
2095
  }
2057
2096
  function parseFieldSelectors(raw) {
2058
2097
  return raw.split(",").map((token) => token.trim()).filter((token) => token.length > 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jiradc-cli",
3
- "version": "1.0.34",
3
+ "version": "1.0.35",
4
4
  "publish": true,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,8 +23,8 @@
23
23
  "tsx": "^4.19.2",
24
24
  "typescript": "^5.7.2",
25
25
  "vitest": "^4.0.16",
26
- "cli-utils": "1.0.0",
27
26
  "config-eslint": "0.0.0",
27
+ "cli-utils": "1.0.0",
28
28
  "config-typescript": "0.0.0"
29
29
  },
30
30
  "engines": {