@floh-solutions/pharos-cli 0.4.0 → 0.12.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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +381 -7
- package/dist/cli.js.map +1 -1
- package/dist/commands/attach.d.ts +30 -0
- package/dist/commands/attach.d.ts.map +1 -0
- package/dist/commands/attach.js +55 -0
- package/dist/commands/attach.js.map +1 -0
- package/dist/commands/create.d.ts +35 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +82 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/detach.d.ts +34 -0
- package/dist/commands/detach.d.ts.map +1 -0
- package/dist/commands/detach.js +117 -0
- package/dist/commands/detach.js.map +1 -0
- package/dist/commands/discover.d.ts +66 -0
- package/dist/commands/discover.d.ts.map +1 -0
- package/dist/commands/discover.js +128 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/hooks.d.ts +24 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +184 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/image.d.ts +44 -0
- package/dist/commands/image.d.ts.map +1 -0
- package/dist/commands/image.js +114 -0
- package/dist/commands/image.js.map +1 -0
- package/dist/commands/import.d.ts +51 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +190 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/link.d.ts +40 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +150 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/people.d.ts +39 -0
- package/dist/commands/people.d.ts.map +1 -0
- package/dist/commands/people.js +64 -0
- package/dist/commands/people.js.map +1 -0
- package/dist/commands/query.d.ts +43 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +202 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/recycle.d.ts +10 -0
- package/dist/commands/recycle.d.ts.map +1 -0
- package/dist/commands/recycle.js +118 -0
- package/dist/commands/recycle.js.map +1 -0
- package/dist/commands/update.d.ts +52 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +181 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/wiki.d.ts.map +1 -1
- package/dist/commands/wiki.js +133 -2
- package/dist/commands/wiki.js.map +1 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +32 -2
- package/dist/output.js.map +1 -1
- package/dist/wiql-build.d.ts +92 -0
- package/dist/wiql-build.d.ts.map +1 -0
- package/dist/wiql-build.js +147 -0
- package/dist/wiql-build.js.map +1 -0
- package/package.json +3 -3
- package/skill/SKILL.md +315 -65
package/dist/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { StateCatalog } from "@floh-solutions/ado-core";
|
|
2
|
+
/**
|
|
3
|
+
* Turning `pharos query`'s flags into one WIQL statement.
|
|
4
|
+
*
|
|
5
|
+
* **Pure, and separate from the command, because this is where the bugs are.**
|
|
6
|
+
* The flags AND together and every one of them puts a literal from the command
|
|
7
|
+
* line into a query language — so composition and quoting are the whole risk
|
|
8
|
+
* surface, and both can be proved without a network. The command file around
|
|
9
|
+
* this is only "call it, hydrate, print".
|
|
10
|
+
*/
|
|
11
|
+
/** What the caller asked for. Everything is optional; everything ANDs. */
|
|
12
|
+
export interface QueryFilters {
|
|
13
|
+
/** `[System.AssignedTo] = @Me`. Mutually exclusive with {@link assignee}. */
|
|
14
|
+
mine?: boolean;
|
|
15
|
+
assignee?: string | undefined;
|
|
16
|
+
states?: readonly string[];
|
|
17
|
+
types?: readonly string[];
|
|
18
|
+
/** An iteration path, or a leaf name resolved under the project. */
|
|
19
|
+
sprint?: string | undefined;
|
|
20
|
+
/** An area path, same resolution as {@link sprint}. */
|
|
21
|
+
area?: string | undefined;
|
|
22
|
+
tags?: readonly string[];
|
|
23
|
+
/** Do not filter by openness at all. */
|
|
24
|
+
all?: boolean;
|
|
25
|
+
/** The project, for turning a leaf sprint name into a path. */
|
|
26
|
+
project?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* How "open" was decided, so the answer can say it.
|
|
30
|
+
*
|
|
31
|
+
* The output carries this verbatim. A list of work items is not interpretable
|
|
32
|
+
* without it: "12 open" means nothing until you know which states were counted
|
|
33
|
+
* as closed, and the whole reason this command exists is that a session had to
|
|
34
|
+
* work that out for itself and guess.
|
|
35
|
+
*/
|
|
36
|
+
export interface Openness {
|
|
37
|
+
/** `categories` read the project; `fallback` guessed and should say so. */
|
|
38
|
+
source: "categories" | "fallback" | "explicit" | "none";
|
|
39
|
+
/** The states treated as finished. Empty when nothing was excluded. */
|
|
40
|
+
terminal: readonly string[];
|
|
41
|
+
/** Present only when it matters — see {@link StateCatalog.ambiguous}. */
|
|
42
|
+
perType?: boolean;
|
|
43
|
+
note?: string;
|
|
44
|
+
}
|
|
45
|
+
/** The names Azure DevOps' stock templates use, for when the catalogue is unreadable. */
|
|
46
|
+
export declare const FALLBACK_TERMINAL_STATES: readonly string[];
|
|
47
|
+
/**
|
|
48
|
+
* A WIQL string literal.
|
|
49
|
+
*
|
|
50
|
+
* Single quotes are doubled — WIQL's own escape, and the only one it has. This
|
|
51
|
+
* is not decoration: a sprint called `Bob's Sprint` composes an unterminated
|
|
52
|
+
* literal and Azure DevOps answers with a parse error naming a query the caller
|
|
53
|
+
* never wrote.
|
|
54
|
+
*/
|
|
55
|
+
export declare function quote(value: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* A leaf name becomes a path under the project; a path is left alone.
|
|
58
|
+
*
|
|
59
|
+
* `System.IterationPath` and `System.AreaPath` are tree fields whose values are
|
|
60
|
+
* always rooted at the project — `Contoso\Sprint 1`, never `Sprint 1`. Somebody
|
|
61
|
+
* typing `--sprint "Sprint 1"` means the obvious thing, and refusing it over a
|
|
62
|
+
* prefix they cannot see would be pedantry. A value that already contains a
|
|
63
|
+
* separator is taken as written, which is how a nested iteration is reached.
|
|
64
|
+
*/
|
|
65
|
+
export declare function treePath(value: string, project: string | undefined): string;
|
|
66
|
+
/**
|
|
67
|
+
* The openness clause, or nothing.
|
|
68
|
+
*
|
|
69
|
+
* Two shapes, and the second is why {@link StateCatalog.ambiguous} exists. When
|
|
70
|
+
* every state name means the same thing on every type, one `NOT IN` covers the
|
|
71
|
+
* project. When a name is `InProgress` on one type and `Completed` on another,
|
|
72
|
+
* no single list is right — so each type gets its own clause and the types that
|
|
73
|
+
* carry no terminal state at all are admitted whole.
|
|
74
|
+
*/
|
|
75
|
+
export declare function opennessClause(catalog: StateCatalog): string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* The statement.
|
|
78
|
+
*
|
|
79
|
+
* `[System.TeamProject] = @project` is always first and is not redundant with
|
|
80
|
+
* the project in the URL: WIQL will happily return items from other projects
|
|
81
|
+
* the token can see, and a `--mine` that reaches across an organisation is a
|
|
82
|
+
* different question from the one that was asked.
|
|
83
|
+
*
|
|
84
|
+
* Only `[System.Id]` is selected because WIQL returns references and never
|
|
85
|
+
* values however many columns are named — the fields come from the hydrate step
|
|
86
|
+
* afterwards, and selecting more here would only make the statement look like
|
|
87
|
+
* it did something it cannot.
|
|
88
|
+
*/
|
|
89
|
+
export declare function buildWiql(filters: QueryFilters, openness: Openness, catalog?: StateCatalog): string;
|
|
90
|
+
/** What the openness of a query is, given what was asked and what could be read. */
|
|
91
|
+
export declare function opennessFor(filters: QueryFilters, catalog: StateCatalog | undefined, failure?: string): Openness;
|
|
92
|
+
//# sourceMappingURL=wiql-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiql-build.d.ts","sourceRoot":"","sources":["../src/wiql-build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;;;GAQG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,wCAAwC;IACxC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACvB,2EAA2E;IAC3E,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;IACxD,uEAAuE;IACvE,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAAkC,CAAC;AAEzF;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAkBxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CA8CnG;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,YAAY,GAAG,SAAS,EACjC,OAAO,CAAC,EAAE,MAAM,GACf,QAAQ,CAkCV"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/** The names Azure DevOps' stock templates use, for when the catalogue is unreadable. */
|
|
2
|
+
export const FALLBACK_TERMINAL_STATES = ["Closed", "Done", "Removed"];
|
|
3
|
+
/**
|
|
4
|
+
* A WIQL string literal.
|
|
5
|
+
*
|
|
6
|
+
* Single quotes are doubled — WIQL's own escape, and the only one it has. This
|
|
7
|
+
* is not decoration: a sprint called `Bob's Sprint` composes an unterminated
|
|
8
|
+
* literal and Azure DevOps answers with a parse error naming a query the caller
|
|
9
|
+
* never wrote.
|
|
10
|
+
*/
|
|
11
|
+
export function quote(value) {
|
|
12
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
13
|
+
}
|
|
14
|
+
function inClause(field, values) {
|
|
15
|
+
if (values.length === 1)
|
|
16
|
+
return `[${field}] = ${quote(values[0])}`;
|
|
17
|
+
return `[${field}] IN (${values.map(quote).join(", ")})`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A leaf name becomes a path under the project; a path is left alone.
|
|
21
|
+
*
|
|
22
|
+
* `System.IterationPath` and `System.AreaPath` are tree fields whose values are
|
|
23
|
+
* always rooted at the project — `Contoso\Sprint 1`, never `Sprint 1`. Somebody
|
|
24
|
+
* typing `--sprint "Sprint 1"` means the obvious thing, and refusing it over a
|
|
25
|
+
* prefix they cannot see would be pedantry. A value that already contains a
|
|
26
|
+
* separator is taken as written, which is how a nested iteration is reached.
|
|
27
|
+
*/
|
|
28
|
+
export function treePath(value, project) {
|
|
29
|
+
if (value.includes("\\") || project === undefined || project === "")
|
|
30
|
+
return value;
|
|
31
|
+
return `${project}\\${value}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The openness clause, or nothing.
|
|
35
|
+
*
|
|
36
|
+
* Two shapes, and the second is why {@link StateCatalog.ambiguous} exists. When
|
|
37
|
+
* every state name means the same thing on every type, one `NOT IN` covers the
|
|
38
|
+
* project. When a name is `InProgress` on one type and `Completed` on another,
|
|
39
|
+
* no single list is right — so each type gets its own clause and the types that
|
|
40
|
+
* carry no terminal state at all are admitted whole.
|
|
41
|
+
*/
|
|
42
|
+
export function opennessClause(catalog) {
|
|
43
|
+
if (catalog.ambiguous.length === 0) {
|
|
44
|
+
if (catalog.terminal.length === 0)
|
|
45
|
+
return undefined;
|
|
46
|
+
return `[System.State] NOT IN (${catalog.terminal.map(quote).join(", ")})`;
|
|
47
|
+
}
|
|
48
|
+
const perType = [];
|
|
49
|
+
for (const [type, states] of catalog.byType) {
|
|
50
|
+
if (states.terminal.length === 0) {
|
|
51
|
+
perType.push(`[System.WorkItemType] = ${quote(type)}`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
perType.push(`([System.WorkItemType] = ${quote(type)}`
|
|
55
|
+
+ ` AND [System.State] NOT IN (${states.terminal.map(quote).join(", ")}))`);
|
|
56
|
+
}
|
|
57
|
+
return perType.length === 0 ? undefined : `(${perType.join(" OR ")})`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The statement.
|
|
61
|
+
*
|
|
62
|
+
* `[System.TeamProject] = @project` is always first and is not redundant with
|
|
63
|
+
* the project in the URL: WIQL will happily return items from other projects
|
|
64
|
+
* the token can see, and a `--mine` that reaches across an organisation is a
|
|
65
|
+
* different question from the one that was asked.
|
|
66
|
+
*
|
|
67
|
+
* Only `[System.Id]` is selected because WIQL returns references and never
|
|
68
|
+
* values however many columns are named — the fields come from the hydrate step
|
|
69
|
+
* afterwards, and selecting more here would only make the statement look like
|
|
70
|
+
* it did something it cannot.
|
|
71
|
+
*/
|
|
72
|
+
export function buildWiql(filters, openness, catalog) {
|
|
73
|
+
const where = ["[System.TeamProject] = @project"];
|
|
74
|
+
if (filters.mine === true)
|
|
75
|
+
where.push("[System.AssignedTo] = @Me");
|
|
76
|
+
else if (filters.assignee !== undefined)
|
|
77
|
+
where.push(`[System.AssignedTo] = ${quote(filters.assignee)}`);
|
|
78
|
+
if (filters.types !== undefined && filters.types.length > 0) {
|
|
79
|
+
where.push(inClause("System.WorkItemType", filters.types));
|
|
80
|
+
}
|
|
81
|
+
if (filters.states !== undefined && filters.states.length > 0) {
|
|
82
|
+
where.push(inClause("System.State", filters.states));
|
|
83
|
+
}
|
|
84
|
+
else if (openness.source === "categories" && catalog !== undefined) {
|
|
85
|
+
const clause = opennessClause(catalog);
|
|
86
|
+
if (clause !== undefined)
|
|
87
|
+
where.push(clause);
|
|
88
|
+
}
|
|
89
|
+
else if (openness.source === "fallback") {
|
|
90
|
+
where.push(`[System.State] NOT IN (${openness.terminal.map(quote).join(", ")})`);
|
|
91
|
+
}
|
|
92
|
+
if (filters.sprint !== undefined) {
|
|
93
|
+
// `current` is the one value that is a macro rather than a path. It resolves
|
|
94
|
+
// against a TEAM, which is a path segment on the request rather than
|
|
95
|
+
// anything in the query — see `WiqlApi.query`.
|
|
96
|
+
where.push(filters.sprint.toLowerCase() === "current"
|
|
97
|
+
? "[System.IterationPath] = @currentIteration"
|
|
98
|
+
: `[System.IterationPath] UNDER ${quote(treePath(filters.sprint, filters.project))}`);
|
|
99
|
+
}
|
|
100
|
+
if (filters.area !== undefined) {
|
|
101
|
+
where.push(`[System.AreaPath] UNDER ${quote(treePath(filters.area, filters.project))}`);
|
|
102
|
+
}
|
|
103
|
+
for (const tag of filters.tags ?? []) {
|
|
104
|
+
// Tags are a semicolon-joined string, so CONTAINS is the operator. It is a
|
|
105
|
+
// substring match: a `--tag api` also matches `api-v2`, which is worth
|
|
106
|
+
// knowing and not worth refusing.
|
|
107
|
+
where.push(`[System.Tags] CONTAINS ${quote(tag)}`);
|
|
108
|
+
}
|
|
109
|
+
return ("SELECT [System.Id] FROM WorkItems WHERE "
|
|
110
|
+
+ where.join(" AND ")
|
|
111
|
+
+ " ORDER BY [System.ChangedDate] DESC");
|
|
112
|
+
}
|
|
113
|
+
/** What the openness of a query is, given what was asked and what could be read. */
|
|
114
|
+
export function opennessFor(filters, catalog, failure) {
|
|
115
|
+
if (filters.states !== undefined && filters.states.length > 0) {
|
|
116
|
+
return {
|
|
117
|
+
source: "explicit",
|
|
118
|
+
terminal: [],
|
|
119
|
+
note: "You named the states, so nothing was treated as finished.",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (filters.all === true) {
|
|
123
|
+
return { source: "none", terminal: [], note: "--all: every state, open or finished." };
|
|
124
|
+
}
|
|
125
|
+
if (catalog !== undefined) {
|
|
126
|
+
return {
|
|
127
|
+
source: "categories",
|
|
128
|
+
terminal: catalog.terminal,
|
|
129
|
+
...(catalog.ambiguous.length > 0 ? { perType: true } : {}),
|
|
130
|
+
note: "Read from this project's own state categories, so it is right whatever the process "
|
|
131
|
+
+ "template calls things."
|
|
132
|
+
+ (catalog.ambiguous.length > 0
|
|
133
|
+
? ` ${catalog.ambiguous.join(", ")} mean different things on different work item types,`
|
|
134
|
+
+ " so the filter is per type."
|
|
135
|
+
: ""),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
source: "fallback",
|
|
140
|
+
terminal: FALLBACK_TERMINAL_STATES,
|
|
141
|
+
note: "COULD NOT read this project's state categories"
|
|
142
|
+
+ (failure === undefined ? "" : ` (${failure})`)
|
|
143
|
+
+ ", so these are Azure DevOps' stock names. If this project renames its states, this "
|
|
144
|
+
+ "result may be missing work or showing finished work. Pass --state to be exact.",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=wiql-build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiql-build.js","sourceRoot":"","sources":["../src/wiql-build.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@floh-solutions/pharos-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Azure DevOps from a headless shell, for an agent: the whole context of a task in one call, and the wiki/comment verbs Microsoft's MCP server does not ship.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "FLOH Solutions",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"node": ">=22"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@floh-solutions/
|
|
28
|
-
"@floh-solutions/
|
|
27
|
+
"@floh-solutions/plan-to-board": "0.1.1",
|
|
28
|
+
"@floh-solutions/ado-core": "0.7.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.2",
|