@kolatts/pncli 1.2.0 → 1.4.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.
@@ -0,0 +1,558 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/http.ts
4
+ import fs2 from "fs";
5
+
6
+ // src/lib/errors.ts
7
+ var PncliError = class extends Error {
8
+ status;
9
+ url;
10
+ constructor(message, status = 1, url) {
11
+ super(message);
12
+ this.name = "PncliError";
13
+ this.status = status;
14
+ this.url = url;
15
+ }
16
+ };
17
+
18
+ // src/lib/exitCodes.ts
19
+ var ExitCode = {
20
+ SUCCESS: 0,
21
+ GENERAL_ERROR: 1,
22
+ USAGE_ERROR: 2,
23
+ NETWORK_ERROR: 69,
24
+ // EX_UNAVAILABLE from sysexits.h
25
+ AUTH_ERROR: 77,
26
+ // EX_NOPERM from sysexits.h
27
+ CONFIG_ERROR: 78
28
+ // EX_CONFIG from sysexits.h
29
+ };
30
+ function exitCodeFromStatus(httpStatus) {
31
+ if (httpStatus === 401 || httpStatus === 403) return ExitCode.AUTH_ERROR;
32
+ if (httpStatus === 0) return ExitCode.NETWORK_ERROR;
33
+ return ExitCode.GENERAL_ERROR;
34
+ }
35
+
36
+ // src/lib/output.ts
37
+ import fs from "fs";
38
+ import chalk from "chalk";
39
+ var globalOptions = { pretty: false, verbose: false };
40
+ var globalUser = { email: void 0, userId: void 0 };
41
+ function setGlobalOptions(opts) {
42
+ globalOptions = opts;
43
+ }
44
+ function setGlobalUser(user) {
45
+ globalUser = user;
46
+ }
47
+ function buildMeta(service, action, startTime) {
48
+ return {
49
+ service,
50
+ action,
51
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
52
+ duration_ms: Date.now() - startTime,
53
+ user: globalUser.email ?? globalUser.userId ? globalUser : void 0
54
+ };
55
+ }
56
+ function success(data, service, action, startTime) {
57
+ const envelope = {
58
+ ok: true,
59
+ data,
60
+ meta: buildMeta(service, action, startTime)
61
+ };
62
+ process.stdout.write(
63
+ (globalOptions.pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope)) + "\n"
64
+ );
65
+ }
66
+ function fail(err, service, action, startTime) {
67
+ const errorDetail = {
68
+ status: err instanceof PncliError ? err.status : 1,
69
+ message: err instanceof Error ? err.message : String(err),
70
+ url: err instanceof PncliError ? err.url ?? null : null
71
+ };
72
+ const envelope = {
73
+ ok: false,
74
+ error: errorDetail,
75
+ meta: buildMeta(service, action, startTime)
76
+ };
77
+ const msg = globalOptions.pretty ? chalk.red("\u2717 Error: ") + errorDetail.message : null;
78
+ if (msg) process.stderr.write(msg + "\n");
79
+ const output = (globalOptions.pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope)) + "\n";
80
+ const exitCode = err instanceof PncliError ? exitCodeFromStatus(err.status) : ExitCode.GENERAL_ERROR;
81
+ try {
82
+ fs.writeSync(process.stdout.fd, output);
83
+ } catch (writeErr) {
84
+ if (writeErr.code !== "EPIPE") throw writeErr;
85
+ }
86
+ process.exitCode = exitCode;
87
+ throw new PncliError(errorDetail.message, errorDetail.status);
88
+ }
89
+ function log(message) {
90
+ if (globalOptions.verbose) {
91
+ process.stderr.write(
92
+ (globalOptions.pretty ? chalk.gray("\u25B8 ") : "") + message + "\n"
93
+ );
94
+ }
95
+ }
96
+ function warn(message) {
97
+ process.stderr.write(
98
+ (globalOptions.pretty ? chalk.yellow("\u26A0 ") : "") + message + "\n"
99
+ );
100
+ }
101
+
102
+ // src/lib/adoFetch.ts
103
+ async function buildAdoFetcher(config) {
104
+ const { pat, baseUrl } = config.ado;
105
+ if (!baseUrl) {
106
+ throw new PncliError("Azure DevOps baseUrl not configured. Run: pncli config init", 1);
107
+ }
108
+ if (!pat) {
109
+ throw new PncliError(
110
+ "Azure DevOps PAT not configured. Set a PAT via pncli config init or PNCLI_ADO_PAT env var.",
111
+ 1
112
+ );
113
+ }
114
+ const encoded = Buffer.from(":" + pat).toString("base64");
115
+ const authHeader = `Basic ${encoded}`;
116
+ return (url, init) => fetch(url, {
117
+ ...init,
118
+ headers: {
119
+ ...init?.headers,
120
+ "Authorization": authHeader,
121
+ "Content-Type": "application/json",
122
+ "Accept": "application/json"
123
+ }
124
+ });
125
+ }
126
+
127
+ // src/lib/http.ts
128
+ function buildUrl(base, path, params) {
129
+ const url = new URL(path, base.endsWith("/") ? base : base + "/");
130
+ if (params) {
131
+ for (const [key, val] of Object.entries(params)) {
132
+ if (val !== void 0) {
133
+ url.searchParams.set(key, String(val));
134
+ }
135
+ }
136
+ }
137
+ return url.toString();
138
+ }
139
+ async function fetchWithTimeout(url, init, timeoutMs, fetcher = fetch) {
140
+ const controller = new AbortController();
141
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
142
+ try {
143
+ return await fetcher(url, { ...init, signal: controller.signal });
144
+ } finally {
145
+ clearTimeout(timer);
146
+ }
147
+ }
148
+ async function request(url, init, timeoutMs, fetcher = fetch) {
149
+ let lastError;
150
+ for (let attempt = 0; attempt < 3; attempt++) {
151
+ let response;
152
+ try {
153
+ response = await fetchWithTimeout(url, init, timeoutMs, fetcher);
154
+ } catch (err) {
155
+ throw new PncliError(
156
+ `Request failed: ${err instanceof Error ? err.message : String(err)}`,
157
+ 0,
158
+ url
159
+ );
160
+ }
161
+ if (response.status === 429) {
162
+ const retryAfter = response.headers.get("Retry-After");
163
+ const waitMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : (attempt + 1) * 1e3;
164
+ log(`Rate limited. Retrying after ${waitMs}ms...`);
165
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
166
+ lastError = new PncliError("Rate limited", 429, url);
167
+ continue;
168
+ }
169
+ if (!response.ok) {
170
+ let message = `HTTP ${response.status} ${response.statusText}`;
171
+ try {
172
+ const body = await response.text();
173
+ const parsed = JSON.parse(body);
174
+ const parts = [];
175
+ if (Array.isArray(parsed.errorMessages)) {
176
+ parts.push(...parsed.errorMessages.filter(Boolean));
177
+ }
178
+ if (parsed.errors && typeof parsed.errors === "object" && !Array.isArray(parsed.errors)) {
179
+ for (const [field, msg] of Object.entries(parsed.errors)) {
180
+ parts.push(`${field}: ${msg}`);
181
+ }
182
+ }
183
+ if (Array.isArray(parsed.errors)) {
184
+ for (const e of parsed.errors) {
185
+ if (e?.message) parts.push(e.message);
186
+ else if (e?.msg) parts.push(e.msg);
187
+ }
188
+ }
189
+ if (parts.length === 0 && parsed.message) {
190
+ parts.push(String(parsed.message));
191
+ }
192
+ if (parts.length > 0) message = parts.join("; ");
193
+ } catch {
194
+ }
195
+ throw new PncliError(message, response.status, url);
196
+ }
197
+ if (response.status === 204) {
198
+ return void 0;
199
+ }
200
+ const text = await response.text();
201
+ if (!text) return void 0;
202
+ return JSON.parse(text);
203
+ }
204
+ throw lastError ?? new PncliError("Request failed after retries", 1, url);
205
+ }
206
+ var HttpClient = class {
207
+ config;
208
+ dryRun;
209
+ adoFetcher = null;
210
+ constructor(config, dryRun = false) {
211
+ this.config = config;
212
+ this.dryRun = dryRun;
213
+ }
214
+ jiraHeaders() {
215
+ const { apiToken } = this.config.jira;
216
+ if (!apiToken) throw new PncliError("Jira credentials not configured. Run: pncli config init");
217
+ return {
218
+ "Authorization": `Bearer ${apiToken}`,
219
+ "Content-Type": "application/json",
220
+ "Accept": "application/json",
221
+ "Connection": "close"
222
+ };
223
+ }
224
+ bitbucketHeaders() {
225
+ const { pat } = this.config.bitbucket;
226
+ if (!pat) throw new PncliError("Bitbucket credentials not configured. Run: pncli config init");
227
+ return {
228
+ "Authorization": `Bearer ${pat}`,
229
+ "Content-Type": "application/json",
230
+ "Accept": "application/json",
231
+ "Connection": "close"
232
+ };
233
+ }
234
+ async jira(path, opts = {}) {
235
+ const baseUrl = this.config.jira.baseUrl;
236
+ if (!baseUrl) throw new PncliError("Jira baseUrl not configured. Run: pncli config init");
237
+ const url = buildUrl(baseUrl, path, opts.params);
238
+ const headers = this.jiraHeaders();
239
+ const init = {
240
+ method: opts.method ?? "GET",
241
+ headers,
242
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
243
+ };
244
+ if (this.dryRun) {
245
+ const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
246
+ const msg = `DRY RUN: ${init.method} ${url}
247
+ Headers: ${JSON.stringify(safeHeaders, null, 2)}
248
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
249
+ ` : "");
250
+ fs2.writeSync(process.stderr.fd, msg);
251
+ process.exitCode = ExitCode.SUCCESS;
252
+ throw new PncliError("dry-run", 0);
253
+ }
254
+ return request(url, init, opts.timeoutMs ?? 3e4);
255
+ }
256
+ async bitbucket(path, opts = {}) {
257
+ const baseUrl = this.config.bitbucket.baseUrl;
258
+ if (!baseUrl) throw new PncliError("Bitbucket baseUrl not configured. Run: pncli config init");
259
+ const url = buildUrl(baseUrl, path, opts.params);
260
+ const headers = this.bitbucketHeaders();
261
+ const init = {
262
+ method: opts.method ?? "GET",
263
+ headers,
264
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
265
+ };
266
+ if (this.dryRun) {
267
+ const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
268
+ const msg = `DRY RUN: ${init.method} ${url}
269
+ Headers: ${JSON.stringify(safeHeaders, null, 2)}
270
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
271
+ ` : "");
272
+ fs2.writeSync(process.stderr.fd, msg);
273
+ process.exitCode = ExitCode.SUCCESS;
274
+ throw new PncliError("dry-run", 0);
275
+ }
276
+ return request(url, init, opts.timeoutMs ?? 3e4);
277
+ }
278
+ confluenceHeaders() {
279
+ const { apiToken } = this.config.confluence;
280
+ if (!apiToken) throw new PncliError("Confluence credentials not configured. Run: pncli config init");
281
+ return {
282
+ "Authorization": `Bearer ${apiToken}`,
283
+ "Content-Type": "application/json",
284
+ "Accept": "application/json",
285
+ "Connection": "close"
286
+ };
287
+ }
288
+ async confluence(path, opts = {}) {
289
+ const baseUrl = this.config.confluence.baseUrl;
290
+ if (!baseUrl) throw new PncliError("Confluence baseUrl not configured. Run: pncli config init");
291
+ const url = buildUrl(baseUrl, path, opts.params);
292
+ const headers = this.confluenceHeaders();
293
+ const init = {
294
+ method: opts.method ?? "GET",
295
+ headers,
296
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
297
+ };
298
+ if (this.dryRun) {
299
+ const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
300
+ const msg = `DRY RUN: ${init.method} ${url}
301
+ Headers: ${JSON.stringify(safeHeaders, null, 2)}
302
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
303
+ ` : "");
304
+ fs2.writeSync(process.stderr.fd, msg);
305
+ process.exitCode = ExitCode.SUCCESS;
306
+ throw new PncliError("dry-run", 0);
307
+ }
308
+ return request(url, init, opts.timeoutMs ?? 3e4);
309
+ }
310
+ sdeHeaders() {
311
+ const { token } = this.config.sde;
312
+ if (!token) throw new PncliError("SDElements credentials not configured. Run: pncli config init");
313
+ return {
314
+ "Authorization": `Token ${token}`,
315
+ "Content-Type": "application/json",
316
+ "Accept": "application/json",
317
+ "Connection": "close"
318
+ };
319
+ }
320
+ async sde(path, opts = {}) {
321
+ const baseUrl = this.config.sde.baseUrl;
322
+ if (!baseUrl) throw new PncliError("SDElements baseUrl not configured. Run: pncli config init");
323
+ const url = buildUrl(baseUrl, path, opts.params);
324
+ const headers = this.sdeHeaders();
325
+ const init = {
326
+ method: opts.method ?? "GET",
327
+ headers,
328
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
329
+ };
330
+ if (this.dryRun) {
331
+ const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
332
+ const msg = `DRY RUN: ${init.method} ${url}
333
+ Headers: ${JSON.stringify(safeHeaders, null, 2)}
334
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
335
+ ` : "");
336
+ fs2.writeSync(process.stderr.fd, msg);
337
+ process.exitCode = ExitCode.SUCCESS;
338
+ throw new PncliError("dry-run", 0);
339
+ }
340
+ return request(url, init, opts.timeoutMs ?? 3e4);
341
+ }
342
+ async sdePaginate(fetchPage) {
343
+ const results = [];
344
+ let page = 1;
345
+ const pageSize = 100;
346
+ while (true) {
347
+ const response = await fetchPage(page, pageSize);
348
+ results.push(...response.results);
349
+ if (results.length >= response.count || response.results.length === 0) break;
350
+ page++;
351
+ }
352
+ return results;
353
+ }
354
+ async getAdoFetcher() {
355
+ if (!this.adoFetcher) {
356
+ this.adoFetcher = await buildAdoFetcher(this.config);
357
+ }
358
+ return this.adoFetcher;
359
+ }
360
+ async ado(path, opts = {}) {
361
+ const baseUrl = this.config.ado.baseUrl;
362
+ if (!baseUrl) throw new PncliError("Azure DevOps baseUrl not configured. Run: pncli config init");
363
+ const url = buildUrl(baseUrl, path, opts.params);
364
+ if (this.dryRun) {
365
+ const msg = `DRY RUN: ${opts.method ?? "GET"} ${url}
366
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
367
+ ` : "");
368
+ fs2.writeSync(process.stderr.fd, msg);
369
+ process.exitCode = ExitCode.SUCCESS;
370
+ throw new PncliError("dry-run", 0);
371
+ }
372
+ const fetcher = await this.getAdoFetcher();
373
+ const defaultHeaders = {
374
+ "Accept": "application/json",
375
+ "Content-Type": "application/json",
376
+ ...opts.headers
377
+ };
378
+ const init = {
379
+ method: opts.method ?? "GET",
380
+ headers: defaultHeaders,
381
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
382
+ };
383
+ return request(url, init, opts.timeoutMs ?? 3e4, fetcher);
384
+ }
385
+ async adoText(path, opts = {}) {
386
+ const baseUrl = this.config.ado.baseUrl;
387
+ if (!baseUrl) throw new PncliError("Azure DevOps baseUrl not configured. Run: pncli config init");
388
+ const url = buildUrl(baseUrl, path, opts.params);
389
+ if (this.dryRun) {
390
+ fs2.writeSync(process.stderr.fd, `DRY RUN: ${opts.method ?? "GET"} ${url}
391
+ `);
392
+ process.exitCode = ExitCode.SUCCESS;
393
+ throw new PncliError("dry-run", 0);
394
+ }
395
+ const fetcher = await this.getAdoFetcher();
396
+ const response = await fetchWithTimeout(url, {
397
+ method: opts.method ?? "GET",
398
+ headers: { "Accept": "text/plain", ...opts.headers }
399
+ }, opts.timeoutMs ?? 3e4, fetcher);
400
+ if (!response.ok) {
401
+ let message = `HTTP ${response.status} ${response.statusText}`;
402
+ try {
403
+ const parsed = JSON.parse(await response.text());
404
+ if (parsed.message) message = String(parsed.message);
405
+ } catch {
406
+ }
407
+ throw new PncliError(message, response.status, url);
408
+ }
409
+ return response.text();
410
+ }
411
+ async adoRaw(path, opts = {}) {
412
+ const baseUrl = this.config.ado.baseUrl;
413
+ if (!baseUrl) throw new PncliError("Azure DevOps baseUrl not configured. Run: pncli config init");
414
+ const url = buildUrl(baseUrl, path, opts.params);
415
+ if (this.dryRun) {
416
+ fs2.writeSync(process.stderr.fd, `DRY RUN: ${opts.method ?? "GET"} ${url}
417
+ `);
418
+ process.exitCode = ExitCode.SUCCESS;
419
+ throw new PncliError("dry-run", 0);
420
+ }
421
+ const fetcher = await this.getAdoFetcher();
422
+ const controller = new AbortController();
423
+ const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 3e4);
424
+ let response;
425
+ try {
426
+ response = await fetcher(url, {
427
+ method: opts.method ?? "GET",
428
+ headers: { "Accept": "application/json", "Content-Type": "application/json", ...opts.headers },
429
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0,
430
+ signal: controller.signal
431
+ });
432
+ } finally {
433
+ clearTimeout(timer);
434
+ }
435
+ if (!response.ok) {
436
+ let message = `HTTP ${response.status} ${response.statusText}`;
437
+ try {
438
+ const parsed = JSON.parse(await response.text());
439
+ if (parsed.message) message = String(parsed.message);
440
+ } catch {
441
+ }
442
+ throw new PncliError(message, response.status, url);
443
+ }
444
+ const text = await response.text();
445
+ const data = text ? JSON.parse(text) : void 0;
446
+ return { data, headers: response.headers };
447
+ }
448
+ async adoPaginate(fetchPage) {
449
+ const results = [];
450
+ let token;
451
+ while (true) {
452
+ const { data, headers } = await fetchPage(token);
453
+ results.push(...data.value ?? []);
454
+ const next = headers.get("x-ms-continuationtoken");
455
+ if (!next) break;
456
+ token = next;
457
+ }
458
+ return results;
459
+ }
460
+ sonarHeaders() {
461
+ const { token } = this.config.sonar;
462
+ if (!token) throw new PncliError("SonarQube credentials not configured. Run: pncli config init");
463
+ return {
464
+ "Authorization": `Bearer ${token}`,
465
+ "Content-Type": "application/json",
466
+ "Accept": "application/json",
467
+ "Connection": "close"
468
+ };
469
+ }
470
+ async sonar(path, opts = {}) {
471
+ const baseUrl = this.config.sonar.baseUrl;
472
+ if (!baseUrl) throw new PncliError("SonarQube baseUrl not configured. Run: pncli config init");
473
+ const url = buildUrl(baseUrl, path, opts.params);
474
+ const headers = this.sonarHeaders();
475
+ const init = {
476
+ method: opts.method ?? "GET",
477
+ headers,
478
+ body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
479
+ };
480
+ if (this.dryRun) {
481
+ const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
482
+ const msg = `DRY RUN: ${init.method} ${url}
483
+ Headers: ${JSON.stringify(safeHeaders, null, 2)}
484
+ ` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
485
+ ` : "");
486
+ fs2.writeSync(process.stderr.fd, msg);
487
+ process.exitCode = ExitCode.SUCCESS;
488
+ throw new PncliError("dry-run", 0);
489
+ }
490
+ return request(url, init, opts.timeoutMs ?? 3e4);
491
+ }
492
+ async sonarPaginate(fetchPage) {
493
+ const results = [];
494
+ let page = 1;
495
+ const pageSize = 500;
496
+ while (true) {
497
+ const response = await fetchPage(page, pageSize);
498
+ results.push(...response.items);
499
+ if (results.length >= response.total || response.items.length === 0) break;
500
+ page++;
501
+ }
502
+ return results;
503
+ }
504
+ async confluencePaginate(fetchPage) {
505
+ const results = [];
506
+ let start = 0;
507
+ const limit = 25;
508
+ while (true) {
509
+ const page = await fetchPage(start, limit);
510
+ results.push(...page.results);
511
+ if (!page._links.next) break;
512
+ start += page.size;
513
+ }
514
+ return results;
515
+ }
516
+ async paginate(fetchPage) {
517
+ const results = [];
518
+ let start = 0;
519
+ const limit = 100;
520
+ while (true) {
521
+ const page = await fetchPage(start, limit);
522
+ results.push(...page.values);
523
+ if (page.isLastPage) break;
524
+ start = page.nextPageStart ?? start + limit;
525
+ }
526
+ return results;
527
+ }
528
+ async jiraPaginate(fetchPage) {
529
+ const results = [];
530
+ let startAt = 0;
531
+ const maxResults = 100;
532
+ while (true) {
533
+ const page = await fetchPage(startAt, maxResults);
534
+ const items = page.issues ?? page.values ?? [];
535
+ results.push(...items);
536
+ startAt += items.length;
537
+ if (startAt >= page.total || items.length === 0) break;
538
+ }
539
+ return results;
540
+ }
541
+ };
542
+ function createHttpClient(config, dryRun = false) {
543
+ return new HttpClient(config, dryRun);
544
+ }
545
+
546
+ export {
547
+ PncliError,
548
+ ExitCode,
549
+ setGlobalOptions,
550
+ setGlobalUser,
551
+ success,
552
+ fail,
553
+ log,
554
+ warn,
555
+ HttpClient,
556
+ createHttpClient
557
+ };
558
+ //# sourceMappingURL=chunk-HWXXNMGE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/http.ts","../src/lib/errors.ts","../src/lib/exitCodes.ts","../src/lib/output.ts","../src/lib/adoFetch.ts"],"sourcesContent":["import fs from 'fs';\nimport type { ResolvedConfig } from '../types/config.js';\nimport { PncliError } from './errors.js';\nimport { ExitCode } from './exitCodes.js';\nimport { log } from './output.js';\nimport { buildAdoFetcher } from './adoFetch.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\nexport interface HttpRequestOptions {\n method?: HttpMethod;\n body?: unknown;\n params?: Record<string, string | number | boolean | undefined>;\n timeoutMs?: number;\n headers?: Record<string, string>;\n}\n\nexport interface HttpError {\n error: true;\n status: number;\n message: string;\n url: string;\n}\n\nfunction buildUrl(base: string, path: string, params?: Record<string, string | number | boolean | undefined>): string {\n const url = new URL(path, base.endsWith('/') ? base : base + '/');\n if (params) {\n for (const [key, val] of Object.entries(params)) {\n if (val !== undefined) {\n url.searchParams.set(key, String(val));\n }\n }\n }\n return url.toString();\n}\n\nasync function fetchWithTimeout(url: string, init: RequestInit, timeoutMs: number, fetcher: typeof fetch = fetch): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetcher(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function request<T>(\n url: string,\n init: RequestInit,\n timeoutMs: number,\n fetcher: typeof fetch = fetch\n): Promise<T> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n let response: Response;\n try {\n response = await fetchWithTimeout(url, init, timeoutMs, fetcher);\n } catch (err) {\n throw new PncliError(\n `Request failed: ${err instanceof Error ? err.message : String(err)}`,\n 0,\n url\n );\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n const waitMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : (attempt + 1) * 1000;\n log(`Rate limited. Retrying after ${waitMs}ms...`);\n await new Promise(resolve => setTimeout(resolve, waitMs));\n lastError = new PncliError('Rate limited', 429, url);\n continue;\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status} ${response.statusText}`;\n try {\n const body = await response.text();\n const parsed = JSON.parse(body);\n const parts: string[] = [];\n // Jira: errorMessages is string[]\n if (Array.isArray(parsed.errorMessages)) {\n parts.push(...(parsed.errorMessages as string[]).filter(Boolean));\n }\n // errors as object map (Jira: Record<string, string>)\n if (parsed.errors && typeof parsed.errors === 'object' && !Array.isArray(parsed.errors)) {\n for (const [field, msg] of Object.entries(parsed.errors as Record<string, string>)) {\n parts.push(`${field}: ${msg}`);\n }\n }\n // errors as array of objects with message or msg field (SonarQube uses msg)\n if (Array.isArray(parsed.errors)) {\n for (const e of parsed.errors as Array<{ message?: string; msg?: string }>) {\n if (e?.message) parts.push(e.message);\n else if (e?.msg) parts.push(e.msg);\n }\n }\n // Generic APIs: { message: \"...\" }\n if (parts.length === 0 && parsed.message) {\n parts.push(String(parsed.message));\n }\n if (parts.length > 0) message = parts.join('; ');\n } catch {\n // ignore parse errors\n }\n throw new PncliError(message, response.status, url);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const text = await response.text();\n if (!text) return undefined as T;\n return JSON.parse(text) as T;\n }\n\n throw lastError ?? new PncliError('Request failed after retries', 1, url);\n}\n\nexport class HttpClient {\n private config: ResolvedConfig;\n private dryRun: boolean;\n private adoFetcher: typeof fetch | null = null;\n\n constructor(config: ResolvedConfig, dryRun = false) {\n this.config = config;\n this.dryRun = dryRun;\n }\n\n private jiraHeaders(): Record<string, string> {\n const { apiToken } = this.config.jira;\n if (!apiToken) throw new PncliError('Jira credentials not configured. Run: pncli config init');\n return {\n 'Authorization': `Bearer ${apiToken}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'Connection': 'close'\n };\n }\n\n private bitbucketHeaders(): Record<string, string> {\n const { pat } = this.config.bitbucket;\n if (!pat) throw new PncliError('Bitbucket credentials not configured. Run: pncli config init');\n return {\n 'Authorization': `Bearer ${pat}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'Connection': 'close'\n };\n }\n\n async jira<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.jira.baseUrl;\n if (!baseUrl) throw new PncliError('Jira baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n const headers = this.jiraHeaders();\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n if (this.dryRun) {\n const safeHeaders = { ...headers, Authorization: '[REDACTED]' };\n const msg = `DRY RUN: ${init.method} ${url}\\nHeaders: ${JSON.stringify(safeHeaders, null, 2)}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n return request<T>(url, init, opts.timeoutMs ?? 30000);\n }\n\n async bitbucket<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.bitbucket.baseUrl;\n if (!baseUrl) throw new PncliError('Bitbucket baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n const headers = this.bitbucketHeaders();\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n if (this.dryRun) {\n const safeHeaders = { ...headers, Authorization: '[REDACTED]' };\n const msg = `DRY RUN: ${init.method} ${url}\\nHeaders: ${JSON.stringify(safeHeaders, null, 2)}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n return request<T>(url, init, opts.timeoutMs ?? 30000);\n }\n\n private confluenceHeaders(): Record<string, string> {\n const { apiToken } = this.config.confluence;\n if (!apiToken) throw new PncliError('Confluence credentials not configured. Run: pncli config init');\n return {\n 'Authorization': `Bearer ${apiToken}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'Connection': 'close'\n };\n }\n\n async confluence<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.confluence.baseUrl;\n if (!baseUrl) throw new PncliError('Confluence baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n const headers = this.confluenceHeaders();\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n if (this.dryRun) {\n const safeHeaders = { ...headers, Authorization: '[REDACTED]' };\n const msg = `DRY RUN: ${init.method} ${url}\\nHeaders: ${JSON.stringify(safeHeaders, null, 2)}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n return request<T>(url, init, opts.timeoutMs ?? 30000);\n }\n\n private sdeHeaders(): Record<string, string> {\n const { token } = this.config.sde;\n if (!token) throw new PncliError('SDElements credentials not configured. Run: pncli config init');\n return {\n 'Authorization': `Token ${token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'Connection': 'close'\n };\n }\n\n async sde<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.sde.baseUrl;\n if (!baseUrl) throw new PncliError('SDElements baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n const headers = this.sdeHeaders();\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n if (this.dryRun) {\n const safeHeaders = { ...headers, Authorization: '[REDACTED]' };\n const msg = `DRY RUN: ${init.method} ${url}\\nHeaders: ${JSON.stringify(safeHeaders, null, 2)}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n return request<T>(url, init, opts.timeoutMs ?? 30000);\n }\n\n async sdePaginate<T>(\n fetchPage: (page: number, pageSize: number) => Promise<{ count: number; results: T[] }>\n ): Promise<T[]> {\n const results: T[] = [];\n let page = 1;\n const pageSize = 100;\n\n while (true) {\n const response = await fetchPage(page, pageSize);\n results.push(...response.results);\n if (results.length >= response.count || response.results.length === 0) break;\n page++;\n }\n\n return results;\n }\n\n private async getAdoFetcher(): Promise<typeof fetch> {\n if (!this.adoFetcher) {\n this.adoFetcher = await buildAdoFetcher(this.config);\n }\n return this.adoFetcher;\n }\n\n async ado<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.ado.baseUrl;\n if (!baseUrl) throw new PncliError('Azure DevOps baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n\n if (this.dryRun) {\n const msg = `DRY RUN: ${opts.method ?? 'GET'} ${url}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n const fetcher = await this.getAdoFetcher();\n const defaultHeaders: Record<string, string> = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n ...opts.headers\n };\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers: defaultHeaders,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n return request<T>(url, init, opts.timeoutMs ?? 30000, fetcher);\n }\n\n async adoText(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<string> {\n const baseUrl = this.config.ado.baseUrl;\n if (!baseUrl) throw new PncliError('Azure DevOps baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n\n if (this.dryRun) {\n fs.writeSync(process.stderr.fd, `DRY RUN: ${opts.method ?? 'GET'} ${url}\\n`);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n const fetcher = await this.getAdoFetcher();\n const response = await fetchWithTimeout(url, {\n method: opts.method ?? 'GET',\n headers: { 'Accept': 'text/plain', ...opts.headers }\n }, opts.timeoutMs ?? 30000, fetcher);\n\n if (!response.ok) {\n let message = `HTTP ${response.status} ${response.statusText}`;\n try {\n const parsed = JSON.parse(await response.text());\n if (parsed.message) message = String(parsed.message);\n } catch { /* ignore */ }\n throw new PncliError(message, response.status, url);\n }\n\n return response.text();\n }\n\n async adoRaw(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<{ data: unknown; headers: Headers }> {\n const baseUrl = this.config.ado.baseUrl;\n if (!baseUrl) throw new PncliError('Azure DevOps baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n\n if (this.dryRun) {\n fs.writeSync(process.stderr.fd, `DRY RUN: ${opts.method ?? 'GET'} ${url}\\n`);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n const fetcher = await this.getAdoFetcher();\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 30000);\n let response: Response;\n try {\n response = await fetcher(url, {\n method: opts.method ?? 'GET',\n headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', ...opts.headers },\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n signal: controller.signal\n });\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n let message = `HTTP ${response.status} ${response.statusText}`;\n try {\n const parsed = JSON.parse(await response.text());\n if (parsed.message) message = String(parsed.message);\n } catch { /* ignore */ }\n throw new PncliError(message, response.status, url);\n }\n\n const text = await response.text();\n const data = text ? JSON.parse(text) : undefined;\n return { data, headers: response.headers };\n }\n\n async adoPaginate<T>(\n fetchPage: (continuationToken?: string) => Promise<{ data: { value: T[] }; headers: Headers }>\n ): Promise<T[]> {\n const results: T[] = [];\n let token: string | undefined;\n\n while (true) {\n const { data, headers } = await fetchPage(token);\n results.push(...(data.value ?? []));\n const next = headers.get('x-ms-continuationtoken');\n if (!next) break;\n token = next;\n }\n\n return results;\n }\n\n private sonarHeaders(): Record<string, string> {\n const { token } = this.config.sonar;\n if (!token) throw new PncliError('SonarQube credentials not configured. Run: pncli config init');\n return {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'Connection': 'close'\n };\n }\n\n async sonar<T>(\n path: string,\n opts: HttpRequestOptions = {}\n ): Promise<T> {\n const baseUrl = this.config.sonar.baseUrl;\n if (!baseUrl) throw new PncliError('SonarQube baseUrl not configured. Run: pncli config init');\n\n const url = buildUrl(baseUrl, path, opts.params);\n const headers = this.sonarHeaders();\n const init: RequestInit = {\n method: opts.method ?? 'GET',\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined\n };\n\n if (this.dryRun) {\n const safeHeaders = { ...headers, Authorization: '[REDACTED]' };\n const msg = `DRY RUN: ${init.method} ${url}\\nHeaders: ${JSON.stringify(safeHeaders, null, 2)}\\n`\n + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}\\n` : '');\n fs.writeSync(process.stderr.fd, msg);\n process.exitCode = ExitCode.SUCCESS;\n throw new PncliError('dry-run', 0);\n }\n\n return request<T>(url, init, opts.timeoutMs ?? 30000);\n }\n\n async sonarPaginate<T>(\n fetchPage: (page: number, pageSize: number) => Promise<{ total: number; p: number; ps: number; items: T[] }>\n ): Promise<T[]> {\n const results: T[] = [];\n let page = 1;\n const pageSize = 500;\n\n while (true) {\n const response = await fetchPage(page, pageSize);\n results.push(...response.items);\n if (results.length >= response.total || response.items.length === 0) break;\n page++;\n }\n\n return results;\n }\n\n async confluencePaginate<T>(\n fetchPage: (start: number, limit: number) => Promise<{ results: T[]; start: number; limit: number; size: number; _links: { next?: string } }>\n ): Promise<T[]> {\n const results: T[] = [];\n let start = 0;\n const limit = 25;\n\n while (true) {\n const page = await fetchPage(start, limit);\n results.push(...page.results);\n if (!page._links.next) break;\n start += page.size;\n }\n\n return results;\n }\n\n async paginate<T>(\n fetchPage: (start: number, limit: number) => Promise<{ values: T[]; isLastPage: boolean; nextPageStart?: number }>\n ): Promise<T[]> {\n const results: T[] = [];\n let start = 0;\n const limit = 100;\n\n while (true) {\n const page = await fetchPage(start, limit);\n results.push(...page.values);\n if (page.isLastPage) break;\n start = page.nextPageStart ?? start + limit;\n }\n\n return results;\n }\n\n async jiraPaginate<T>(\n fetchPage: (startAt: number, maxResults: number) => Promise<{ issues?: T[]; values?: T[]; total: number; startAt: number; maxResults: number }>\n ): Promise<T[]> {\n const results: T[] = [];\n let startAt = 0;\n const maxResults = 100;\n\n while (true) {\n const page = await fetchPage(startAt, maxResults);\n const items = (page.issues ?? page.values ?? []) as T[];\n results.push(...items);\n startAt += items.length;\n if (startAt >= page.total || items.length === 0) break;\n }\n\n return results;\n }\n}\n\nexport function createHttpClient(config: ResolvedConfig, dryRun = false): HttpClient {\n return new HttpClient(config, dryRun);\n}\n","export class PncliError extends Error {\n status: number;\n url?: string;\n\n constructor(message: string, status: number = 1, url?: string) {\n super(message);\n this.name = 'PncliError';\n this.status = status;\n this.url = url;\n }\n}\n","export const ExitCode = {\n SUCCESS: 0,\n GENERAL_ERROR: 1,\n USAGE_ERROR: 2,\n NETWORK_ERROR: 69, // EX_UNAVAILABLE from sysexits.h\n AUTH_ERROR: 77, // EX_NOPERM from sysexits.h\n CONFIG_ERROR: 78, // EX_CONFIG from sysexits.h\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n\nexport function exitCodeFromStatus(httpStatus: number): ExitCode {\n if (httpStatus === 401 || httpStatus === 403) return ExitCode.AUTH_ERROR;\n if (httpStatus === 0) return ExitCode.NETWORK_ERROR;\n return ExitCode.GENERAL_ERROR;\n}\n","import fs from 'fs';\nimport chalk from 'chalk';\nimport type { Meta, SuccessEnvelope, ErrorEnvelope, ErrorDetail } from '../types/common.js';\nimport { PncliError } from './errors.js';\nimport { ExitCode, exitCodeFromStatus } from './exitCodes.js';\n\nlet globalOptions = { pretty: false, verbose: false };\nlet globalUser: { email: string | undefined; userId: string | undefined } = { email: undefined, userId: undefined };\n\nexport function setGlobalOptions(opts: { pretty: boolean; verbose: boolean }): void {\n globalOptions = opts;\n}\n\nexport function setGlobalUser(user: { email: string | undefined; userId: string | undefined }): void {\n globalUser = user;\n}\n\nfunction buildMeta(service: string, action: string, startTime: number): Meta {\n return {\n service,\n action,\n timestamp: new Date().toISOString(),\n duration_ms: Date.now() - startTime,\n user: (globalUser.email ?? globalUser.userId) ? globalUser : undefined\n };\n}\n\nexport function success<T>(data: T, service: string, action: string, startTime: number): void {\n const envelope: SuccessEnvelope<T> = {\n ok: true,\n data,\n meta: buildMeta(service, action, startTime)\n };\n process.stdout.write(\n (globalOptions.pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope)) + '\\n'\n );\n}\n\nexport function fail(\n err: unknown,\n service: string,\n action: string,\n startTime: number\n): never {\n const errorDetail: ErrorDetail = {\n status: err instanceof PncliError ? err.status : 1,\n message: err instanceof Error ? err.message : String(err),\n url: err instanceof PncliError ? (err.url ?? null) : null\n };\n\n const envelope: ErrorEnvelope = {\n ok: false,\n error: errorDetail,\n meta: buildMeta(service, action, startTime)\n };\n\n const msg = globalOptions.pretty\n ? chalk.red('✗ Error: ') + errorDetail.message\n : null;\n\n if (msg) process.stderr.write(msg + '\\n');\n\n const output = (globalOptions.pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope)) + '\\n';\n const exitCode = err instanceof PncliError ? exitCodeFromStatus(err.status) : ExitCode.GENERAL_ERROR;\n try {\n fs.writeSync(process.stdout.fd, output);\n } catch (writeErr) {\n if ((writeErr as NodeJS.ErrnoException).code !== 'EPIPE') throw writeErr;\n }\n process.exitCode = exitCode;\n throw new PncliError(errorDetail.message, errorDetail.status);\n}\n\nexport function log(message: string): void {\n if (globalOptions.verbose) {\n process.stderr.write(\n (globalOptions.pretty ? chalk.gray('▸ ') : '') + message + '\\n'\n );\n }\n}\n\nexport function warn(message: string): void {\n process.stderr.write(\n (globalOptions.pretty ? chalk.yellow('⚠ ') : '') + message + '\\n'\n );\n}\n","import type { ResolvedConfig } from '../types/config.js';\nimport { PncliError } from './errors.js';\n\n/**\n * Returns a fetch-compatible function for Azure DevOps Server requests,\n * with Basic auth (PAT) injected into every call.\n */\nexport async function buildAdoFetcher(\n config: ResolvedConfig\n): Promise<typeof fetch> {\n const { pat, baseUrl } = config.ado;\n\n if (!baseUrl) {\n throw new PncliError('Azure DevOps baseUrl not configured. Run: pncli config init', 1);\n }\n\n if (!pat) {\n throw new PncliError(\n 'Azure DevOps PAT not configured. Set a PAT via pncli config init or PNCLI_ADO_PAT env var.',\n 1\n );\n }\n\n const encoded = Buffer.from(':' + pat).toString('base64');\n const authHeader = `Basic ${encoded}`;\n return (url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) =>\n fetch(url, {\n ...init,\n headers: {\n ...(init?.headers as Record<string, string> | undefined),\n 'Authorization': authHeader,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n }\n });\n}\n"],"mappings":"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","names":["fs","fs"]}