agent-issues 0.0.119
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/.github/agents/agent-issues.agent.md +54 -0
- package/.github/agents/agent-issues.claude.md +51 -0
- package/dist/agent-installer.d.ts +49 -0
- package/dist/agent-installer.js +171 -0
- package/dist/agent-installer.js.map +1 -0
- package/dist/auth-session.d.ts +40 -0
- package/dist/auth-session.js +107 -0
- package/dist/auth-session.js.map +1 -0
- package/dist/body-backfill.d.ts +26 -0
- package/dist/body-backfill.js +219 -0
- package/dist/body-backfill.js.map +1 -0
- package/dist/build-mode.d.ts +1 -0
- package/dist/build-mode.js +1 -0
- package/dist/build-mode.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +61 -0
- package/dist/cli/commands/auth.js +134 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/backfill.d.ts +8 -0
- package/dist/cli/commands/backfill.js +36 -0
- package/dist/cli/commands/backfill.js.map +1 -0
- package/dist/cli/commands/comments.d.ts +34 -0
- package/dist/cli/commands/comments.js +124 -0
- package/dist/cli/commands/comments.js.map +1 -0
- package/dist/cli/commands/context.d.ts +13 -0
- package/dist/cli/commands/context.js +156 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/entities.d.ts +91 -0
- package/dist/cli/commands/entities.js +420 -0
- package/dist/cli/commands/entities.js.map +1 -0
- package/dist/cli/commands/export.d.ts +20 -0
- package/dist/cli/commands/export.js +98 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/fallback.d.ts +6 -0
- package/dist/cli/commands/fallback.js +10 -0
- package/dist/cli/commands/fallback.js.map +1 -0
- package/dist/cli/commands/handoff.d.ts +1 -0
- package/dist/cli/commands/handoff.js +2 -0
- package/dist/cli/commands/handoff.js.map +1 -0
- package/dist/cli/commands/installers.d.ts +37 -0
- package/dist/cli/commands/installers.js +78 -0
- package/dist/cli/commands/installers.js.map +1 -0
- package/dist/cli/commands/kanban.d.ts +8 -0
- package/dist/cli/commands/kanban.js +83 -0
- package/dist/cli/commands/kanban.js.map +1 -0
- package/dist/cli/commands/meta.d.ts +14 -0
- package/dist/cli/commands/meta.js +33 -0
- package/dist/cli/commands/meta.js.map +1 -0
- package/dist/cli/commands/plan-entries.d.ts +30 -0
- package/dist/cli/commands/plan-entries.js +94 -0
- package/dist/cli/commands/plan-entries.js.map +1 -0
- package/dist/cli/commands/site.d.ts +29 -0
- package/dist/cli/commands/site.js +89 -0
- package/dist/cli/commands/site.js.map +1 -0
- package/dist/cli/commands/sql.d.ts +6 -0
- package/dist/cli/commands/sql.js +21 -0
- package/dist/cli/commands/sql.js.map +1 -0
- package/dist/cli/commands/synchronize.d.ts +12 -0
- package/dist/cli/commands/synchronize.js +31 -0
- package/dist/cli/commands/synchronize.js.map +1 -0
- package/dist/cli/commands/tenants.d.ts +29 -0
- package/dist/cli/commands/tenants.js +101 -0
- package/dist/cli/commands/tenants.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +120 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/renderers.d.ts +250 -0
- package/dist/cli/renderers.js +286 -0
- package/dist/cli/renderers.js.map +1 -0
- package/dist/cli/shared.d.ts +97 -0
- package/dist/cli/shared.js +192 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +41 -0
- package/dist/cli.js.map +1 -0
- package/dist/context-cli.d.ts +16 -0
- package/dist/context-cli.js +131 -0
- package/dist/context-cli.js.map +1 -0
- package/dist/daemon/daemon-lifecycle.d.ts +1 -0
- package/dist/daemon/daemon-lifecycle.js +2 -0
- package/dist/daemon/daemon-lifecycle.js.map +1 -0
- package/dist/daemon/daemon-main.d.ts +14 -0
- package/dist/daemon/daemon-main.js +30 -0
- package/dist/daemon/daemon-main.js.map +1 -0
- package/dist/daemon/local-daemon-store.d.ts +21 -0
- package/dist/daemon/local-daemon-store.js +31 -0
- package/dist/daemon/local-daemon-store.js.map +1 -0
- package/dist/entity-projection.d.ts +141 -0
- package/dist/entity-projection.js +147 -0
- package/dist/entity-projection.js.map +1 -0
- package/dist/entra-device-login.d.ts +12 -0
- package/dist/entra-device-login.js +40 -0
- package/dist/entra-device-login.js.map +1 -0
- package/dist/export-files.d.ts +24 -0
- package/dist/export-files.js +230 -0
- package/dist/export-files.js.map +1 -0
- package/dist/export-markdown.d.ts +24 -0
- package/dist/export-markdown.js +343 -0
- package/dist/export-markdown.js.map +1 -0
- package/dist/help.d.ts +112 -0
- package/dist/help.js +1430 -0
- package/dist/help.js.map +1 -0
- package/dist/kanban/assets.d.ts +3 -0
- package/dist/kanban/assets.js +37 -0
- package/dist/kanban/assets.js.map +1 -0
- package/dist/kanban/index.d.ts +1 -0
- package/dist/kanban/index.js +2 -0
- package/dist/kanban/index.js.map +1 -0
- package/dist/kanban/server.d.ts +28 -0
- package/dist/kanban/server.js +118 -0
- package/dist/kanban/server.js.map +1 -0
- package/dist/mcp-installer.d.ts +32 -0
- package/dist/mcp-installer.js +118 -0
- package/dist/mcp-installer.js.map +1 -0
- package/dist/mcp-server/index.d.ts +11 -0
- package/dist/mcp-server/index.js +504 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/mcp-server/index.test.d.ts +1 -0
- package/dist/mcp-server/index.test.js +746 -0
- package/dist/mcp-server/index.test.js.map +1 -0
- package/dist/mcp-server/mcp-tool-audit.d.ts +6 -0
- package/dist/mcp-server/mcp-tool-audit.js +47 -0
- package/dist/mcp-server/mcp-tool-audit.js.map +1 -0
- package/dist/mcp-server/stdio.d.ts +2 -0
- package/dist/mcp-server/stdio.js +7 -0
- package/dist/mcp-server/stdio.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +19 -0
- package/dist/mcp.js.map +1 -0
- package/dist/open-storage-driver.d.ts +53 -0
- package/dist/open-storage-driver.js +71 -0
- package/dist/open-storage-driver.js.map +1 -0
- package/dist/open-synchronize-stores.d.ts +24 -0
- package/dist/open-synchronize-stores.js +34 -0
- package/dist/open-synchronize-stores.js.map +1 -0
- package/dist/project-identity.d.ts +23 -0
- package/dist/project-identity.js +121 -0
- package/dist/project-identity.js.map +1 -0
- package/dist/runtime-access-boundary.d.ts +7 -0
- package/dist/runtime-access-boundary.js +182 -0
- package/dist/runtime-access-boundary.js.map +1 -0
- package/dist/service-discovery.d.ts +10 -0
- package/dist/service-discovery.js +64 -0
- package/dist/service-discovery.js.map +1 -0
- package/dist/site/assets.d.ts +4 -0
- package/dist/site/assets.js +46 -0
- package/dist/site/assets.js.map +1 -0
- package/dist/site/cloud-events-relay.d.ts +18 -0
- package/dist/site/cloud-events-relay.js +78 -0
- package/dist/site/cloud-events-relay.js.map +1 -0
- package/dist/site/index.d.ts +1 -0
- package/dist/site/index.js +2 -0
- package/dist/site/index.js.map +1 -0
- package/dist/site/server.d.ts +42 -0
- package/dist/site/server.js +320 -0
- package/dist/site/server.js.map +1 -0
- package/dist/skill-installer.d.ts +35 -0
- package/dist/skill-installer.js +174 -0
- package/dist/skill-installer.js.map +1 -0
- package/dist/vitest-setup.d.ts +1 -0
- package/dist/vitest-setup.js +7 -0
- package/dist/vitest-setup.js.map +1 -0
- package/package.json +42 -0
- package/site/dist/assets/index-DKEVC0aQ.css +1 -0
- package/site/dist/assets/index-DSR4mIml.js +4396 -0
- package/site/dist/index.html +14 -0
- package/skills/agent-issues-language.md +5 -0
- package/skills/agent-issues-operating-contract.md +208 -0
- package/skills/ai-agent-issues/SKILL.md +127 -0
- package/skills/ai-domain-modeling/ADR-FORMAT.md +48 -0
- package/skills/ai-domain-modeling/CONTEXT-FORMAT.md +54 -0
- package/skills/ai-domain-modeling/SKILL.md +45 -0
- package/skills/ai-grill-with-docs/SKILL.md +28 -0
- package/skills/ai-handoff/SKILL.md +41 -0
- package/skills/ai-implement/SKILL.md +98 -0
- package/skills/ai-migrate-docs/SKILL.md +65 -0
- package/skills/ai-next-work/SKILL.md +43 -0
- package/skills/ai-plan/SKILL.md +41 -0
- package/skills/ai-prepare/SKILL.md +79 -0
- package/skills/ai-prototype/LOGIC.md +67 -0
- package/skills/ai-prototype/SKILL.md +31 -0
- package/skills/ai-prototype/UI.md +112 -0
- package/skills/ai-recipe-migration/SKILL.md +49 -0
- package/skills/ai-start-work/SKILL.md +56 -0
- package/skills/ai-tdd/SKILL.md +99 -0
- package/skills/ai-tdd/deep-modules.md +33 -0
- package/skills/ai-tdd/interface-design.md +20 -0
- package/skills/ai-tdd/mocking.md +28 -0
- package/skills/ai-tdd/refactoring.md +10 -0
- package/skills/ai-tdd/tests.md +74 -0
- package/skills/ai-to-issues/SKILL.md +70 -0
- package/skills/ai-to-prd/SKILL.md +33 -0
- package/skills/ai-wayfinder/SKILL.md +110 -0
- package/skills/recipes/README.md +29 -0
- package/skills/recipes/adr.md +21 -0
- package/skills/recipes/context-summary.md +17 -0
- package/skills/recipes/context-term.md +3 -0
- package/skills/recipes/debt.md +21 -0
- package/skills/recipes/epic.md +21 -0
- package/skills/recipes/handoff.md +29 -0
- package/skills/recipes/initiative.md +21 -0
- package/skills/recipes/issue-comment.md +15 -0
- package/skills/recipes/issue.md +33 -0
- package/skills/recipes/prd.md +29 -0
- package/skills/recipes/project.md +21 -0
- package/skills/recipes/user-story.md +15 -0
- package/skills/recipes/version.md +13 -0
- package/skills/recipes/wayfinder-map.md +25 -0
- package/skills/recipes/wayfinder-ticket.md +17 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
export const BACKFILLABLE_BODY_KINDS = ["project", "epic", "version", "initiative", "issue", "prd", "userStory", "adr"];
|
|
2
|
+
const DERIVED_CONTENT_MARKER = "Not derived from tracker metadata.";
|
|
3
|
+
export function isBackfillableBodyKind(value) {
|
|
4
|
+
return BACKFILLABLE_BODY_KINDS.includes(value);
|
|
5
|
+
}
|
|
6
|
+
export function parseBackfillableBodyKinds(values) {
|
|
7
|
+
if (values.length === 0) {
|
|
8
|
+
return [...BACKFILLABLE_BODY_KINDS];
|
|
9
|
+
}
|
|
10
|
+
const kinds = [];
|
|
11
|
+
const invalid = [];
|
|
12
|
+
for (const value of values) {
|
|
13
|
+
if (!isBackfillableBodyKind(value)) {
|
|
14
|
+
invalid.push(value);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (!kinds.includes(value)) {
|
|
18
|
+
kinds.push(value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (invalid.length > 0) {
|
|
22
|
+
throw new Error(`Unsupported backfill kinds: ${invalid.join(", ")}. Supported kinds: ${BACKFILLABLE_BODY_KINDS.join(", ")}.`);
|
|
23
|
+
}
|
|
24
|
+
return kinds;
|
|
25
|
+
}
|
|
26
|
+
export async function backfillBodies(store, input = {}) {
|
|
27
|
+
const snapshot = await store.getDatabaseSnapshot();
|
|
28
|
+
const kinds = input.kinds ?? [...BACKFILLABLE_BODY_KINDS];
|
|
29
|
+
const byKind = [];
|
|
30
|
+
for (const kind of kinds) {
|
|
31
|
+
const entities = sortEntities(snapshot.entities.filter((entity) => entity.kind === kind));
|
|
32
|
+
let updated = 0;
|
|
33
|
+
let skipped = 0;
|
|
34
|
+
for (const entity of entities) {
|
|
35
|
+
const body = buildBody(kind);
|
|
36
|
+
if (body.trim().length === 0) {
|
|
37
|
+
skipped += 1;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const hasStoredBody = entity.body.trim().length > 0;
|
|
41
|
+
const matchesGeneratedBody = hasStoredBody && entity.body === body;
|
|
42
|
+
if (!input.force && hasStoredBody && !matchesGeneratedBody) {
|
|
43
|
+
skipped += 1;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (!input.force && matchesGeneratedBody && entity.bodySource === "generated") {
|
|
47
|
+
skipped += 1;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!input.dryRun) {
|
|
51
|
+
await store.setEntityBody({ entityId: entity.id, body, bodySource: "generated", expectedRevision: entity.revision, expectedContentHash: entity.contentHash });
|
|
52
|
+
}
|
|
53
|
+
updated += 1;
|
|
54
|
+
}
|
|
55
|
+
byKind.push({
|
|
56
|
+
kind,
|
|
57
|
+
considered: entities.length,
|
|
58
|
+
updated,
|
|
59
|
+
skipped
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
tenantId: store.tenantId,
|
|
64
|
+
dryRun: input.dryRun ?? false,
|
|
65
|
+
force: input.force ?? false,
|
|
66
|
+
kinds,
|
|
67
|
+
considered: byKind.reduce((sum, item) => sum + item.considered, 0),
|
|
68
|
+
updated: byKind.reduce((sum, item) => sum + item.updated, 0),
|
|
69
|
+
skipped: byKind.reduce((sum, item) => sum + item.skipped, 0),
|
|
70
|
+
byKind
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function buildBody(kind) {
|
|
74
|
+
switch (kind) {
|
|
75
|
+
case "project":
|
|
76
|
+
return buildManagementBody();
|
|
77
|
+
case "epic":
|
|
78
|
+
return buildManagementBody();
|
|
79
|
+
case "version":
|
|
80
|
+
return buildVersionBody();
|
|
81
|
+
case "initiative":
|
|
82
|
+
return buildInitiativeBody();
|
|
83
|
+
case "issue":
|
|
84
|
+
return buildIssueBody();
|
|
85
|
+
case "prd":
|
|
86
|
+
return buildPrdBody();
|
|
87
|
+
case "userStory":
|
|
88
|
+
return buildUserStoryBody();
|
|
89
|
+
case "adr":
|
|
90
|
+
return buildAdrBody();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function buildManagementBody() {
|
|
94
|
+
return [
|
|
95
|
+
"## Purpose",
|
|
96
|
+
"",
|
|
97
|
+
DERIVED_CONTENT_MARKER,
|
|
98
|
+
"",
|
|
99
|
+
"## Scope",
|
|
100
|
+
"",
|
|
101
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
102
|
+
"",
|
|
103
|
+
"## Success Conditions",
|
|
104
|
+
"",
|
|
105
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
106
|
+
"",
|
|
107
|
+
"## Non-Goals",
|
|
108
|
+
"",
|
|
109
|
+
`- ${DERIVED_CONTENT_MARKER}`
|
|
110
|
+
].join("\n");
|
|
111
|
+
}
|
|
112
|
+
function buildVersionBody() {
|
|
113
|
+
return [
|
|
114
|
+
"## Release Intent",
|
|
115
|
+
"",
|
|
116
|
+
DERIVED_CONTENT_MARKER,
|
|
117
|
+
"",
|
|
118
|
+
"## Compatibility and Migration Notes",
|
|
119
|
+
"",
|
|
120
|
+
`- ${DERIVED_CONTENT_MARKER}`
|
|
121
|
+
].join("\n");
|
|
122
|
+
}
|
|
123
|
+
function buildInitiativeBody() {
|
|
124
|
+
return buildManagementBody();
|
|
125
|
+
}
|
|
126
|
+
function buildIssueBody() {
|
|
127
|
+
return [
|
|
128
|
+
"## Work Mode",
|
|
129
|
+
"",
|
|
130
|
+
DERIVED_CONTENT_MARKER,
|
|
131
|
+
"",
|
|
132
|
+
"## Outcome",
|
|
133
|
+
"",
|
|
134
|
+
DERIVED_CONTENT_MARKER,
|
|
135
|
+
"",
|
|
136
|
+
"## Scope",
|
|
137
|
+
"",
|
|
138
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
139
|
+
"",
|
|
140
|
+
"## Work Plan",
|
|
141
|
+
"",
|
|
142
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
143
|
+
"",
|
|
144
|
+
"## Acceptance Criteria",
|
|
145
|
+
"",
|
|
146
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
147
|
+
"",
|
|
148
|
+
"## Verification",
|
|
149
|
+
"",
|
|
150
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
151
|
+
"",
|
|
152
|
+
"## Notes",
|
|
153
|
+
"",
|
|
154
|
+
DERIVED_CONTENT_MARKER
|
|
155
|
+
].join("\n");
|
|
156
|
+
}
|
|
157
|
+
function buildPrdBody() {
|
|
158
|
+
return [
|
|
159
|
+
"## Problem Statement",
|
|
160
|
+
"",
|
|
161
|
+
DERIVED_CONTENT_MARKER,
|
|
162
|
+
"",
|
|
163
|
+
"## Solution",
|
|
164
|
+
"",
|
|
165
|
+
DERIVED_CONTENT_MARKER,
|
|
166
|
+
"",
|
|
167
|
+
"## Implementation Decisions",
|
|
168
|
+
"",
|
|
169
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
170
|
+
"",
|
|
171
|
+
"## Testing Decisions",
|
|
172
|
+
"",
|
|
173
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
174
|
+
"",
|
|
175
|
+
"## Out of Scope",
|
|
176
|
+
"",
|
|
177
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
178
|
+
"",
|
|
179
|
+
"## Further Notes",
|
|
180
|
+
"",
|
|
181
|
+
DERIVED_CONTENT_MARKER
|
|
182
|
+
].join("\n");
|
|
183
|
+
}
|
|
184
|
+
function buildUserStoryBody() {
|
|
185
|
+
return [
|
|
186
|
+
`As an actor, I want ${DERIVED_CONTENT_MARKER}, so that ${DERIVED_CONTENT_MARKER}`,
|
|
187
|
+
"",
|
|
188
|
+
"## Acceptance Criteria",
|
|
189
|
+
"",
|
|
190
|
+
`- ${DERIVED_CONTENT_MARKER}`,
|
|
191
|
+
"",
|
|
192
|
+
"## Boundaries",
|
|
193
|
+
"",
|
|
194
|
+
`- ${DERIVED_CONTENT_MARKER}`
|
|
195
|
+
].join("\n");
|
|
196
|
+
}
|
|
197
|
+
function buildAdrBody() {
|
|
198
|
+
return [
|
|
199
|
+
"## Status",
|
|
200
|
+
"",
|
|
201
|
+
DERIVED_CONTENT_MARKER,
|
|
202
|
+
"",
|
|
203
|
+
"## Context",
|
|
204
|
+
"",
|
|
205
|
+
DERIVED_CONTENT_MARKER,
|
|
206
|
+
"",
|
|
207
|
+
"## Decision",
|
|
208
|
+
"",
|
|
209
|
+
DERIVED_CONTENT_MARKER,
|
|
210
|
+
"",
|
|
211
|
+
"## Consequences",
|
|
212
|
+
"",
|
|
213
|
+
`- ${DERIVED_CONTENT_MARKER}`
|
|
214
|
+
].join("\n");
|
|
215
|
+
}
|
|
216
|
+
function sortEntities(entities) {
|
|
217
|
+
return [...entities].sort((left, right) => left.id.localeCompare(right.id, undefined, { numeric: true }));
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=body-backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-backfill.js","sourceRoot":"","sources":["../src/body-backfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BUILD_MODE: "development" | "production";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const BUILD_MODE = "production";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-mode.js","sourceRoot":"","sources":["../src/build-mode.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAiC,aAAa,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type SavedLoginStoreOptions, type RemoteSavedLogin } from "../../auth-session.js";
|
|
2
|
+
import { BaseCommand } from "../shared.js";
|
|
3
|
+
export type DeviceCodeLoginResult = {
|
|
4
|
+
tenantId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
displayName?: string;
|
|
7
|
+
accessToken: string;
|
|
8
|
+
expiresAt: string;
|
|
9
|
+
};
|
|
10
|
+
/** Reports the human-readable device-code instructions Entra returns (e.g. "go to microsoft.com/devicelogin and enter code ABCD-EFGH"). */
|
|
11
|
+
export type DeviceCodePrompt = (message: string) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Runs the interactive Entra ID device-code exchange and resolves the
|
|
14
|
+
* identity + token it produced. The real implementation
|
|
15
|
+
* (`../../entra-device-login.js`) is the genuine HITL gap this repo cannot
|
|
16
|
+
* exercise: it requires a human to complete a device-code login in a
|
|
17
|
+
* browser against a real Azure tenant (ISS32's acceptance criteria).
|
|
18
|
+
*/
|
|
19
|
+
export type DeviceCodeLoginFn = (options: {
|
|
20
|
+
tenantId: string;
|
|
21
|
+
clientId: string;
|
|
22
|
+
onDeviceCode: DeviceCodePrompt;
|
|
23
|
+
}) => Promise<DeviceCodeLoginResult>;
|
|
24
|
+
export type RemoteLoginDependencies = {
|
|
25
|
+
deviceCodeLogin: DeviceCodeLoginFn;
|
|
26
|
+
fetch?: typeof globalThis.fetch;
|
|
27
|
+
onDeviceCode: DeviceCodePrompt;
|
|
28
|
+
storeOptions?: SavedLoginStoreOptions;
|
|
29
|
+
};
|
|
30
|
+
export declare function performRemoteLogin(input: {
|
|
31
|
+
name: string;
|
|
32
|
+
serviceUrl: string;
|
|
33
|
+
}, dependencies: RemoteLoginDependencies): Promise<RemoteSavedLogin>;
|
|
34
|
+
export declare class AuthLoginCommand extends BaseCommand {
|
|
35
|
+
static paths: string[][];
|
|
36
|
+
name: string | undefined;
|
|
37
|
+
serviceUrl: string | undefined;
|
|
38
|
+
execute(): Promise<number>;
|
|
39
|
+
private loginRemote;
|
|
40
|
+
private resolveRemoteInput;
|
|
41
|
+
private prompt;
|
|
42
|
+
}
|
|
43
|
+
export declare class AuthListCommand extends BaseCommand {
|
|
44
|
+
static paths: string[][];
|
|
45
|
+
execute(): Promise<number>;
|
|
46
|
+
}
|
|
47
|
+
export declare class AuthLogoutCommand extends BaseCommand {
|
|
48
|
+
static paths: string[][];
|
|
49
|
+
positionals: string[];
|
|
50
|
+
execute(): Promise<number>;
|
|
51
|
+
}
|
|
52
|
+
export declare class AuthStatusCommand extends BaseCommand {
|
|
53
|
+
static paths: string[][];
|
|
54
|
+
execute(): Promise<number>;
|
|
55
|
+
}
|
|
56
|
+
export declare class AuthSwitchCommand extends BaseCommand {
|
|
57
|
+
static paths: string[][];
|
|
58
|
+
positionals: string[];
|
|
59
|
+
execute(): Promise<number>;
|
|
60
|
+
private getNextSavedLoginName;
|
|
61
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { Option } from "clipanion";
|
|
3
|
+
import { getActiveSavedLogin, listSavedLogins, removeSavedLogin, saveSavedLogin, setActiveSavedLogin, toSavedLoginView } from "../../auth-session.js";
|
|
4
|
+
import { discoverServiceAuth } from "../../service-discovery.js";
|
|
5
|
+
import { renderAuthList, renderAuthLogin, renderAuthLogout, renderAuthStatus, renderAuthSwitch } from "../renderers.js";
|
|
6
|
+
import { BaseCommand } from "../shared.js";
|
|
7
|
+
export async function performRemoteLogin(input, dependencies) {
|
|
8
|
+
if (input.name === "local") {
|
|
9
|
+
throw new Error('Saved-login name "local" is reserved.');
|
|
10
|
+
}
|
|
11
|
+
const discovered = await discoverServiceAuth(input.serviceUrl, dependencies.fetch);
|
|
12
|
+
const result = await dependencies.deviceCodeLogin({
|
|
13
|
+
tenantId: discovered.auth.tenantId,
|
|
14
|
+
clientId: discovered.auth.clientId,
|
|
15
|
+
onDeviceCode: dependencies.onDeviceCode
|
|
16
|
+
});
|
|
17
|
+
const login = {
|
|
18
|
+
name: input.name,
|
|
19
|
+
kind: "remote",
|
|
20
|
+
serviceUrl: discovered.serviceUrl,
|
|
21
|
+
tenantId: result.tenantId,
|
|
22
|
+
userId: result.userId,
|
|
23
|
+
displayName: result.displayName,
|
|
24
|
+
accessToken: result.accessToken,
|
|
25
|
+
expiresAt: result.expiresAt
|
|
26
|
+
};
|
|
27
|
+
await saveSavedLogin(login, dependencies.storeOptions);
|
|
28
|
+
return login;
|
|
29
|
+
}
|
|
30
|
+
export class AuthLoginCommand extends BaseCommand {
|
|
31
|
+
static paths = [["auth", "login"]];
|
|
32
|
+
name = Option.String("--name");
|
|
33
|
+
serviceUrl = Option.String("--url");
|
|
34
|
+
async execute() {
|
|
35
|
+
const login = await this.loginRemote();
|
|
36
|
+
const view = toSavedLoginView(login);
|
|
37
|
+
this.print({ command: "auth-login", login: view }, renderAuthLogin(view));
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
async loginRemote() {
|
|
41
|
+
const { name, serviceUrl } = await this.resolveRemoteInput();
|
|
42
|
+
const dependencies = this.context.authLoginDependencies;
|
|
43
|
+
const deviceCodeLogin = dependencies?.deviceCodeLogin
|
|
44
|
+
?? (await import("../../entra-device-login.js")).acquireEntraDeviceCodeSession;
|
|
45
|
+
return performRemoteLogin({ name, serviceUrl }, {
|
|
46
|
+
deviceCodeLogin,
|
|
47
|
+
fetch: dependencies?.fetch,
|
|
48
|
+
onDeviceCode: (message) => this.context.stdout.write(`${message}\n`),
|
|
49
|
+
storeOptions: this.context.credentialStoreOptions
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async resolveRemoteInput() {
|
|
53
|
+
let name = this.name?.trim();
|
|
54
|
+
let serviceUrl = this.serviceUrl?.trim();
|
|
55
|
+
if (this.asJson) {
|
|
56
|
+
if (!name)
|
|
57
|
+
throw new Error("`auth login --json` requires --name <name>.");
|
|
58
|
+
if (!serviceUrl)
|
|
59
|
+
throw new Error("`auth login --json` requires --url <url>.");
|
|
60
|
+
return { name, serviceUrl };
|
|
61
|
+
}
|
|
62
|
+
const dependencies = this.context.authLoginDependencies;
|
|
63
|
+
const interactive = dependencies?.interactive ?? (process.stdin.isTTY === true && process.stdout.isTTY === true);
|
|
64
|
+
if ((!name || !serviceUrl) && !interactive) {
|
|
65
|
+
throw new Error("`auth login` requires --name <name> and --url <url> outside an interactive terminal.");
|
|
66
|
+
}
|
|
67
|
+
const prompt = dependencies?.prompt ?? ((question) => this.prompt(question));
|
|
68
|
+
name ||= (await prompt("Saved login name: ")).trim();
|
|
69
|
+
serviceUrl ||= (await prompt("Service URL: ")).trim();
|
|
70
|
+
if (!name)
|
|
71
|
+
throw new Error("Saved-login name cannot be empty.");
|
|
72
|
+
if (!serviceUrl)
|
|
73
|
+
throw new Error("Service URL cannot be empty.");
|
|
74
|
+
return { name, serviceUrl };
|
|
75
|
+
}
|
|
76
|
+
async prompt(question) {
|
|
77
|
+
const readline = createInterface({ input: process.stdin, output: this.context.stdout, terminal: true });
|
|
78
|
+
try {
|
|
79
|
+
return await readline.question(question);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
readline.close();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export class AuthListCommand extends BaseCommand {
|
|
87
|
+
static paths = [["auth", "list"]];
|
|
88
|
+
async execute() {
|
|
89
|
+
const logins = await listSavedLogins(this.context.credentialStoreOptions);
|
|
90
|
+
const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
|
|
91
|
+
const views = logins.map((login) => ({ login: toSavedLoginView(login), active: login.name === active.name }));
|
|
92
|
+
this.print({ command: "auth-list", logins: views }, renderAuthList(views));
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export class AuthLogoutCommand extends BaseCommand {
|
|
97
|
+
static paths = [["auth", "logout"]];
|
|
98
|
+
positionals = Option.Rest();
|
|
99
|
+
async execute() {
|
|
100
|
+
const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
|
|
101
|
+
const name = this.positionals[0] ?? active.name;
|
|
102
|
+
await removeSavedLogin(name, this.context.credentialStoreOptions);
|
|
103
|
+
this.print({ command: "auth-logout", name }, renderAuthLogout(name));
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export class AuthStatusCommand extends BaseCommand {
|
|
108
|
+
static paths = [["auth", "status"]];
|
|
109
|
+
async execute() {
|
|
110
|
+
const login = await getActiveSavedLogin(this.context.credentialStoreOptions);
|
|
111
|
+
const view = toSavedLoginView(login);
|
|
112
|
+
this.print({ command: "auth-status", login: view }, renderAuthStatus(view));
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export class AuthSwitchCommand extends BaseCommand {
|
|
117
|
+
static paths = [["auth", "switch"]];
|
|
118
|
+
positionals = Option.Rest();
|
|
119
|
+
async execute() {
|
|
120
|
+
const name = this.positionals[0] ?? (await this.getNextSavedLoginName());
|
|
121
|
+
await setActiveSavedLogin(name, this.context.credentialStoreOptions);
|
|
122
|
+
const login = await getActiveSavedLogin(this.context.credentialStoreOptions);
|
|
123
|
+
const view = toSavedLoginView(login);
|
|
124
|
+
this.print({ command: "auth-switch", login: view }, renderAuthSwitch(view));
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
async getNextSavedLoginName() {
|
|
128
|
+
const logins = await listSavedLogins(this.context.credentialStoreOptions);
|
|
129
|
+
const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
|
|
130
|
+
const activeIndex = logins.findIndex(({ name }) => name === active.name);
|
|
131
|
+
return logins[(activeIndex + 1) % logins.length].name;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Option } from "clipanion";
|
|
2
|
+
import { backfillBodies, parseBackfillableBodyKinds } from "@agent-issues/core";
|
|
3
|
+
import { renderBackfillBodies } from "../renderers.js";
|
|
4
|
+
import { MutableTenantCommand, parseCsvOption, withStore } from "../shared.js";
|
|
5
|
+
export class BackfillBodiesCommand extends MutableTenantCommand {
|
|
6
|
+
static paths = [["backfill-bodies"]];
|
|
7
|
+
allTenants = Option.Boolean("--all-tenants", false);
|
|
8
|
+
dryRun = Option.Boolean("--dry-run", false);
|
|
9
|
+
kinds = Option.String("--kinds");
|
|
10
|
+
async execute() {
|
|
11
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store, dbPath) => {
|
|
12
|
+
const kinds = parseBackfillableBodyKinds(parseCsvOption(this.kinds));
|
|
13
|
+
const tenantIds = this.allTenants ? (await store.listTenants()).map((tenant) => tenant.id) : [store.tenantId];
|
|
14
|
+
const tenants = [];
|
|
15
|
+
for (const tenantId of tenantIds) {
|
|
16
|
+
if (tenantId === store.tenantId) {
|
|
17
|
+
tenants.push(await backfillBodies(store, { dryRun: this.dryRun, force: this.force, kinds }));
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
tenants.push(await withStore(this.dbPath, this.withStoreOptions({ tenant: tenantId }), (tenantStore) => backfillBodies(tenantStore, { dryRun: this.dryRun, force: this.force, kinds })));
|
|
21
|
+
}
|
|
22
|
+
const result = {
|
|
23
|
+
command: "backfill-bodies",
|
|
24
|
+
dbPath,
|
|
25
|
+
dryRun: this.dryRun,
|
|
26
|
+
force: this.force,
|
|
27
|
+
kinds,
|
|
28
|
+
scope: this.allTenants ? "all-tenants" : "current-tenant",
|
|
29
|
+
tenants
|
|
30
|
+
};
|
|
31
|
+
this.print(result, renderBackfillBodies(result));
|
|
32
|
+
return 0;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../../src/cli/commands/backfill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/E,MAAM,OAAO,qBAAsB,SAAQ,oBAAoB;IACvD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAErC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACpD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC5C,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEjC,KAAK,CAAC,OAAO;QACnB,OAAO,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC9E,MAAM,KAAK,GAAG,0BAA0B,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE9G,MAAM,OAAO,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBAClC,IAAI,QAAQ,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACjC,OAAO,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;oBAC7F,SAAS;gBACV,CAAC;gBAED,OAAO,CAAC,IAAI,CACX,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CACzF,cAAc,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAC9E,CACD,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG;gBACd,OAAO,EAAE,iBAA0B;gBACnC,MAAM;gBACN,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK;gBACL,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,aAAuB,CAAC,CAAC,CAAE,gBAA0B;gBAC/E,OAAO;aACP,CAAC;YAEF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseCommand, BodyTenantCommand, TenantCommand } from "../shared.js";
|
|
2
|
+
export declare class IssueCommentCommand extends BaseCommand {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
execute(): Promise<number>;
|
|
5
|
+
}
|
|
6
|
+
export declare class AddIssueCommentCommand extends BodyTenantCommand {
|
|
7
|
+
static paths: string[][];
|
|
8
|
+
positionals: string[];
|
|
9
|
+
references: string[] | undefined;
|
|
10
|
+
execute(): Promise<number>;
|
|
11
|
+
}
|
|
12
|
+
export declare class EditIssueCommentCommand extends BodyTenantCommand {
|
|
13
|
+
static paths: string[][];
|
|
14
|
+
positionals: string[];
|
|
15
|
+
references: string[] | undefined;
|
|
16
|
+
execute(): Promise<number>;
|
|
17
|
+
}
|
|
18
|
+
export declare class DeleteIssueCommentCommand extends TenantCommand {
|
|
19
|
+
static paths: string[][];
|
|
20
|
+
positionals: string[];
|
|
21
|
+
execute(): Promise<number>;
|
|
22
|
+
}
|
|
23
|
+
export declare class IssueCommentHistoryCommand extends TenantCommand {
|
|
24
|
+
static paths: string[][];
|
|
25
|
+
positionals: string[];
|
|
26
|
+
execute(): Promise<number>;
|
|
27
|
+
}
|
|
28
|
+
export declare class ListIssueCommentsCommand extends TenantCommand {
|
|
29
|
+
static paths: string[][];
|
|
30
|
+
all: boolean;
|
|
31
|
+
before: string | undefined;
|
|
32
|
+
positionals: string[];
|
|
33
|
+
execute(): Promise<number>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Option } from "clipanion";
|
|
2
|
+
import { getHelpPayload, renderHelp } from "../../help.js";
|
|
3
|
+
import { BaseCommand, BodyTenantCommand, TenantCommand, requireOption, requirePositional, withStore } from "../shared.js";
|
|
4
|
+
export class IssueCommentCommand extends BaseCommand {
|
|
5
|
+
static paths = [["comment"]];
|
|
6
|
+
async execute() {
|
|
7
|
+
const payload = getHelpPayload("comment");
|
|
8
|
+
this.print(payload, renderHelp(payload));
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class AddIssueCommentCommand extends BodyTenantCommand {
|
|
13
|
+
static paths = [["comment", "add"]];
|
|
14
|
+
positionals = Option.Rest();
|
|
15
|
+
references = Option.Array("--reference");
|
|
16
|
+
async execute() {
|
|
17
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
|
|
18
|
+
const referencedIssueIds = await resolveReferencedIssueIds(store, this.references ?? []);
|
|
19
|
+
const comment = await store.createIssueComment({
|
|
20
|
+
issueId: requirePositional(this.positionals, 0, "comment add <issueId> --body-file <path|-> [--reference <issueId>]"),
|
|
21
|
+
body: requireOption(await this.resolveBody(), "--body-file is required for comment add."),
|
|
22
|
+
referencedIssueIds
|
|
23
|
+
});
|
|
24
|
+
this.print(comment, renderIssueComment(comment));
|
|
25
|
+
return 0;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class EditIssueCommentCommand extends BodyTenantCommand {
|
|
30
|
+
static paths = [["comment", "edit"]];
|
|
31
|
+
positionals = Option.Rest();
|
|
32
|
+
references = Option.Array("--reference");
|
|
33
|
+
async execute() {
|
|
34
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
|
|
35
|
+
const issueId = requirePositional(this.positionals, 0, "comment edit <issueId> <commentId> --body-file <path|-> [--reference <issueId>]");
|
|
36
|
+
const commentId = requirePositional(this.positionals, 1, "comment edit <issueId> <commentId> --body-file <path|-> [--reference <issueId>]");
|
|
37
|
+
const comment = await getIssueComment(store, issueId, commentId);
|
|
38
|
+
const referencedIssueIds = this.references === undefined
|
|
39
|
+
? undefined
|
|
40
|
+
: await resolveReferencedIssueIds(store, this.references);
|
|
41
|
+
const updated = await store.updateIssueComment({
|
|
42
|
+
commentId,
|
|
43
|
+
body: requireOption(await this.resolveBody(), "--body-file is required for comment edit."),
|
|
44
|
+
referencedIssueIds,
|
|
45
|
+
expectedRevision: comment.revision,
|
|
46
|
+
expectedContentHash: comment.contentHash
|
|
47
|
+
});
|
|
48
|
+
this.print(updated, renderIssueComment(updated));
|
|
49
|
+
return 0;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export class DeleteIssueCommentCommand extends TenantCommand {
|
|
54
|
+
static paths = [["comment", "delete"]];
|
|
55
|
+
positionals = Option.Rest();
|
|
56
|
+
async execute() {
|
|
57
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
|
|
58
|
+
const issueId = requirePositional(this.positionals, 0, "comment delete <issueId> <commentId>");
|
|
59
|
+
const commentId = requirePositional(this.positionals, 1, "comment delete <issueId> <commentId>");
|
|
60
|
+
const comment = await getIssueComment(store, issueId, commentId);
|
|
61
|
+
const deleted = await store.deleteIssueComment({
|
|
62
|
+
commentId,
|
|
63
|
+
expectedRevision: comment.revision,
|
|
64
|
+
expectedContentHash: comment.contentHash
|
|
65
|
+
});
|
|
66
|
+
this.print(deleted, renderIssueComment(deleted));
|
|
67
|
+
return 0;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export class IssueCommentHistoryCommand extends TenantCommand {
|
|
72
|
+
static paths = [["comment", "history"]];
|
|
73
|
+
positionals = Option.Rest();
|
|
74
|
+
async execute() {
|
|
75
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
|
|
76
|
+
const history = await store.listIssueCommentHistory({
|
|
77
|
+
commentId: requirePositional(this.positionals, 0, "comment history <commentId>")
|
|
78
|
+
});
|
|
79
|
+
this.print(history, history.map(renderIssueCommentHistory).join("\n") || "No comment history found.");
|
|
80
|
+
return 0;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export class ListIssueCommentsCommand extends TenantCommand {
|
|
85
|
+
static paths = [["comment", "list"]];
|
|
86
|
+
all = Option.Boolean("--all", false);
|
|
87
|
+
before = Option.String("--before");
|
|
88
|
+
positionals = Option.Rest();
|
|
89
|
+
async execute() {
|
|
90
|
+
return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
|
|
91
|
+
const page = await store.listIssueComments({
|
|
92
|
+
issueId: requirePositional(this.positionals, 0, "comment list <issueId> [--before <cursor>] [--all]"),
|
|
93
|
+
before: this.before,
|
|
94
|
+
all: this.all
|
|
95
|
+
});
|
|
96
|
+
this.print(page, page.comments.map(renderIssueComment).join("\n") || "No comments found.");
|
|
97
|
+
return 0;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function renderIssueComment(comment) {
|
|
102
|
+
if (comment.tombstone) {
|
|
103
|
+
return `${comment.reference} deleted ${comment.updatedAt}`;
|
|
104
|
+
}
|
|
105
|
+
return `${comment.reference} by ${comment.createdBy}\n${comment.body}`;
|
|
106
|
+
}
|
|
107
|
+
function renderIssueCommentHistory(entry) {
|
|
108
|
+
return `revision ${entry.targetRevision}/${entry.headRevision} by ${entry.author} ${entry.createdAt}${entry.tombstone ? " deleted" : ""}\n${entry.body}`;
|
|
109
|
+
}
|
|
110
|
+
async function getIssueComment(store, issueId, commentId) {
|
|
111
|
+
const issue = await store.getEntityDetails(issueId);
|
|
112
|
+
const comment = (await store.listIssueComments({ issueId: issue.entity.id, all: true })).comments
|
|
113
|
+
.find((candidate) => candidate.id === commentId || candidate.reference === commentId);
|
|
114
|
+
if (!comment) {
|
|
115
|
+
throw new Error(`Issue comment not found: ${commentId}`);
|
|
116
|
+
}
|
|
117
|
+
return comment;
|
|
118
|
+
}
|
|
119
|
+
async function resolveReferencedIssueIds(store, references) {
|
|
120
|
+
return await Promise.all(references.map(async (reference) => {
|
|
121
|
+
return (await store.getEntityDetails(reference)).entity.id;
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=comments.js.map
|