dsh-plugin-github-issues 0.0.0-stage → 0.4.7

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 (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -2
  3. package/cordis.patch.yml +20 -0
  4. package/docs/README.zh.md +134 -0
  5. package/icon.svg +9 -0
  6. package/lib/client.js +3243 -0
  7. package/lib/controller.js +289 -0
  8. package/lib/controller.js.map +1 -0
  9. package/lib/github/auth.js +249 -0
  10. package/lib/github/auth.js.map +1 -0
  11. package/lib/github/client.js +767 -0
  12. package/lib/github/client.js.map +1 -0
  13. package/lib/github/queries.js +479 -0
  14. package/lib/github/queries.js.map +1 -0
  15. package/lib/github/state.js +186 -0
  16. package/lib/github/state.js.map +1 -0
  17. package/lib/github/types.js +29 -0
  18. package/lib/github/types.js.map +1 -0
  19. package/lib/github/vm.js +362 -0
  20. package/lib/github/vm.js.map +1 -0
  21. package/lib/index.js +65 -0
  22. package/lib/index.js.map +1 -0
  23. package/lib/prompt.js +87 -0
  24. package/lib/prompt.js.map +1 -0
  25. package/lib/remote-methods.js +32 -0
  26. package/lib/remote-methods.js.map +1 -0
  27. package/lib/types/controller.d.ts +105 -0
  28. package/lib/types/controller.d.ts.map +1 -0
  29. package/lib/types/github/auth.d.ts +52 -0
  30. package/lib/types/github/auth.d.ts.map +1 -0
  31. package/lib/types/github/client.d.ts +40 -0
  32. package/lib/types/github/client.d.ts.map +1 -0
  33. package/lib/types/github/queries.d.ts +172 -0
  34. package/lib/types/github/queries.d.ts.map +1 -0
  35. package/lib/types/github/state.d.ts +51 -0
  36. package/lib/types/github/state.d.ts.map +1 -0
  37. package/lib/types/github/types.d.ts +79 -0
  38. package/lib/types/github/types.d.ts.map +1 -0
  39. package/lib/types/github/vm.d.ts +260 -0
  40. package/lib/types/github/vm.d.ts.map +1 -0
  41. package/lib/types/index.d.ts +46 -0
  42. package/lib/types/index.d.ts.map +1 -0
  43. package/lib/types/prompt.d.ts +30 -0
  44. package/lib/types/prompt.d.ts.map +1 -0
  45. package/lib/types/remote-methods.d.ts +32 -0
  46. package/lib/types/remote-methods.d.ts.map +1 -0
  47. package/lib/types/vm.d.ts +264 -0
  48. package/lib/types/vm.d.ts.map +1 -0
  49. package/lib/types/workspace.d.ts +43 -0
  50. package/lib/types/workspace.d.ts.map +1 -0
  51. package/lib/vm.js +42 -0
  52. package/lib/vm.js.map +1 -0
  53. package/lib/workspace.js +57 -0
  54. package/lib/workspace.js.map +1 -0
  55. package/locale/en.json +6 -0
  56. package/locale/zh.json +6 -0
  57. package/package.json +97 -4
@@ -0,0 +1,289 @@
1
+ /**
2
+ * The browser's way into GitHub.
3
+ *
4
+ * Everything that needs a credential happens here or below: the token is resolved
5
+ * on the Host, cached briefly in memory, and used only in an `Authorization`
6
+ * header. The browser half receives JSON view models and never a token.
7
+ *
8
+ * One `GitHubApi` is created lazily on the first call and re-created after a
9
+ * 401 (the machine's `gh` token may have been refreshed or revoked between
10
+ * sessions) or when the settings page asks for a refresh.
11
+ *
12
+ * @module dsh-plugin-github-issues/controller
13
+ */
14
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
15
+ var useValue = arguments.length > 2;
16
+ for (var i = 0; i < initializers.length; i++) {
17
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
18
+ }
19
+ return useValue ? value : void 0;
20
+ };
21
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
22
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
23
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
24
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
25
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
26
+ var _, done = false;
27
+ for (var i = decorators.length - 1; i >= 0; i--) {
28
+ var context = {};
29
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
30
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
31
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
32
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
33
+ if (kind === "accessor") {
34
+ if (result === void 0) continue;
35
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
36
+ if (_ = accept(result.get)) descriptor.get = _;
37
+ if (_ = accept(result.set)) descriptor.set = _;
38
+ if (_ = accept(result.init)) initializers.unshift(_);
39
+ }
40
+ else if (_ = accept(result)) {
41
+ if (kind === "field") initializers.unshift(_);
42
+ else descriptor[key] = _;
43
+ }
44
+ }
45
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
46
+ done = true;
47
+ };
48
+ import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
49
+ import { GitHubApiError } from "./github/types.js";
50
+ /** How long one resolved token is reused before asking `gh` again. */
51
+ const TOKEN_TTL_MS = 5 * 60 * 1_000;
52
+ /** Validate a list request that came over the wire. */
53
+ function normalizeRequest(input) {
54
+ const raw = (typeof input === 'object' && input !== null ? input : {});
55
+ const views = ['assigned', 'created', 'open', 'repo', 'project'];
56
+ const view = typeof raw.view === 'string' && views.includes(raw.view)
57
+ ? raw.view
58
+ : undefined;
59
+ const states = ['open', 'closed', 'all'];
60
+ const state = typeof raw.state === 'string' && states.includes(raw.state)
61
+ ? raw.state
62
+ : 'open';
63
+ const repos = Array.isArray(raw.repos)
64
+ ? raw.repos.filter((entry) => typeof entry === 'string' && entry.includes('/')).slice(0, 10)
65
+ : undefined;
66
+ const first = typeof raw.first === 'number' && Number.isFinite(raw.first)
67
+ ? Math.min(Math.max(Math.trunc(raw.first), 1), 50)
68
+ : 30;
69
+ const after = typeof raw.after === 'string' && raw.after !== '' ? raw.after : null;
70
+ const assignee = typeof raw.assignee === 'string' && raw.assignee !== ''
71
+ ? raw.assignee
72
+ : view === 'assigned' ? '@me' : 'all';
73
+ const author = typeof raw.author === 'string' && raw.author !== ''
74
+ ? raw.author
75
+ : view === 'created' ? '@me' : undefined;
76
+ return {
77
+ ...view === undefined ? {} : { view },
78
+ state,
79
+ first,
80
+ after,
81
+ assignee,
82
+ ...author === undefined ? {} : { author },
83
+ ...repos === undefined || repos.length === 0 ? {} : { repos },
84
+ ...typeof raw.projectId === 'string' && raw.projectId !== '' ? { projectId: raw.projectId } : {},
85
+ ...typeof raw.org === 'string' && raw.org !== '' ? { org: raw.org } : {},
86
+ };
87
+ }
88
+ /** Remote owner of the GitHub Issues surface, namespace `githubIssues`. */
89
+ let GitHubIssuesController = (() => {
90
+ let _classSuper = TypertRemoteService;
91
+ let _instanceExtraInitializers = [];
92
+ let _status_decorators;
93
+ let _catalog_decorators;
94
+ let _listIssues_decorators;
95
+ let _orgProjects_decorators;
96
+ let _orgRepos_decorators;
97
+ let _issueDetail_decorators;
98
+ let _issueMentionedPRs_decorators;
99
+ let _links_decorators;
100
+ let _linkIssue_decorators;
101
+ let _unlinkIssue_decorators;
102
+ let _loadPrefs_decorators;
103
+ let _savePrefs_decorators;
104
+ let _refresh_decorators;
105
+ return class GitHubIssuesController extends _classSuper {
106
+ static {
107
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
108
+ _status_decorators = [Remote];
109
+ _catalog_decorators = [Remote];
110
+ _listIssues_decorators = [Remote];
111
+ _orgProjects_decorators = [Remote];
112
+ _orgRepos_decorators = [Remote];
113
+ _issueDetail_decorators = [Remote];
114
+ _issueMentionedPRs_decorators = [Remote];
115
+ _links_decorators = [Remote];
116
+ _linkIssue_decorators = [Remote];
117
+ _unlinkIssue_decorators = [Remote];
118
+ _loadPrefs_decorators = [Remote];
119
+ _savePrefs_decorators = [Remote];
120
+ _refresh_decorators = [Remote];
121
+ __esDecorate(this, null, _status_decorators, { kind: "method", name: "status", static: false, private: false, access: { has: obj => "status" in obj, get: obj => obj.status }, metadata: _metadata }, null, _instanceExtraInitializers);
122
+ __esDecorate(this, null, _catalog_decorators, { kind: "method", name: "catalog", static: false, private: false, access: { has: obj => "catalog" in obj, get: obj => obj.catalog }, metadata: _metadata }, null, _instanceExtraInitializers);
123
+ __esDecorate(this, null, _listIssues_decorators, { kind: "method", name: "listIssues", static: false, private: false, access: { has: obj => "listIssues" in obj, get: obj => obj.listIssues }, metadata: _metadata }, null, _instanceExtraInitializers);
124
+ __esDecorate(this, null, _orgProjects_decorators, { kind: "method", name: "orgProjects", static: false, private: false, access: { has: obj => "orgProjects" in obj, get: obj => obj.orgProjects }, metadata: _metadata }, null, _instanceExtraInitializers);
125
+ __esDecorate(this, null, _orgRepos_decorators, { kind: "method", name: "orgRepos", static: false, private: false, access: { has: obj => "orgRepos" in obj, get: obj => obj.orgRepos }, metadata: _metadata }, null, _instanceExtraInitializers);
126
+ __esDecorate(this, null, _issueDetail_decorators, { kind: "method", name: "issueDetail", static: false, private: false, access: { has: obj => "issueDetail" in obj, get: obj => obj.issueDetail }, metadata: _metadata }, null, _instanceExtraInitializers);
127
+ __esDecorate(this, null, _issueMentionedPRs_decorators, { kind: "method", name: "issueMentionedPRs", static: false, private: false, access: { has: obj => "issueMentionedPRs" in obj, get: obj => obj.issueMentionedPRs }, metadata: _metadata }, null, _instanceExtraInitializers);
128
+ __esDecorate(this, null, _links_decorators, { kind: "method", name: "links", static: false, private: false, access: { has: obj => "links" in obj, get: obj => obj.links }, metadata: _metadata }, null, _instanceExtraInitializers);
129
+ __esDecorate(this, null, _linkIssue_decorators, { kind: "method", name: "linkIssue", static: false, private: false, access: { has: obj => "linkIssue" in obj, get: obj => obj.linkIssue }, metadata: _metadata }, null, _instanceExtraInitializers);
130
+ __esDecorate(this, null, _unlinkIssue_decorators, { kind: "method", name: "unlinkIssue", static: false, private: false, access: { has: obj => "unlinkIssue" in obj, get: obj => obj.unlinkIssue }, metadata: _metadata }, null, _instanceExtraInitializers);
131
+ __esDecorate(this, null, _loadPrefs_decorators, { kind: "method", name: "loadPrefs", static: false, private: false, access: { has: obj => "loadPrefs" in obj, get: obj => obj.loadPrefs }, metadata: _metadata }, null, _instanceExtraInitializers);
132
+ __esDecorate(this, null, _savePrefs_decorators, { kind: "method", name: "savePrefs", static: false, private: false, access: { has: obj => "savePrefs" in obj, get: obj => obj.savePrefs }, metadata: _metadata }, null, _instanceExtraInitializers);
133
+ __esDecorate(this, null, _refresh_decorators, { kind: "method", name: "refresh", static: false, private: false, access: { has: obj => "refresh" in obj, get: obj => obj.refresh }, metadata: _metadata }, null, _instanceExtraInitializers);
134
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
135
+ }
136
+ options = __runInitializers(this, _instanceExtraInitializers);
137
+ api;
138
+ tokenAt = 0;
139
+ token;
140
+ /**
141
+ * @param ctx - the plugin context this service lives and dies with.
142
+ * @param options - the Host collaborators.
143
+ */
144
+ constructor(ctx, options) {
145
+ super(ctx, 'githubIssuesController', { namespace: 'githubIssues' });
146
+ this.options = options;
147
+ }
148
+ /** Resolve one API session, reusing the token briefly. */
149
+ async apiNow(signal) {
150
+ if (this.api !== undefined && this.token !== undefined && Date.now() - this.tokenAt < TOKEN_TTL_MS) {
151
+ return this.api;
152
+ }
153
+ const authConfig = this.authConfig();
154
+ const auth = await this.options.resolveToken(authConfig, signal);
155
+ this.token = auth;
156
+ this.tokenAt = Date.now();
157
+ this.api = this.options.createApi({ token: auth.token, host: auth.host });
158
+ return this.api;
159
+ }
160
+ /** Forget the cached token and session, so the next call re-resolves them. */
161
+ forgetAuth() {
162
+ this.api = undefined;
163
+ this.token = undefined;
164
+ this.tokenAt = 0;
165
+ }
166
+ ghPath() {
167
+ return this.options.config.ghPath === '' ? undefined : this.options.config.ghPath;
168
+ }
169
+ /** The membership the auth helpers accept, with no `undefined`-valued key. */
170
+ authConfig() {
171
+ const ghPath = this.ghPath();
172
+ return ghPath === undefined
173
+ ? { host: this.options.config.host }
174
+ : { host: this.options.config.host, ghPath };
175
+ }
176
+ /** Run one API operation, retrying once after a 401 with a freshly resolved token. */
177
+ async withApi(operation, signal) {
178
+ try {
179
+ return await operation(await this.apiNow(signal));
180
+ }
181
+ catch (error) {
182
+ if (error instanceof GitHubApiError && error.status === 401) {
183
+ this.forgetAuth();
184
+ return await operation(await this.apiNow(signal));
185
+ }
186
+ throw error;
187
+ }
188
+ }
189
+ /** Auth facts for the settings page: no token, only what `gh auth status` reports. */
190
+ async status() {
191
+ let probe;
192
+ try {
193
+ probe = await this.options.probeGh(this.authConfig());
194
+ }
195
+ catch (error) {
196
+ probe = {
197
+ installed: false,
198
+ signedIn: false,
199
+ scopes: [],
200
+ error: error instanceof Error ? error.message : String(error),
201
+ };
202
+ }
203
+ const scopes = probe.scopes;
204
+ return {
205
+ mode: 'gh',
206
+ ghInstalled: probe.installed,
207
+ ...probe.path === undefined ? {} : { ghPath: probe.path },
208
+ signedIn: probe.signedIn,
209
+ ...probe.login === undefined ? {} : { login: probe.login },
210
+ host: this.options.config.host,
211
+ ...probe.tokenSource === undefined ? {} : { tokenSource: probe.tokenSource },
212
+ scopes,
213
+ missingProjectScope: !scopes.some(scope => scope === 'project' || scope === 'read:project'),
214
+ config: {
215
+ authMode: this.options.config.authMode,
216
+ host: this.options.config.host,
217
+ handoffMode: this.options.config.handoffMode,
218
+ pollSeconds: this.options.config.pollSeconds,
219
+ },
220
+ ...probe.error === undefined ? {} : { error: probe.error },
221
+ };
222
+ }
223
+ /** Repositories, organizations, projects, and the viewer. */
224
+ async catalog() {
225
+ return await this.withApi(api => api.scopes());
226
+ }
227
+ /** Attach the recorded session links to one card. */
228
+ decorate(card) {
229
+ const links = this.options.prefs.linksFor(card.repo, card.number);
230
+ return links.length === 0 ? card : { ...card, sessionLinks: links };
231
+ }
232
+ /** One page of the list. */
233
+ async listIssues(request) {
234
+ const page = await this.withApi(api => api.listIssues(normalizeRequest(request)));
235
+ return { ...page, items: page.items.map(card => this.decorate(card)) };
236
+ }
237
+ /** Projects v2 of one organization; empty and `blocked` without `read:project`. */
238
+ async orgProjects(org) {
239
+ return await this.withApi(api => api.orgProjects(org));
240
+ }
241
+ /** One organization's repositories, loaded when the organization is chosen. */
242
+ async orgRepos(org) {
243
+ return await this.withApi(api => api.orgRepos(org));
244
+ }
245
+ /** One issue with body and linked PRs. */
246
+ async issueDetail(repo, number) {
247
+ return this.withApi(api => api.issueDetail(repo, number));
248
+ }
249
+ /** The issue's cross-referenced pull requests; fetched after the detail shows. */
250
+ async issueMentionedPRs(repo, number) {
251
+ return this.withApi(api => api.issueMentionedPRs(repo, number));
252
+ }
253
+ /** Every recorded issue → session link (the dock resolves its own session). */
254
+ async links() {
255
+ return this.options.prefs.links();
256
+ }
257
+ /** Record that an issue was handed to one session. */
258
+ async linkIssue(repo, number, sessionId) {
259
+ if (typeof repo !== 'string' || repo === '' || !Number.isInteger(number) || number <= 0 || typeof sessionId !== 'string' || sessionId === '') {
260
+ throw new Error('linkIssue: repo, a positive number, and sessionId are required');
261
+ }
262
+ return this.options.prefs.link(repo, number, sessionId);
263
+ }
264
+ /** Remove one issue → session link, or all links of the issue. */
265
+ async unlinkIssue(repo, number, sessionId) {
266
+ return this.options.prefs.unlink(repo, number, sessionId);
267
+ }
268
+ /** Preferences persisted on the Host. */
269
+ async loadPrefs() {
270
+ return this.options.prefs.load();
271
+ }
272
+ /** Merge one preference patch and persist it. */
273
+ async savePrefs(patch) {
274
+ return this.options.prefs.save(patch);
275
+ }
276
+ /**
277
+ * Drop cached GitHub responses and the resolved token so the next request
278
+ * refetches. The token is re-resolved too: the user may have just granted a
279
+ * scope (`gh auth refresh -s read:project`) and the Host must see it at once,
280
+ * not after the five-minute token TTL.
281
+ */
282
+ async refresh() {
283
+ this.forgetAuth();
284
+ return { ok: true };
285
+ }
286
+ };
287
+ })();
288
+ export { GitHubIssuesController };
289
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAG9E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAQlD,sEAAsE;AACtE,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,CAAA;AAgBnC,uDAAuD;AACvD,SAAS,gBAAgB,CAAC,KAAc;IAWtC,MAAM,GAAG,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAA;IACjG,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAU,CAAA;IACzE,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAK,KAA2B,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAC1F,CAAC,CAAC,GAAG,CAAC,IAA8B;QACpC,CAAC,CAAC,SAAS,CAAA;IACb,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAU,CAAA;IACjD,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAK,MAA4B,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9F,CAAC,CAAC,GAAG,CAAC,KAAgC;QACtC,CAAC,CAAC,MAAM,CAAA;IACV,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACpC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7G,CAAC,CAAC,SAAS,CAAA;IACb,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QACvE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QAClD,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;IAClF,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QACtE,CAAC,CAAC,GAAG,CAAC,QAAQ;QACd,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;IACvC,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAChE,CAAC,CAAC,GAAG,CAAC,MAAM;QACZ,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1C,OAAO;QACL,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;QACrC,KAAK;QACL,KAAK;QACL,KAAK;QACL,QAAQ;QACR,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE;QACzC,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE;QAC7D,GAAG,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE;QAChG,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE;KACzE,CAAA;AACH,CAAC;AAED,2EAA2E;IAC9D,sBAAsB;sBAAS,mBAAmB;;;;;;;;;;;;;;;iBAAlD,sBAAuB,SAAQ,WAAmB;;;kCA2D5D,MAAM;mCAmCN,MAAM;sCAYN,MAAM;uCAON,MAAM;oCAMN,MAAM;uCAMN,MAAM;6CAMN,MAAM;iCAMN,MAAM;qCAMN,MAAM;uCASN,MAAM;qCAMN,MAAM;qCAMN,MAAM;mCAWN,MAAM;YAnHP,qKAAM,MAAM,6DA+BX;YAID,wKAAM,OAAO,6DAEZ;YAUD,iLAAM,UAAU,6DAGf;YAID,oLAAM,WAAW,6DAEhB;YAID,2KAAM,QAAQ,6DAEb;YAID,oLAAM,WAAW,6DAEhB;YAID,sMAAM,iBAAiB,6DAEtB;YAID,kKAAM,KAAK,6DAEV;YAID,8KAAM,SAAS,6DAKd;YAID,oLAAM,WAAW,6DAEhB;YAID,8KAAM,SAAS,6DAEd;YAID,8KAAM,SAAS,6DAEd;YASD,wKAAM,OAAO,6DAGZ;;;QA1K0C,OAAO,GATvC,mDAAsB;QACzB,GAAG,CAAuB;QAC1B,OAAO,GAAG,CAAC,CAAA;QACX,KAAK,CAA0B;QAEvC;;;WAGG;QACH,YAAY,GAAY,EAAmB,OAA0B;YACnE,KAAK,CAAC,GAAG,EAAE,wBAAwB,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAA;YAD1B,YAAO,GAAP,OAAO,CAAmB;QAErE,CAAC;QAED,0DAA0D;QAClD,KAAK,CAAC,MAAM,CAAC,MAAoB;YACvC,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,YAAY,EAAE,CAAC;gBACnG,OAAO,IAAI,CAAC,GAAG,CAAA;YACjB,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;YACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;YAChE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;YACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;YACzE,OAAO,IAAI,CAAC,GAAG,CAAA;QACjB,CAAC;QAED,8EAA8E;QACtE,UAAU;YAChB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAA;YACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;YACtB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;QAClB,CAAC;QAEO,MAAM;YACZ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAA;QACnF,CAAC;QAED,8EAA8E;QACtE,UAAU;YAChB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;YAC5B,OAAO,MAAM,KAAK,SAAS;gBACzB,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE;gBACpC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;QAChD,CAAC;QAED,sFAAsF;QAC9E,KAAK,CAAC,OAAO,CAAI,SAAyC,EAAE,MAAoB;YACtF,IAAI,CAAC;gBACH,OAAO,MAAM,SAAS,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,cAAc,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC5D,IAAI,CAAC,UAAU,EAAE,CAAA;oBACjB,OAAO,MAAM,SAAS,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;gBACnD,CAAC;gBACD,MAAM,KAAK,CAAA;YACb,CAAC;QACH,CAAC;QAED,sFAAsF;QAEtF,KAAK,CAAC,MAAM;YACV,IAAI,KAAc,CAAA;YAClB,IAAI,CAAC;gBACH,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;YACvD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,KAAK,GAAG;oBACN,SAAS,EAAE,KAAK;oBAChB,QAAQ,EAAE,KAAK;oBACf,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC9D,CAAA;YACH,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;YAC3B,OAAO;gBACL,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,KAAK,CAAC,SAAS;gBAC5B,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE;gBACzD,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;gBAC1D,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI;gBAC9B,GAAG,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE;gBAC5E,MAAM;gBACN,mBAAmB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,cAAc,CAAC;gBAC3F,MAAM,EAAE;oBACN,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ;oBACtC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI;oBAC9B,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW;oBAC5C,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW;iBAC7C;gBACD,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;aAC3D,CAAA;QACH,CAAC;QAED,6DAA6D;QAE7D,KAAK,CAAC,OAAO;YACX,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAChD,CAAC;QAED,qDAAqD;QAC7C,QAAQ,CAAwB,IAAO;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;YACjE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAA;QACrE,CAAC;QAED,4BAA4B;QAE5B,KAAK,CAAC,UAAU,CAAC,OAAgB;YAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YACjF,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAA;QACxE,CAAC;QAED,mFAAmF;QAEnF,KAAK,CAAC,WAAW,CAAC,GAAW;YAC3B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;QACxD,CAAC;QAED,+EAA+E;QAE/E,KAAK,CAAC,QAAQ,CAAC,GAAW;YACxB,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QACrD,CAAC;QAED,0CAA0C;QAE1C,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,MAAc;YAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QAC3D,CAAC;QAED,kFAAkF;QAElF,KAAK,CAAC,iBAAiB,CAAC,IAAY,EAAE,MAAc;YAClD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACjE,CAAC;QAED,+EAA+E;QAE/E,KAAK,CAAC,KAAK;YACT,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACnC,CAAC;QAED,sDAAsD;QAEtD,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,MAAc,EAAE,SAAiB;YAC7D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;gBAC7I,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;YACnF,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;QACzD,CAAC;QAED,kEAAkE;QAElE,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,MAAc,EAAE,SAAkB;YAChE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;QAC3D,CAAC;QAED,yCAAyC;QAEzC,KAAK,CAAC,SAAS;YACb,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QAClC,CAAC;QAED,iDAAiD;QAEjD,KAAK,CAAC,SAAS,CAAC,KAAc;YAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC;QAED;;;;;WAKG;QAEH,KAAK,CAAC,OAAO;YACX,IAAI,CAAC,UAAU,EAAE,CAAA;YACjB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;QACrB,CAAC;;;SAnLU,sBAAsB"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Resolving the machine's GitHub credential from the `gh` CLI.
3
+ *
4
+ * The plugin never asks for a token in its own UI: a developer machine that can
5
+ * run `gh` can list and read issues, and `gh auth token` hands the Host the same
6
+ * credential. Two invariants matter here:
7
+ *
8
+ * - **The token never leaves this module's success value.** It is not logged, not
9
+ * placed in an error message, and not read from the environment by this code.
10
+ * - **A failure is always actionable.** "gh is missing", "not signed in", and
11
+ * "gh failed" are distinct codes with human messages, so the settings card can
12
+ * tell the user which of the three things to fix.
13
+ *
14
+ * @module dsh-plugin-github-issues/github/auth
15
+ */
16
+ import { execFile } from 'node:child_process';
17
+ import { accessSync, constants, existsSync } from 'node:fs';
18
+ import { GitHubApiError } from "./types.js";
19
+ /** How long one `gh` invocation may take before it is killed. */
20
+ const GH_TIMEOUT_MS = 5_000;
21
+ /** Where Homebrew and the system install `gh`; checked before falling back to PATH. */
22
+ const GH_CANDIDATES = ['/opt/homebrew/bin/gh', '/usr/local/bin/gh', '/usr/bin/gh'];
23
+ /**
24
+ * Resolve the `gh` executable to run.
25
+ * An explicit Config value wins outright (the operator may point at a wrapper);
26
+ * otherwise the usual install locations are tried and a bare `gh` is left for
27
+ * PATH to resolve.
28
+ * @param ghPath - explicit path from Config, if any.
29
+ * @returns the executable path or the bare command name.
30
+ */
31
+ export function resolveGhPath(ghPath) {
32
+ const explicit = ghPath?.trim();
33
+ if (explicit !== undefined && explicit !== '')
34
+ return explicit;
35
+ for (const candidate of GH_CANDIDATES) {
36
+ if (!existsSync(candidate))
37
+ continue;
38
+ try {
39
+ accessSync(candidate, constants.X_OK);
40
+ return candidate;
41
+ }
42
+ catch {
43
+ // Present but not executable: try the next location.
44
+ }
45
+ }
46
+ return 'gh';
47
+ }
48
+ /** Build the error a caller sees when an operation was aborted. */
49
+ function abortReason(signal) {
50
+ const reason = signal?.reason;
51
+ if (reason instanceof Error)
52
+ return reason;
53
+ const error = new Error('The operation was aborted');
54
+ error.name = 'AbortError';
55
+ return error;
56
+ }
57
+ /** Whether a `gh` failure means the executable could not be started. */
58
+ function isMissingExecutable(error) {
59
+ return error !== undefined && (error.code === 'ENOENT' || error.code === 'EACCES');
60
+ }
61
+ /** Whether a `gh` failure came from an abort rather than gh itself. */
62
+ function isAbortError(error) {
63
+ return error !== undefined && (error.name === 'AbortError' || error.code === 'ABORT_ERR');
64
+ }
65
+ /**
66
+ * Remove token-shaped text from a message before it can reach a log or an error.
67
+ * `gh auth status` does not print tokens, but the redaction is cheap insurance
68
+ * for a promise the module makes.
69
+ */
70
+ function redactTokens(text) {
71
+ return text
72
+ .replace(/\b(gh[pousr]_[A-Za-z0-9]{10,}|github_pat_[A-Za-z0-9_]{10,})\b/g, '[redacted]')
73
+ .replace(/[\u0000-\u001f\u007f]+/g, ' ');
74
+ }
75
+ /** Turn gh's stderr into one short, safe line. */
76
+ function safeGhMessage(text) {
77
+ const line = redactTokens(text).trim().split(/\r?\n/)[0] ?? '';
78
+ return line.length > 300 ? `${line.slice(0, 299)}…` : line;
79
+ }
80
+ /** Run `gh` without a shell, with a timeout and an optional abort signal. */
81
+ function runGh(bin, args, signal) {
82
+ return new Promise((resolve) => {
83
+ execFile(bin, [...args], {
84
+ encoding: 'utf8',
85
+ timeout: GH_TIMEOUT_MS,
86
+ maxBuffer: 1024 * 1024,
87
+ windowsHide: true,
88
+ ...signal === undefined ? {} : { signal },
89
+ }, (error, stdout, stderr) => {
90
+ if (error !== null) {
91
+ resolve({ stdout: stdout ?? '', stderr: stderr ?? '', error });
92
+ return;
93
+ }
94
+ resolve({ stdout: stdout ?? '', stderr: stderr ?? '' });
95
+ });
96
+ });
97
+ }
98
+ /** Read `scopes` as an array: newer gh prints a comma-separated string, older a list. */
99
+ function parseScopes(value) {
100
+ if (Array.isArray(value))
101
+ return value.filter((entry) => typeof entry === 'string' && entry !== '');
102
+ if (typeof value === 'string')
103
+ return value.split(',').map(scope => scope.trim()).filter(scope => scope !== '');
104
+ return [];
105
+ }
106
+ /** Flatten the `hosts` object into one entry per account, tolerating both gh shapes. */
107
+ function hostAccountsOf(hosts) {
108
+ if (typeof hosts !== 'object' || hosts === null)
109
+ return [];
110
+ const entries = [];
111
+ for (const [host, value] of Object.entries(hosts)) {
112
+ const accounts = Array.isArray(value)
113
+ ? value.filter((entry) => typeof entry === 'object' && entry !== null)
114
+ : typeof value === 'object' && value !== null ? [value] : [];
115
+ for (const account of accounts)
116
+ entries.push({ host, account });
117
+ }
118
+ return entries;
119
+ }
120
+ /** Pick the account for the configured host, else whichever host is active. */
121
+ function pickAccount(entries, host) {
122
+ const configured = entries.filter(entry => entry.host === host || entry.account.host === host);
123
+ const fromConfigured = configured.find(entry => entry.account.active === true) ?? configured[0];
124
+ if (fromConfigured !== undefined)
125
+ return fromConfigured;
126
+ return entries.find(entry => entry.account.active === true);
127
+ }
128
+ /** The probe result for an account, exposing no secret. */
129
+ function probeOf(host, path, entry) {
130
+ if (entry === undefined) {
131
+ return {
132
+ installed: true,
133
+ path,
134
+ signedIn: false,
135
+ host,
136
+ scopes: [],
137
+ error: `Not signed in to ${host}. Run: gh auth login --hostname ${host}`,
138
+ };
139
+ }
140
+ const signedIn = entry.account.state === 'success';
141
+ const login = typeof entry.account.login === 'string' && entry.account.login !== ''
142
+ ? entry.account.login
143
+ : undefined;
144
+ const tokenSource = typeof entry.account.tokenSource === 'string' && entry.account.tokenSource !== ''
145
+ ? entry.account.tokenSource
146
+ : undefined;
147
+ return {
148
+ installed: true,
149
+ path,
150
+ signedIn,
151
+ host: typeof entry.account.host === 'string' && entry.account.host !== '' ? entry.account.host : entry.host,
152
+ scopes: parseScopes(entry.account.scopes),
153
+ ...login === undefined ? {} : { login },
154
+ ...tokenSource === undefined ? {} : { tokenSource },
155
+ ...signedIn ? {} : { error: `The gh account on ${entry.host} is not usable. Run: gh auth login --hostname ${entry.host}` },
156
+ };
157
+ }
158
+ /**
159
+ * Read what `gh auth status` says about this machine.
160
+ * Never throws for a missing CLI or a signed-out host — those are described by
161
+ * the returned value, because not being signed in is a normal first-run state.
162
+ * Only an abort is rethrown.
163
+ * @param config - host and optional explicit executable path.
164
+ * @param signal - cancellation signal, forwarded to the child process.
165
+ * @returns the probe facts, with `installed` false when gh cannot be started.
166
+ */
167
+ export async function probeGh(config, signal) {
168
+ const path = resolveGhPath(config.ghPath);
169
+ const run = await runGh(path, ['auth', 'status', '--json', 'hosts'], signal);
170
+ if (isAbortError(run.error))
171
+ throw abortReason(signal);
172
+ if (isMissingExecutable(run.error)) {
173
+ return {
174
+ installed: false,
175
+ signedIn: false,
176
+ scopes: [],
177
+ error: 'The GitHub CLI (gh) is not installed. Install it from https://cli.github.com, then run: gh auth login',
178
+ };
179
+ }
180
+ const failure = run.error;
181
+ let parsed;
182
+ try {
183
+ parsed = JSON.parse(run.stdout);
184
+ }
185
+ catch {
186
+ parsed = undefined;
187
+ }
188
+ if (parsed === undefined) {
189
+ const detail = safeGhMessage(run.stderr);
190
+ return {
191
+ installed: true,
192
+ signedIn: false,
193
+ scopes: [],
194
+ error: detail === ''
195
+ ? `gh auth status did not print usable JSON${failure?.killed === true ? ' (timed out)' : ''}.`
196
+ : `gh auth status failed: ${detail}`,
197
+ };
198
+ }
199
+ const hosts = parsed.hosts;
200
+ return probeOf(config.host, path, pickAccount(hostAccountsOf(hosts), config.host));
201
+ }
202
+ /**
203
+ * Resolve the token for the configured host via `gh auth token`.
204
+ * A token is accepted only from a successful invocation; every failure path
205
+ * throws a {@link GitHubApiError} whose message is safe to render.
206
+ * @param config - host and optional explicit executable path.
207
+ * @param signal - cancellation signal, forwarded to the child process.
208
+ * @returns the token plus the account facts the settings card shows.
209
+ */
210
+ export async function resolveToken(config, signal) {
211
+ const path = resolveGhPath(config.ghPath);
212
+ const run = await runGh(path, ['auth', 'token', '--hostname', config.host], signal);
213
+ if (isAbortError(run.error))
214
+ throw abortReason(signal);
215
+ if (isMissingExecutable(run.error)) {
216
+ throw new GitHubApiError('The GitHub CLI (gh) is not installed. Install it from https://cli.github.com, then run: gh auth login', 'gh_missing');
217
+ }
218
+ const token = run.stdout.trim().split(/\r?\n/)[0] ?? '';
219
+ if (run.error !== undefined && run.error.killed === true) {
220
+ throw new GitHubApiError(`gh auth token did not answer within ${String(GH_TIMEOUT_MS / 1_000)} s.`, 'gh_failed');
221
+ }
222
+ if (run.error !== undefined || token === '') {
223
+ const detail = safeGhMessage(run.stderr);
224
+ const signedOut = token === ''
225
+ && (detail === '' || /not logged|no oauth token|not signed in|logged out/i.test(detail));
226
+ if (signedOut) {
227
+ throw new GitHubApiError(`Not signed in to ${config.host} via the gh CLI. Run: gh auth login --hostname ${config.host}`, 'gh_not_signed_in');
228
+ }
229
+ throw new GitHubApiError(`gh could not produce a token for ${config.host}${detail === '' ? '.' : `: ${detail}`}`, 'gh_failed');
230
+ }
231
+ // The token is already usable; a probe failure only loses the cosmetic facts.
232
+ let probe;
233
+ try {
234
+ probe = await probeGh(config, signal);
235
+ }
236
+ catch (error) {
237
+ if (error instanceof Error && error.name === 'AbortError')
238
+ throw error;
239
+ probe = undefined;
240
+ }
241
+ return {
242
+ token,
243
+ source: 'gh',
244
+ host: config.host,
245
+ scopes: probe?.scopes ?? [],
246
+ ...probe?.login === undefined ? {} : { login: probe.login },
247
+ };
248
+ }
249
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/github/auth.ts"],"names":[],"mappings":"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"}