@kolatts/pncli 5.3.0 → 5.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.
@@ -1,466 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- PncliError
4
- } from "./chunk-HRNOAQDN.js";
5
-
6
- // src/lib/config.ts
7
- import fs from "fs";
8
- import os from "os";
9
- import path from "path";
10
- import { execSync } from "child_process";
11
-
12
- // src/types/jira.ts
13
- var CUSTOM_FIELD_TYPES = [
14
- "string",
15
- "number",
16
- "date",
17
- "datetime",
18
- "select",
19
- "multi-select",
20
- "option-id",
21
- "cascading-select",
22
- "user",
23
- "labels",
24
- "url",
25
- "textarea"
26
- ];
27
-
28
- // src/lib/validate-custom-fields.ts
29
- var EXAMPLE = '[{"id":"customfield_10032","name":"Epic Link","type":"select"}]';
30
- function assertValidCustomFields(fields, opts = {}) {
31
- const where = opts.source ? `in ${opts.source}` : "config";
32
- const fix = (value) => `Fix with: pncli config set jira.customFields '${value}'${opts.repo ? " --repo" : ""}`;
33
- if (!Array.isArray(fields)) {
34
- throw new PncliError(
35
- `Invalid jira.customFields ${where}: expected an array, got ${JSON.stringify(fields)}. ${fix("[]")}`,
36
- 1
37
- );
38
- }
39
- for (const f of fields) {
40
- const entry = f;
41
- if (typeof entry !== "object" || entry === null || typeof entry.id !== "string" || typeof entry.name !== "string") {
42
- throw new PncliError(
43
- `Invalid jira.customFields ${where}: each entry must be an object with string "id" and "name" fields. Got: ${JSON.stringify(f)}. ${fix(EXAMPLE)}`,
44
- 1
45
- );
46
- }
47
- if (entry.type !== void 0 && (typeof entry.type !== "string" || !CUSTOM_FIELD_TYPES.includes(entry.type))) {
48
- throw new PncliError(
49
- `Invalid jira.customFields ${where}: entry "${entry.name}" has unknown "type" ${JSON.stringify(entry.type)}; expected one of ${CUSTOM_FIELD_TYPES.join(", ")}. ${fix(EXAMPLE)}`,
50
- 1
51
- );
52
- }
53
- }
54
- }
55
-
56
- // src/lib/config.ts
57
- var ENV_KEYS = {
58
- EMAIL: "PNCLI_EMAIL",
59
- USERID: "PNCLI_USERID",
60
- JIRA_BASE_URL: "PNCLI_JIRA_BASE_URL",
61
- JIRA_API_TOKEN: "PNCLI_JIRA_API_TOKEN",
62
- BITBUCKET_BASE_URL: "PNCLI_BITBUCKET_BASE_URL",
63
- BITBUCKET_PAT: "PNCLI_BITBUCKET_PAT",
64
- GITHUB_BASE_URL: "PNCLI_GITHUB_BASE_URL",
65
- GITHUB_TOKEN: "PNCLI_GITHUB_TOKEN",
66
- // Well-known vars CI platforms provide without any pncli-specific setup.
67
- GITHUB_TOKEN_FALLBACK: "GITHUB_TOKEN",
68
- GITHUB_API_URL_FALLBACK: "GITHUB_API_URL",
69
- CONFLUENCE_BASE_URL: "PNCLI_CONFLUENCE_BASE_URL",
70
- CONFLUENCE_API_TOKEN: "PNCLI_CONFLUENCE_API_TOKEN",
71
- ARTIFACTORY_BASE_URL: "PNCLI_ARTIFACTORY_BASE_URL",
72
- ARTIFACTORY_TOKEN: "PNCLI_ARTIFACTORY_TOKEN",
73
- ARTIFACTORY_REPO_NPM: "PNCLI_ARTIFACTORY_REPO_NPM",
74
- ARTIFACTORY_REPO_NUGET: "PNCLI_ARTIFACTORY_REPO_NUGET",
75
- ARTIFACTORY_REPO_MAVEN: "PNCLI_ARTIFACTORY_REPO_MAVEN",
76
- SONAR_BASE_URL: "PNCLI_SONAR_BASE_URL",
77
- SONAR_TOKEN: "PNCLI_SONAR_TOKEN",
78
- // SonarSource's own scanner CLI standard var name — see the comment above GITHUB_TOKEN_FALLBACK.
79
- SONAR_TOKEN_FALLBACK: "SONAR_TOKEN",
80
- SDE_CONNECTION: "PNCLI_SDE_CONNECTION",
81
- ADO_BASE_URL: "PNCLI_ADO_BASE_URL",
82
- ADO_PAT: "PNCLI_ADO_PAT",
83
- // Azure Pipelines' conventional name for $(System.AccessToken) — see the comment above GITHUB_TOKEN_FALLBACK.
84
- ADO_PAT_FALLBACK: "SYSTEM_ACCESSTOKEN",
85
- JENKINS_BASE_URL: "PNCLI_JENKINS_BASE_URL",
86
- JENKINS_USERNAME: "PNCLI_JENKINS_USERNAME",
87
- JENKINS_API_TOKEN: "PNCLI_JENKINS_API_TOKEN",
88
- CHECKMARX_BASE_URL: "PNCLI_CHECKMARX_BASE_URL",
89
- CHECKMARX_TENANT_NAME: "PNCLI_CHECKMARX_TENANT_NAME",
90
- CHECKMARX_API_KEY: "PNCLI_CHECKMARX_API_KEY",
91
- CHECKMARX_CLIENT_ID: "PNCLI_CHECKMARX_CLIENT_ID",
92
- CHECKMARX_CLIENT_SECRET: "PNCLI_CHECKMARX_CLIENT_SECRET",
93
- CONTRAST_BASE_URL: "PNCLI_CONTRAST_BASE_URL",
94
- CONTRAST_ORG_UUID: "PNCLI_CONTRAST_ORG_UUID",
95
- CONTRAST_API_KEY: "PNCLI_CONTRAST_API_KEY",
96
- CONTRAST_SERVICE_KEY: "PNCLI_CONTRAST_SERVICE_KEY",
97
- CONTRAST_USERNAME: "PNCLI_CONTRAST_USERNAME",
98
- SONATYPEIQ_BASE_URL: "PNCLI_SONATYPEIQ_BASE_URL",
99
- SONATYPEIQ_USER_CODE: "PNCLI_SONATYPEIQ_USER_CODE",
100
- SONATYPEIQ_PASSCODE: "PNCLI_SONATYPEIQ_PASSCODE",
101
- OPENSHIFT_BASE_URL: "PNCLI_OPENSHIFT_BASE_URL",
102
- OPENSHIFT_TOKEN: "PNCLI_OPENSHIFT_TOKEN",
103
- DYNATRACE_BASE_URL: "PNCLI_DYNATRACE_BASE_URL",
104
- DYNATRACE_API_TOKEN: "PNCLI_DYNATRACE_API_TOKEN",
105
- DYNATRACE_PLATFORM_URL: "PNCLI_DYNATRACE_PLATFORM_URL",
106
- DYNATRACE_PLATFORM_TOKEN: "PNCLI_DYNATRACE_PLATFORM_TOKEN",
107
- LOGSCALE_BASE_URL: "PNCLI_LOGSCALE_BASE_URL",
108
- LOGSCALE_TOKEN: "PNCLI_LOGSCALE_TOKEN",
109
- SPLITIO_BASE_URL: "PNCLI_SPLITIO_BASE_URL",
110
- SPLITIO_ADMIN_API_KEY: "PNCLI_SPLITIO_ADMIN_API_KEY",
111
- FIGMA_BASE_URL: "PNCLI_FIGMA_BASE_URL",
112
- FIGMA_TOKEN: "PNCLI_FIGMA_TOKEN",
113
- ALATION_BASE_URL: "PNCLI_ALATION_BASE_URL",
114
- ALATION_REFRESH_TOKEN: "PNCLI_ALATION_REFRESH_TOKEN",
115
- ALATION_USER_ID: "PNCLI_ALATION_USER_ID",
116
- CONFIG_PATH: "PNCLI_CONFIG_PATH"
117
- };
118
- function getGlobalConfigPath(overridePath) {
119
- if (overridePath) return overridePath;
120
- const envPath = process.env[ENV_KEYS.CONFIG_PATH];
121
- if (envPath) return envPath;
122
- return path.join(os.homedir(), ".pncli", "config.json");
123
- }
124
- function loadJsonFile(filePath) {
125
- try {
126
- const content = fs.readFileSync(filePath, "utf8");
127
- return JSON.parse(content);
128
- } catch {
129
- return null;
130
- }
131
- }
132
- function getRepoRoot() {
133
- try {
134
- return execSync("git rev-parse --show-toplevel", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
135
- } catch {
136
- return null;
137
- }
138
- }
139
- function parseSdeConnection(connection) {
140
- const idx = connection.indexOf("@");
141
- if (idx <= 0) return null;
142
- const token = connection.slice(0, idx);
143
- const host = connection.slice(idx + 1);
144
- const baseUrl = /^https?:\/\//i.test(host) ? host : `https://${host}`;
145
- return { token, baseUrl };
146
- }
147
- function mergeCustomFields(global, repo) {
148
- const map = /* @__PURE__ */ new Map();
149
- if (global != null) {
150
- assertValidCustomFields(global, { source: "global config" });
151
- for (const f of global) map.set(f.id, f);
152
- }
153
- if (repo != null) {
154
- assertValidCustomFields(repo, { source: "repo config (.pncli.json)", repo: true });
155
- for (const f of repo) map.set(f.id, f);
156
- }
157
- return Array.from(map.values());
158
- }
159
- function mergeDefaults(global, repo) {
160
- return {
161
- jira: { ...global?.jira, ...repo?.jira },
162
- bitbucket: { ...global?.bitbucket, ...repo?.bitbucket },
163
- github: { ...global?.github, ...repo?.github },
164
- sonar: { ...global?.sonar, ...repo?.sonar },
165
- sde: { ...global?.sde, ...repo?.sde },
166
- ado: { ...global?.ado, ...repo?.ado },
167
- jenkins: { ...global?.jenkins, ...repo?.jenkins }
168
- };
169
- }
170
- function loadConfig(opts = {}) {
171
- const globalConfigPath = getGlobalConfigPath(opts.configPath);
172
- const globalConfig = loadJsonFile(globalConfigPath) ?? {};
173
- const repoRoot = getRepoRoot();
174
- let repoConfig = {};
175
- if (repoRoot) {
176
- repoConfig = loadJsonFile(path.join(repoRoot, ".pncli.json")) ?? {};
177
- }
178
- const mergedDefaults = mergeDefaults(globalConfig.defaults, repoConfig.defaults);
179
- return {
180
- user: {
181
- email: process.env[ENV_KEYS.EMAIL] ?? globalConfig.user?.email,
182
- userId: process.env[ENV_KEYS.USERID] ?? globalConfig.user?.userId
183
- },
184
- jira: {
185
- baseUrl: process.env[ENV_KEYS.JIRA_BASE_URL] ?? globalConfig.jira?.baseUrl,
186
- apiToken: process.env[ENV_KEYS.JIRA_API_TOKEN] ?? globalConfig.jira?.apiToken,
187
- customFields: mergeCustomFields(globalConfig.jira?.customFields, repoConfig.jira?.customFields)
188
- },
189
- bitbucket: {
190
- baseUrl: process.env[ENV_KEYS.BITBUCKET_BASE_URL] ?? globalConfig.bitbucket?.baseUrl,
191
- pat: process.env[ENV_KEYS.BITBUCKET_PAT] ?? globalConfig.bitbucket?.pat
192
- },
193
- github: {
194
- baseUrl: process.env[ENV_KEYS.GITHUB_BASE_URL] ?? process.env[ENV_KEYS.GITHUB_API_URL_FALLBACK] ?? globalConfig.github?.baseUrl,
195
- token: process.env[ENV_KEYS.GITHUB_TOKEN] ?? process.env[ENV_KEYS.GITHUB_TOKEN_FALLBACK] ?? globalConfig.github?.token
196
- },
197
- confluence: {
198
- baseUrl: process.env[ENV_KEYS.CONFLUENCE_BASE_URL] ?? globalConfig.confluence?.baseUrl,
199
- apiToken: process.env[ENV_KEYS.CONFLUENCE_API_TOKEN] ?? globalConfig.confluence?.apiToken ?? process.env[ENV_KEYS.JIRA_API_TOKEN] ?? globalConfig.jira?.apiToken,
200
- apiTokenExplicit: !!(process.env[ENV_KEYS.CONFLUENCE_API_TOKEN] ?? globalConfig.confluence?.apiToken)
201
- },
202
- artifactory: {
203
- baseUrl: process.env[ENV_KEYS.ARTIFACTORY_BASE_URL] ?? globalConfig.artifactory?.baseUrl,
204
- token: process.env[ENV_KEYS.ARTIFACTORY_TOKEN] ?? globalConfig.artifactory?.token,
205
- npmRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_NPM] ?? globalConfig.artifactory?.npmRepo,
206
- nugetRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_NUGET] ?? globalConfig.artifactory?.nugetRepo,
207
- mavenRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_MAVEN] ?? globalConfig.artifactory?.mavenRepo
208
- },
209
- sonar: {
210
- baseUrl: process.env[ENV_KEYS.SONAR_BASE_URL] ?? globalConfig.sonar?.baseUrl,
211
- token: process.env[ENV_KEYS.SONAR_TOKEN] ?? process.env[ENV_KEYS.SONAR_TOKEN_FALLBACK] ?? globalConfig.sonar?.token
212
- },
213
- sde: (() => {
214
- const raw = process.env[ENV_KEYS.SDE_CONNECTION] ?? globalConfig.sde?.connection;
215
- const parsed = raw ? parseSdeConnection(raw) : null;
216
- return { baseUrl: parsed?.baseUrl, token: parsed?.token };
217
- })(),
218
- ado: {
219
- baseUrl: process.env[ENV_KEYS.ADO_BASE_URL] ?? globalConfig.ado?.baseUrl,
220
- pat: process.env[ENV_KEYS.ADO_PAT] ?? process.env[ENV_KEYS.ADO_PAT_FALLBACK] ?? globalConfig.ado?.pat,
221
- fieldAliases: globalConfig.ado?.fieldAliases ?? {},
222
- discoveredFields: globalConfig.ado?.discoveredFields ?? [],
223
- discoveredTypes: globalConfig.ado?.discoveredTypes ?? []
224
- },
225
- jenkins: {
226
- baseUrl: repoConfig.defaults?.jenkins?.baseUrl ?? process.env[ENV_KEYS.JENKINS_BASE_URL] ?? globalConfig.jenkins?.baseUrl,
227
- username: process.env[ENV_KEYS.JENKINS_USERNAME] ?? globalConfig.jenkins?.username,
228
- apiToken: process.env[ENV_KEYS.JENKINS_API_TOKEN] ?? globalConfig.jenkins?.apiToken
229
- },
230
- jenkinsInstances: Array.isArray(globalConfig.jenkinsInstances) ? globalConfig.jenkinsInstances : [],
231
- checkmarx: {
232
- baseUrl: process.env[ENV_KEYS.CHECKMARX_BASE_URL] ?? globalConfig.checkmarx?.baseUrl,
233
- tenantName: process.env[ENV_KEYS.CHECKMARX_TENANT_NAME] ?? globalConfig.checkmarx?.tenantName,
234
- apiKey: process.env[ENV_KEYS.CHECKMARX_API_KEY] ?? globalConfig.checkmarx?.apiKey,
235
- clientId: process.env[ENV_KEYS.CHECKMARX_CLIENT_ID] ?? globalConfig.checkmarx?.clientId,
236
- clientSecret: process.env[ENV_KEYS.CHECKMARX_CLIENT_SECRET] ?? globalConfig.checkmarx?.clientSecret
237
- },
238
- contrast: {
239
- baseUrl: process.env[ENV_KEYS.CONTRAST_BASE_URL] ?? globalConfig.contrast?.baseUrl,
240
- orgUuid: process.env[ENV_KEYS.CONTRAST_ORG_UUID] ?? globalConfig.contrast?.orgUuid,
241
- apiKey: process.env[ENV_KEYS.CONTRAST_API_KEY] ?? globalConfig.contrast?.apiKey,
242
- serviceKey: process.env[ENV_KEYS.CONTRAST_SERVICE_KEY] ?? globalConfig.contrast?.serviceKey,
243
- username: process.env[ENV_KEYS.CONTRAST_USERNAME] ?? globalConfig.contrast?.username
244
- },
245
- sonatypeiq: {
246
- baseUrl: process.env[ENV_KEYS.SONATYPEIQ_BASE_URL] ?? globalConfig.sonatypeiq?.baseUrl,
247
- userCode: process.env[ENV_KEYS.SONATYPEIQ_USER_CODE] ?? globalConfig.sonatypeiq?.userCode,
248
- passcode: process.env[ENV_KEYS.SONATYPEIQ_PASSCODE] ?? globalConfig.sonatypeiq?.passcode
249
- },
250
- openshift: {
251
- baseUrl: process.env[ENV_KEYS.OPENSHIFT_BASE_URL] ?? globalConfig.openshift?.baseUrl,
252
- token: process.env[ENV_KEYS.OPENSHIFT_TOKEN] ?? globalConfig.openshift?.token,
253
- defaultEnvironment: globalConfig.openshift?.defaultEnvironment,
254
- defaultInstance: globalConfig.openshift?.defaultInstance,
255
- environments: typeof globalConfig.openshift?.environments === "object" && globalConfig.openshift.environments !== null ? globalConfig.openshift.environments : {}
256
- },
257
- dynatrace: {
258
- baseUrl: process.env[ENV_KEYS.DYNATRACE_BASE_URL] ?? globalConfig.dynatrace?.baseUrl,
259
- apiToken: process.env[ENV_KEYS.DYNATRACE_API_TOKEN] ?? globalConfig.dynatrace?.apiToken,
260
- platformUrl: process.env[ENV_KEYS.DYNATRACE_PLATFORM_URL] ?? globalConfig.dynatrace?.platformUrl,
261
- platformToken: process.env[ENV_KEYS.DYNATRACE_PLATFORM_TOKEN] ?? globalConfig.dynatrace?.platformToken,
262
- defaultEnvironment: globalConfig.dynatrace?.defaultEnvironment,
263
- environments: typeof globalConfig.dynatrace?.environments === "object" && globalConfig.dynatrace.environments !== null ? globalConfig.dynatrace.environments : {}
264
- },
265
- logscale: {
266
- baseUrl: process.env[ENV_KEYS.LOGSCALE_BASE_URL] ?? globalConfig.logscale?.baseUrl,
267
- token: process.env[ENV_KEYS.LOGSCALE_TOKEN] ?? globalConfig.logscale?.token
268
- },
269
- splitio: {
270
- baseUrl: process.env[ENV_KEYS.SPLITIO_BASE_URL] ?? globalConfig.splitio?.baseUrl,
271
- adminApiKey: process.env[ENV_KEYS.SPLITIO_ADMIN_API_KEY] ?? globalConfig.splitio?.adminApiKey
272
- },
273
- figma: {
274
- baseUrl: process.env[ENV_KEYS.FIGMA_BASE_URL] ?? globalConfig.figma?.baseUrl,
275
- token: process.env[ENV_KEYS.FIGMA_TOKEN] ?? globalConfig.figma?.token
276
- },
277
- alation: {
278
- baseUrl: process.env[ENV_KEYS.ALATION_BASE_URL] ?? globalConfig.alation?.baseUrl,
279
- refreshToken: process.env[ENV_KEYS.ALATION_REFRESH_TOKEN] ?? globalConfig.alation?.refreshToken,
280
- userId: process.env[ENV_KEYS.ALATION_USER_ID] ?? globalConfig.alation?.userId
281
- },
282
- defaults: mergedDefaults
283
- };
284
- }
285
- function normalizeBaseUrl(raw) {
286
- const trimmed = raw.trim();
287
- if (!trimmed) return trimmed;
288
- return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
289
- }
290
- function writeGlobalConfig(config, configPath) {
291
- const filePath = getGlobalConfigPath(configPath);
292
- const dir = path.dirname(filePath);
293
- if (!fs.existsSync(dir)) {
294
- fs.mkdirSync(dir, { recursive: true });
295
- }
296
- fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", "utf8");
297
- }
298
- function writeRepoConfig(config) {
299
- const repoRoot = getRepoRoot();
300
- const targetDir = repoRoot ?? process.cwd();
301
- fs.writeFileSync(path.join(targetDir, ".pncli.json"), JSON.stringify(config, null, 2) + "\n", "utf8");
302
- }
303
- function parseConfigValue(value) {
304
- try {
305
- const parsed = JSON.parse(value);
306
- if (typeof parsed === "object" && parsed !== null) {
307
- return parsed;
308
- }
309
- } catch {
310
- }
311
- return value;
312
- }
313
- function setConfigValue(key, value, configPath) {
314
- const filePath = getGlobalConfigPath(configPath);
315
- const existing = loadJsonFile(filePath) ?? {};
316
- const parts = key.split(".");
317
- let current = existing;
318
- for (let i = 0; i < parts.length - 1; i++) {
319
- const part = parts[i];
320
- if (typeof current[part] !== "object" || current[part] === null) {
321
- current[part] = {};
322
- }
323
- current = current[part];
324
- }
325
- current[parts[parts.length - 1]] = parseConfigValue(value);
326
- writeGlobalConfig(existing, configPath);
327
- }
328
- function setRepoConfigValue(key, value) {
329
- const repoRoot = getRepoRoot();
330
- const targetDir = repoRoot ?? process.cwd();
331
- const filePath = path.join(targetDir, ".pncli.json");
332
- const existing = loadJsonFile(filePath) ?? {};
333
- const parts = key.split(".");
334
- let current = existing;
335
- for (let i = 0; i < parts.length - 1; i++) {
336
- const part = parts[i];
337
- if (typeof current[part] !== "object" || current[part] === null) {
338
- current[part] = {};
339
- }
340
- current = current[part];
341
- }
342
- current[parts[parts.length - 1]] = parseConfigValue(value);
343
- writeRepoConfig(existing);
344
- }
345
- function maskConfig(config) {
346
- return {
347
- ...config,
348
- jira: {
349
- ...config.jira,
350
- apiToken: config.jira.apiToken ? "***" : void 0,
351
- customFields: config.jira.customFields
352
- },
353
- bitbucket: {
354
- ...config.bitbucket,
355
- pat: config.bitbucket.pat ? "***" : void 0
356
- },
357
- github: {
358
- ...config.github,
359
- token: config.github.token ? "***" : void 0
360
- },
361
- confluence: {
362
- ...config.confluence,
363
- apiToken: config.confluence.apiToken ? "***" : void 0
364
- },
365
- artifactory: {
366
- ...config.artifactory,
367
- token: config.artifactory.token ? "***" : void 0
368
- },
369
- sonar: {
370
- ...config.sonar,
371
- token: config.sonar.token ? "***" : void 0
372
- },
373
- sde: {
374
- baseUrl: config.sde.baseUrl,
375
- token: config.sde.token ? "***" : void 0
376
- },
377
- ado: {
378
- ...config.ado,
379
- pat: config.ado.pat ? "***" : void 0
380
- },
381
- jenkins: {
382
- ...config.jenkins,
383
- apiToken: config.jenkins.apiToken ? "***" : void 0
384
- },
385
- jenkinsInstances: config.jenkinsInstances.map((inst) => ({
386
- ...inst,
387
- apiToken: inst.apiToken ? "***" : void 0
388
- })),
389
- checkmarx: {
390
- ...config.checkmarx,
391
- apiKey: config.checkmarx.apiKey ? "***" : void 0,
392
- clientSecret: config.checkmarx.clientSecret ? "***" : void 0
393
- },
394
- contrast: {
395
- ...config.contrast,
396
- apiKey: config.contrast.apiKey ? "***" : void 0,
397
- serviceKey: config.contrast.serviceKey ? "***" : void 0
398
- },
399
- sonatypeiq: {
400
- ...config.sonatypeiq,
401
- passcode: config.sonatypeiq.passcode ? "***" : void 0
402
- },
403
- openshift: {
404
- ...config.openshift,
405
- token: config.openshift.token ? "***" : void 0,
406
- environments: Object.fromEntries(
407
- Object.entries(config.openshift.environments).map(([envName, envCfg]) => [
408
- envName,
409
- {
410
- instances: Object.fromEntries(
411
- Object.entries(envCfg.instances ?? {}).map(([instName, instCfg]) => [
412
- instName,
413
- { ...instCfg, token: instCfg.token ? "***" : void 0 }
414
- ])
415
- )
416
- }
417
- ])
418
- )
419
- },
420
- dynatrace: {
421
- ...config.dynatrace,
422
- apiToken: config.dynatrace.apiToken ? "***" : void 0,
423
- platformToken: config.dynatrace.platformToken ? "***" : void 0,
424
- environments: Object.fromEntries(
425
- Object.entries(config.dynatrace.environments).map(([name, env]) => [
426
- name,
427
- {
428
- ...env,
429
- apiToken: env.apiToken ? "***" : void 0,
430
- platformToken: env.platformToken ? "***" : void 0
431
- }
432
- ])
433
- )
434
- },
435
- logscale: {
436
- ...config.logscale,
437
- token: config.logscale.token ? "***" : void 0
438
- },
439
- splitio: {
440
- ...config.splitio,
441
- adminApiKey: config.splitio.adminApiKey ? "***" : void 0
442
- },
443
- figma: {
444
- ...config.figma,
445
- token: config.figma.token ? "***" : void 0
446
- },
447
- alation: {
448
- ...config.alation,
449
- refreshToken: config.alation.refreshToken ? "***" : void 0
450
- }
451
- };
452
- }
453
-
454
- export {
455
- assertValidCustomFields,
456
- getGlobalConfigPath,
457
- loadJsonFile,
458
- loadConfig,
459
- normalizeBaseUrl,
460
- writeGlobalConfig,
461
- writeRepoConfig,
462
- setConfigValue,
463
- setRepoConfigValue,
464
- maskConfig
465
- };
466
- //# sourceMappingURL=chunk-QHJ2HM5J.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/config.ts","../src/types/jira.ts","../src/lib/validate-custom-fields.ts"],"sourcesContent":["import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport type { GlobalConfig, RepoConfig, ResolvedConfig, JiraDefaults, BitbucketDefaults, GitHubDefaults, SonarDefaults, SdeDefaults, AdoDefaults, JenkinsDefaults, JenkinsInstanceConfig } from '../types/config.js';\nimport type { CustomFieldDefinition } from '../types/jira.js';\nimport { assertValidCustomFields } from './validate-custom-fields.js';\n\nconst ENV_KEYS = {\n EMAIL: 'PNCLI_EMAIL',\n USERID: 'PNCLI_USERID',\n JIRA_BASE_URL: 'PNCLI_JIRA_BASE_URL',\n JIRA_API_TOKEN: 'PNCLI_JIRA_API_TOKEN',\n BITBUCKET_BASE_URL: 'PNCLI_BITBUCKET_BASE_URL',\n BITBUCKET_PAT: 'PNCLI_BITBUCKET_PAT',\n GITHUB_BASE_URL: 'PNCLI_GITHUB_BASE_URL',\n GITHUB_TOKEN: 'PNCLI_GITHUB_TOKEN',\n // Well-known vars CI platforms provide without any pncli-specific setup.\n GITHUB_TOKEN_FALLBACK: 'GITHUB_TOKEN',\n GITHUB_API_URL_FALLBACK: 'GITHUB_API_URL',\n CONFLUENCE_BASE_URL: 'PNCLI_CONFLUENCE_BASE_URL',\n CONFLUENCE_API_TOKEN: 'PNCLI_CONFLUENCE_API_TOKEN',\n ARTIFACTORY_BASE_URL: 'PNCLI_ARTIFACTORY_BASE_URL',\n ARTIFACTORY_TOKEN: 'PNCLI_ARTIFACTORY_TOKEN',\n ARTIFACTORY_REPO_NPM: 'PNCLI_ARTIFACTORY_REPO_NPM',\n ARTIFACTORY_REPO_NUGET: 'PNCLI_ARTIFACTORY_REPO_NUGET',\n ARTIFACTORY_REPO_MAVEN: 'PNCLI_ARTIFACTORY_REPO_MAVEN',\n SONAR_BASE_URL: 'PNCLI_SONAR_BASE_URL',\n SONAR_TOKEN: 'PNCLI_SONAR_TOKEN',\n // SonarSource's own scanner CLI standard var name — see the comment above GITHUB_TOKEN_FALLBACK.\n SONAR_TOKEN_FALLBACK: 'SONAR_TOKEN',\n SDE_CONNECTION: 'PNCLI_SDE_CONNECTION',\n ADO_BASE_URL: 'PNCLI_ADO_BASE_URL',\n ADO_PAT: 'PNCLI_ADO_PAT',\n // Azure Pipelines' conventional name for $(System.AccessToken) — see the comment above GITHUB_TOKEN_FALLBACK.\n ADO_PAT_FALLBACK: 'SYSTEM_ACCESSTOKEN',\n JENKINS_BASE_URL: 'PNCLI_JENKINS_BASE_URL',\n JENKINS_USERNAME: 'PNCLI_JENKINS_USERNAME',\n JENKINS_API_TOKEN: 'PNCLI_JENKINS_API_TOKEN',\n CHECKMARX_BASE_URL: 'PNCLI_CHECKMARX_BASE_URL',\n CHECKMARX_TENANT_NAME: 'PNCLI_CHECKMARX_TENANT_NAME',\n CHECKMARX_API_KEY: 'PNCLI_CHECKMARX_API_KEY',\n CHECKMARX_CLIENT_ID: 'PNCLI_CHECKMARX_CLIENT_ID',\n CHECKMARX_CLIENT_SECRET: 'PNCLI_CHECKMARX_CLIENT_SECRET',\n CONTRAST_BASE_URL: 'PNCLI_CONTRAST_BASE_URL',\n CONTRAST_ORG_UUID: 'PNCLI_CONTRAST_ORG_UUID',\n CONTRAST_API_KEY: 'PNCLI_CONTRAST_API_KEY',\n CONTRAST_SERVICE_KEY: 'PNCLI_CONTRAST_SERVICE_KEY',\n CONTRAST_USERNAME: 'PNCLI_CONTRAST_USERNAME',\n SONATYPEIQ_BASE_URL: 'PNCLI_SONATYPEIQ_BASE_URL',\n SONATYPEIQ_USER_CODE: 'PNCLI_SONATYPEIQ_USER_CODE',\n SONATYPEIQ_PASSCODE: 'PNCLI_SONATYPEIQ_PASSCODE',\n OPENSHIFT_BASE_URL: 'PNCLI_OPENSHIFT_BASE_URL',\n OPENSHIFT_TOKEN: 'PNCLI_OPENSHIFT_TOKEN',\n DYNATRACE_BASE_URL: 'PNCLI_DYNATRACE_BASE_URL',\n DYNATRACE_API_TOKEN: 'PNCLI_DYNATRACE_API_TOKEN',\n DYNATRACE_PLATFORM_URL: 'PNCLI_DYNATRACE_PLATFORM_URL',\n DYNATRACE_PLATFORM_TOKEN: 'PNCLI_DYNATRACE_PLATFORM_TOKEN',\n LOGSCALE_BASE_URL: 'PNCLI_LOGSCALE_BASE_URL',\n LOGSCALE_TOKEN: 'PNCLI_LOGSCALE_TOKEN',\n SPLITIO_BASE_URL: 'PNCLI_SPLITIO_BASE_URL',\n SPLITIO_ADMIN_API_KEY: 'PNCLI_SPLITIO_ADMIN_API_KEY',\n FIGMA_BASE_URL: 'PNCLI_FIGMA_BASE_URL',\n FIGMA_TOKEN: 'PNCLI_FIGMA_TOKEN',\n ALATION_BASE_URL: 'PNCLI_ALATION_BASE_URL',\n ALATION_REFRESH_TOKEN: 'PNCLI_ALATION_REFRESH_TOKEN',\n ALATION_USER_ID: 'PNCLI_ALATION_USER_ID',\n CONFIG_PATH: 'PNCLI_CONFIG_PATH'\n} as const;\n\nfunction getGlobalConfigPath(overridePath?: string): string {\n if (overridePath) return overridePath;\n const envPath = process.env[ENV_KEYS.CONFIG_PATH];\n if (envPath) return envPath;\n return path.join(os.homedir(), '.pncli', 'config.json');\n}\n\nfunction loadJsonFile<T>(filePath: string): T | null {\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nfunction getRepoRoot(): string | null {\n try {\n return execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();\n } catch {\n return null;\n }\n}\n\nfunction parseSdeConnection(connection: string): { token: string; baseUrl: string } | null {\n const idx = connection.indexOf('@');\n if (idx <= 0) return null;\n const token = connection.slice(0, idx);\n const host = connection.slice(idx + 1);\n const baseUrl = /^https?:\\/\\//i.test(host) ? host : `https://${host}`;\n return { token, baseUrl };\n}\n\nfunction mergeCustomFields(\n global: CustomFieldDefinition[] | undefined,\n repo: CustomFieldDefinition[] | undefined\n): CustomFieldDefinition[] {\n const map = new Map<string, CustomFieldDefinition>();\n if (global != null) {\n assertValidCustomFields(global, { source: 'global config' });\n for (const f of global) map.set(f.id, f);\n }\n if (repo != null) {\n assertValidCustomFields(repo, { source: 'repo config (.pncli.json)', repo: true });\n for (const f of repo) map.set(f.id, f); // repo wins\n }\n return Array.from(map.values());\n}\n\nfunction mergeDefaults(\n global: GlobalConfig['defaults'],\n repo: RepoConfig['defaults']\n): { jira: JiraDefaults; bitbucket: BitbucketDefaults; github: GitHubDefaults; sonar: SonarDefaults; sde: SdeDefaults; ado: AdoDefaults; jenkins: JenkinsDefaults } {\n return {\n jira: { ...global?.jira, ...repo?.jira },\n bitbucket: { ...global?.bitbucket, ...repo?.bitbucket },\n github: { ...global?.github, ...repo?.github },\n sonar: { ...global?.sonar, ...repo?.sonar },\n sde: { ...global?.sde, ...repo?.sde },\n ado: { ...global?.ado, ...repo?.ado },\n jenkins: { ...global?.jenkins, ...repo?.jenkins }\n };\n}\n\nexport interface LoadConfigOptions {\n configPath?: string;\n}\n\nexport function loadConfig(opts: LoadConfigOptions = {}): ResolvedConfig {\n const globalConfigPath = getGlobalConfigPath(opts.configPath);\n const globalConfig = loadJsonFile<GlobalConfig>(globalConfigPath) ?? {};\n\n const repoRoot = getRepoRoot();\n let repoConfig: RepoConfig = {};\n if (repoRoot) {\n repoConfig = loadJsonFile<RepoConfig>(path.join(repoRoot, '.pncli.json')) ?? {};\n }\n\n const mergedDefaults = mergeDefaults(globalConfig.defaults, repoConfig.defaults);\n\n return {\n user: {\n email: process.env[ENV_KEYS.EMAIL] ?? globalConfig.user?.email,\n userId: process.env[ENV_KEYS.USERID] ?? globalConfig.user?.userId\n },\n jira: {\n baseUrl: process.env[ENV_KEYS.JIRA_BASE_URL] ?? globalConfig.jira?.baseUrl,\n apiToken: process.env[ENV_KEYS.JIRA_API_TOKEN] ?? globalConfig.jira?.apiToken,\n customFields: mergeCustomFields(globalConfig.jira?.customFields, repoConfig.jira?.customFields)\n },\n bitbucket: {\n baseUrl: process.env[ENV_KEYS.BITBUCKET_BASE_URL] ?? globalConfig.bitbucket?.baseUrl,\n pat: process.env[ENV_KEYS.BITBUCKET_PAT] ?? globalConfig.bitbucket?.pat\n },\n github: {\n baseUrl: process.env[ENV_KEYS.GITHUB_BASE_URL] ?? process.env[ENV_KEYS.GITHUB_API_URL_FALLBACK] ?? globalConfig.github?.baseUrl,\n token: process.env[ENV_KEYS.GITHUB_TOKEN] ?? process.env[ENV_KEYS.GITHUB_TOKEN_FALLBACK] ?? globalConfig.github?.token\n },\n confluence: {\n baseUrl: process.env[ENV_KEYS.CONFLUENCE_BASE_URL] ?? globalConfig.confluence?.baseUrl,\n apiToken: process.env[ENV_KEYS.CONFLUENCE_API_TOKEN] ?? globalConfig.confluence?.apiToken\n ?? process.env[ENV_KEYS.JIRA_API_TOKEN] ?? globalConfig.jira?.apiToken,\n apiTokenExplicit: !!(\n process.env[ENV_KEYS.CONFLUENCE_API_TOKEN] ?? globalConfig.confluence?.apiToken\n )\n },\n artifactory: {\n baseUrl: process.env[ENV_KEYS.ARTIFACTORY_BASE_URL] ?? globalConfig.artifactory?.baseUrl,\n token: process.env[ENV_KEYS.ARTIFACTORY_TOKEN] ?? globalConfig.artifactory?.token,\n npmRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_NPM] ?? globalConfig.artifactory?.npmRepo,\n nugetRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_NUGET] ?? globalConfig.artifactory?.nugetRepo,\n mavenRepo: process.env[ENV_KEYS.ARTIFACTORY_REPO_MAVEN] ?? globalConfig.artifactory?.mavenRepo\n },\n sonar: {\n baseUrl: process.env[ENV_KEYS.SONAR_BASE_URL] ?? globalConfig.sonar?.baseUrl,\n token: process.env[ENV_KEYS.SONAR_TOKEN] ?? process.env[ENV_KEYS.SONAR_TOKEN_FALLBACK] ?? globalConfig.sonar?.token\n },\n sde: (() => {\n const raw = process.env[ENV_KEYS.SDE_CONNECTION] ?? globalConfig.sde?.connection;\n const parsed = raw ? parseSdeConnection(raw) : null;\n return { baseUrl: parsed?.baseUrl, token: parsed?.token };\n })(),\n ado: {\n baseUrl: process.env[ENV_KEYS.ADO_BASE_URL] ?? globalConfig.ado?.baseUrl,\n pat: process.env[ENV_KEYS.ADO_PAT] ?? process.env[ENV_KEYS.ADO_PAT_FALLBACK] ?? globalConfig.ado?.pat,\n fieldAliases: globalConfig.ado?.fieldAliases ?? {},\n discoveredFields: globalConfig.ado?.discoveredFields ?? [],\n discoveredTypes: globalConfig.ado?.discoveredTypes ?? []\n },\n jenkins: {\n baseUrl: repoConfig.defaults?.jenkins?.baseUrl ?? process.env[ENV_KEYS.JENKINS_BASE_URL] ?? globalConfig.jenkins?.baseUrl,\n username: process.env[ENV_KEYS.JENKINS_USERNAME] ?? globalConfig.jenkins?.username,\n apiToken: process.env[ENV_KEYS.JENKINS_API_TOKEN] ?? globalConfig.jenkins?.apiToken\n },\n jenkinsInstances: (Array.isArray(globalConfig.jenkinsInstances) ? globalConfig.jenkinsInstances : []) as JenkinsInstanceConfig[],\n checkmarx: {\n baseUrl: process.env[ENV_KEYS.CHECKMARX_BASE_URL] ?? globalConfig.checkmarx?.baseUrl,\n tenantName: process.env[ENV_KEYS.CHECKMARX_TENANT_NAME] ?? globalConfig.checkmarx?.tenantName,\n apiKey: process.env[ENV_KEYS.CHECKMARX_API_KEY] ?? globalConfig.checkmarx?.apiKey,\n clientId: process.env[ENV_KEYS.CHECKMARX_CLIENT_ID] ?? globalConfig.checkmarx?.clientId,\n clientSecret: process.env[ENV_KEYS.CHECKMARX_CLIENT_SECRET] ?? globalConfig.checkmarx?.clientSecret,\n },\n contrast: {\n baseUrl: process.env[ENV_KEYS.CONTRAST_BASE_URL] ?? globalConfig.contrast?.baseUrl,\n orgUuid: process.env[ENV_KEYS.CONTRAST_ORG_UUID] ?? globalConfig.contrast?.orgUuid,\n apiKey: process.env[ENV_KEYS.CONTRAST_API_KEY] ?? globalConfig.contrast?.apiKey,\n serviceKey: process.env[ENV_KEYS.CONTRAST_SERVICE_KEY] ?? globalConfig.contrast?.serviceKey,\n username: process.env[ENV_KEYS.CONTRAST_USERNAME] ?? globalConfig.contrast?.username,\n },\n sonatypeiq: {\n baseUrl: process.env[ENV_KEYS.SONATYPEIQ_BASE_URL] ?? globalConfig.sonatypeiq?.baseUrl,\n userCode: process.env[ENV_KEYS.SONATYPEIQ_USER_CODE] ?? globalConfig.sonatypeiq?.userCode,\n passcode: process.env[ENV_KEYS.SONATYPEIQ_PASSCODE] ?? globalConfig.sonatypeiq?.passcode,\n },\n openshift: {\n baseUrl: process.env[ENV_KEYS.OPENSHIFT_BASE_URL] ?? globalConfig.openshift?.baseUrl,\n token: process.env[ENV_KEYS.OPENSHIFT_TOKEN] ?? globalConfig.openshift?.token,\n defaultEnvironment: globalConfig.openshift?.defaultEnvironment,\n defaultInstance: globalConfig.openshift?.defaultInstance,\n environments: (typeof globalConfig.openshift?.environments === 'object' && globalConfig.openshift.environments !== null)\n ? globalConfig.openshift.environments\n : {},\n },\n dynatrace: {\n baseUrl: process.env[ENV_KEYS.DYNATRACE_BASE_URL] ?? globalConfig.dynatrace?.baseUrl,\n apiToken: process.env[ENV_KEYS.DYNATRACE_API_TOKEN] ?? globalConfig.dynatrace?.apiToken,\n platformUrl: process.env[ENV_KEYS.DYNATRACE_PLATFORM_URL] ?? globalConfig.dynatrace?.platformUrl,\n platformToken: process.env[ENV_KEYS.DYNATRACE_PLATFORM_TOKEN] ?? globalConfig.dynatrace?.platformToken,\n defaultEnvironment: globalConfig.dynatrace?.defaultEnvironment,\n environments: (typeof globalConfig.dynatrace?.environments === 'object' && globalConfig.dynatrace.environments !== null)\n ? globalConfig.dynatrace.environments\n : {},\n },\n logscale: {\n baseUrl: process.env[ENV_KEYS.LOGSCALE_BASE_URL] ?? globalConfig.logscale?.baseUrl,\n token: process.env[ENV_KEYS.LOGSCALE_TOKEN] ?? globalConfig.logscale?.token,\n },\n splitio: {\n baseUrl: process.env[ENV_KEYS.SPLITIO_BASE_URL] ?? globalConfig.splitio?.baseUrl,\n adminApiKey: process.env[ENV_KEYS.SPLITIO_ADMIN_API_KEY] ?? globalConfig.splitio?.adminApiKey,\n },\n figma: {\n baseUrl: process.env[ENV_KEYS.FIGMA_BASE_URL] ?? globalConfig.figma?.baseUrl,\n token: process.env[ENV_KEYS.FIGMA_TOKEN] ?? globalConfig.figma?.token,\n },\n alation: {\n baseUrl: process.env[ENV_KEYS.ALATION_BASE_URL] ?? globalConfig.alation?.baseUrl,\n refreshToken: process.env[ENV_KEYS.ALATION_REFRESH_TOKEN] ?? globalConfig.alation?.refreshToken,\n userId: process.env[ENV_KEYS.ALATION_USER_ID] ?? globalConfig.alation?.userId,\n },\n defaults: mergedDefaults\n };\n}\n\nexport function normalizeBaseUrl(raw: string): string {\n const trimmed = raw.trim();\n if (!trimmed) return trimmed;\n return /^https?:\\/\\//i.test(trimmed) ? trimmed : `https://${trimmed}`;\n}\n\nexport function writeGlobalConfig(config: GlobalConfig, configPath?: string): void {\n const filePath = getGlobalConfigPath(configPath);\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n}\n\nexport function writeRepoConfig(config: RepoConfig): void {\n const repoRoot = getRepoRoot();\n const targetDir = repoRoot ?? process.cwd();\n fs.writeFileSync(path.join(targetDir, '.pncli.json'), JSON.stringify(config, null, 2) + '\\n', 'utf8');\n}\n\nfunction parseConfigValue(value: string): unknown {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === 'object' && parsed !== null) {\n return parsed;\n }\n } catch {\n // not valid JSON — fall through to raw string\n }\n return value;\n}\n\nexport function setConfigValue(key: string, value: string, configPath?: string): void {\n const filePath = getGlobalConfigPath(configPath);\n const existing = loadJsonFile<GlobalConfig>(filePath) ?? {};\n\n const parts = key.split('.');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = existing;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n if (typeof current[part] !== 'object' || current[part] === null) {\n current[part] = {};\n }\n current = current[part];\n }\n current[parts[parts.length - 1]!] = parseConfigValue(value);\n\n writeGlobalConfig(existing, configPath);\n}\n\nexport function setRepoConfigValue(key: string, value: string): void {\n const repoRoot = getRepoRoot();\n const targetDir = repoRoot ?? process.cwd();\n const filePath = path.join(targetDir, '.pncli.json');\n const existing = loadJsonFile<RepoConfig>(filePath) ?? {};\n\n const parts = key.split('.');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = existing;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n if (typeof current[part] !== 'object' || current[part] === null) {\n current[part] = {};\n }\n current = current[part];\n }\n current[parts[parts.length - 1]!] = parseConfigValue(value);\n\n writeRepoConfig(existing);\n}\n\nexport function maskConfig(config: ResolvedConfig): unknown {\n return {\n ...config,\n jira: {\n ...config.jira,\n apiToken: config.jira.apiToken ? '***' : undefined,\n customFields: config.jira.customFields\n },\n bitbucket: {\n ...config.bitbucket,\n pat: config.bitbucket.pat ? '***' : undefined\n },\n github: {\n ...config.github,\n token: config.github.token ? '***' : undefined\n },\n confluence: {\n ...config.confluence,\n apiToken: config.confluence.apiToken ? '***' : undefined\n },\n artifactory: {\n ...config.artifactory,\n token: config.artifactory.token ? '***' : undefined\n },\n sonar: {\n ...config.sonar,\n token: config.sonar.token ? '***' : undefined\n },\n sde: {\n baseUrl: config.sde.baseUrl,\n token: config.sde.token ? '***' : undefined\n },\n ado: {\n ...config.ado,\n pat: config.ado.pat ? '***' : undefined\n },\n jenkins: {\n ...config.jenkins,\n apiToken: config.jenkins.apiToken ? '***' : undefined\n },\n jenkinsInstances: config.jenkinsInstances.map(inst => ({\n ...inst,\n apiToken: inst.apiToken ? '***' : undefined\n })),\n checkmarx: {\n ...config.checkmarx,\n apiKey: config.checkmarx.apiKey ? '***' : undefined,\n clientSecret: config.checkmarx.clientSecret ? '***' : undefined\n },\n contrast: {\n ...config.contrast,\n apiKey: config.contrast.apiKey ? '***' : undefined,\n serviceKey: config.contrast.serviceKey ? '***' : undefined\n },\n sonatypeiq: {\n ...config.sonatypeiq,\n passcode: config.sonatypeiq.passcode ? '***' : undefined\n },\n openshift: {\n ...config.openshift,\n token: config.openshift.token ? '***' : undefined,\n environments: Object.fromEntries(\n Object.entries(config.openshift.environments).map(([envName, envCfg]) => [\n envName,\n {\n instances: Object.fromEntries(\n Object.entries(envCfg.instances ?? {}).map(([instName, instCfg]) => [\n instName,\n { ...instCfg, token: instCfg.token ? '***' : undefined }\n ])\n )\n }\n ])\n )\n },\n dynatrace: {\n ...config.dynatrace,\n apiToken: config.dynatrace.apiToken ? '***' : undefined,\n platformToken: config.dynatrace.platformToken ? '***' : undefined,\n environments: Object.fromEntries(\n Object.entries(config.dynatrace.environments).map(([name, env]) => [\n name,\n {\n ...env,\n apiToken: env.apiToken ? '***' : undefined,\n platformToken: env.platformToken ? '***' : undefined\n }\n ])\n )\n },\n logscale: {\n ...config.logscale,\n token: config.logscale.token ? '***' : undefined\n },\n splitio: {\n ...config.splitio,\n adminApiKey: config.splitio.adminApiKey ? '***' : undefined\n },\n figma: {\n ...config.figma,\n token: config.figma.token ? '***' : undefined\n },\n alation: {\n ...config.alation,\n refreshToken: config.alation.refreshToken ? '***' : undefined\n }\n };\n}\n\nexport { getGlobalConfigPath, loadJsonFile };\n","// Phase 3 — Jira Data Cloud types\n\nexport const CUSTOM_FIELD_TYPES = [\n 'string',\n 'number',\n 'date',\n 'datetime',\n 'select',\n 'multi-select',\n 'option-id',\n 'cascading-select',\n 'user',\n 'labels',\n 'url',\n 'textarea'\n] as const;\n\nexport type CustomFieldType = (typeof CUSTOM_FIELD_TYPES)[number];\n\nexport interface CustomFieldDefinition {\n id: string;\n name: string;\n /** Drives how a `--field` value is shaped for Jira's API. Omitted = raw string. */\n type?: CustomFieldType;\n description?: string;\n examples?: string[];\n}\n\nexport interface CustomFieldMap {\n byName: Map<string, CustomFieldDefinition>;\n byId: Map<string, CustomFieldDefinition>;\n}\n\nexport interface JiraUser {\n name: string;\n displayName: string;\n}\n\nexport interface JiraFieldInfo {\n id: string;\n name: string;\n custom: boolean;\n schema?: { type: string; custom?: string };\n allowedValues?: Array<{ id: string; value?: string; name?: string; children?: Array<{ id: string; value: string }> }>;\n /** Suggested pncli config type inferred from the Jira field schema. */\n pncliType?: CustomFieldType;\n}\n\nexport interface JiraIssue {\n id: string;\n key: string;\n fields: {\n summary: string;\n description?: unknown;\n status: { name: string };\n priority?: { name: string };\n assignee?: JiraUser | null;\n reporter?: JiraUser;\n labels?: string[];\n issuetype: { name: string };\n project: { key: string; name: string };\n created: string;\n updated: string;\n [key: string]: unknown;\n };\n}\n\nexport interface JiraTransition {\n id: string;\n name: string;\n to: { name: string };\n}\n\nexport interface JiraComment {\n id: string;\n author: JiraUser;\n body: unknown;\n created: string;\n updated: string;\n}\n\nexport interface JiraSearchResult {\n issues: JiraIssue[];\n total: number;\n startAt: number;\n maxResults: number;\n}\n\nexport interface JiraAttachment {\n id: string;\n filename: string;\n author: JiraUser;\n created: string;\n size: number;\n mimeType: string;\n content: string;\n}\n\nexport interface JiraBoard {\n id: number;\n name: string;\n type: string;\n}\n\nexport interface JiraSprint {\n id: number;\n name: string;\n state: string;\n startDate?: string;\n endDate?: string;\n goal?: string;\n}\n","import { PncliError } from './errors.js';\nimport { CUSTOM_FIELD_TYPES } from '../types/jira.js';\nimport type { CustomFieldDefinition } from '../types/jira.js';\n\nexport interface ValidateCustomFieldsOptions {\n /** Where the value came from, for the error message — e.g. `global config`. */\n source?: string;\n /** Append `--repo` to the suggested fix, for values read from `.pncli.json`. */\n repo?: boolean;\n}\n\nconst EXAMPLE = '[{\"id\":\"customfield_10032\",\"name\":\"Epic Link\",\"type\":\"select\"}]';\n\n/**\n * Validates `jira.customFields` before it's indexed or merged. The value comes straight\n * off disk (or a `config set` value that fell back to a raw string when JSON.parse failed —\n * e.g. mangled shell quoting), so it isn't guaranteed to match CustomFieldDefinition at\n * runtime even though the type says it does. Shared by `loadConfig` (which names the\n * offending config file) and `buildFieldMap` (which doesn't know where the value came from).\n */\nexport function assertValidCustomFields(\n fields: unknown,\n opts: ValidateCustomFieldsOptions = {}\n): asserts fields is CustomFieldDefinition[] {\n const where = opts.source ? `in ${opts.source}` : 'config';\n const fix = (value: string) => `Fix with: pncli config set jira.customFields '${value}'${opts.repo ? ' --repo' : ''}`;\n\n if (!Array.isArray(fields)) {\n throw new PncliError(\n `Invalid jira.customFields ${where}: expected an array, got ${JSON.stringify(fields)}. ${fix('[]')}`,\n 1\n );\n }\n for (const f of fields) {\n const entry = f as { id?: unknown; name?: unknown; type?: unknown } | null;\n if (typeof entry !== 'object' || entry === null || typeof entry.id !== 'string' || typeof entry.name !== 'string') {\n throw new PncliError(\n `Invalid jira.customFields ${where}: each entry must be an object with string \"id\" and \"name\" fields. Got: ${JSON.stringify(f)}. ${fix(EXAMPLE)}`,\n 1\n );\n }\n // `type` is optional (omitted = raw string, per skills/pncli/jira.md), but when present it\n // must be a known CustomFieldType — otherwise formatFieldValue silently falls through.\n if (entry.type !== undefined && (typeof entry.type !== 'string' || !(CUSTOM_FIELD_TYPES as readonly string[]).includes(entry.type))) {\n throw new PncliError(\n `Invalid jira.customFields ${where}: entry \"${entry.name}\" has unknown \"type\" ${JSON.stringify(entry.type)}; expected one of ${CUSTOM_FIELD_TYPES.join(', ')}. ${fix(EXAMPLE)}`,\n 1\n );\n }\n }\n}\n"],"mappings":"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","names":[]}