@kolatts/pncli 1.17.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/copilot-instructions.md +44 -5
- package/dist/{chunk-FFVQ4PA7.js → chunk-FXY262BR.js} +38 -8
- package/dist/chunk-FXY262BR.js.map +1 -0
- package/dist/{chunk-XPPEXJBP.js → chunk-WM5NYVEO.js} +112 -24
- package/dist/chunk-WM5NYVEO.js.map +1 -0
- package/dist/cli.js +1065 -131
- package/dist/cli.js.map +1 -1
- package/dist/{config-S56LADVF.js → config-CPRXY5SN.js} +2 -2
- package/dist/{http-5WRBWEM6.js → http-FNRE7NQU.js} +2 -2
- package/package.json +1 -1
- package/skills/pncli/SKILL.md +7 -2
- package/skills/pncli/ado.md +19 -1
- package/skills/pncli/bitbucket.md +11 -1
- package/skills/pncli/checkmarx.md +20 -13
- package/skills/pncli/confluence.md +5 -1
- package/skills/pncli/dynatrace.md +46 -0
- package/skills/pncli/github.md +11 -1
- package/skills/pncli/jira.md +11 -0
- package/dist/chunk-FFVQ4PA7.js.map +0 -1
- package/dist/chunk-XPPEXJBP.js.map +0 -1
- /package/dist/{config-S56LADVF.js.map → config-CPRXY5SN.js.map} +0 -0
- /package/dist/{http-5WRBWEM6.js.map → http-FNRE7NQU.js.map} +0 -0
package/README.md
CHANGED
|
@@ -68,9 +68,11 @@ pncli uses a three-layer config system (highest priority wins):
|
|
|
68
68
|
| `PNCLI_UDEPLOY_PAT` | IBM UrbanCode Deploy personal access token |
|
|
69
69
|
| `PNCLI_UDEPLOY_USERNAME` | IBM UrbanCode Deploy username (alternative to PAT) |
|
|
70
70
|
| `PNCLI_UDEPLOY_PASSWORD` | IBM UrbanCode Deploy password (used with `PNCLI_UDEPLOY_USERNAME`) |
|
|
71
|
-
| `PNCLI_CHECKMARX_BASE_URL` | Checkmarx
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
71
|
+
| `PNCLI_CHECKMARX_BASE_URL` | Checkmarx One API base URL |
|
|
72
|
+
| `PNCLI_CHECKMARX_TENANT_NAME` | Checkmarx One tenant name |
|
|
73
|
+
| `PNCLI_CHECKMARX_API_KEY` | Checkmarx One API key |
|
|
74
|
+
| `PNCLI_CHECKMARX_CLIENT_ID` | Checkmarx One OAuth client ID (API key alternative) |
|
|
75
|
+
| `PNCLI_CHECKMARX_CLIENT_SECRET` | Checkmarx One OAuth client secret (API key alternative) |
|
|
74
76
|
| `PNCLI_CONFIG_PATH` | Override global config file path |
|
|
75
77
|
|
|
76
78
|
## For AI Agents
|
package/copilot-instructions.md
CHANGED
|
@@ -143,7 +143,8 @@ pncli jira get-issue
|
|
|
143
143
|
pncli jira create-issue
|
|
144
144
|
--project <key> Project key
|
|
145
145
|
--type <type> Issue type (Bug, Story, Task, ...)
|
|
146
|
-
--summary <text> Issue summary
|
|
146
|
+
--summary <text> Issue summary (required, unless supplied via
|
|
147
|
+
--input-file)
|
|
147
148
|
--description <text> Issue description
|
|
148
149
|
--priority <name> Priority name
|
|
149
150
|
--assignee <accountId> Assignee account ID
|
|
@@ -154,6 +155,9 @@ pncli jira create-issue
|
|
|
154
155
|
from file (repeatable) (default: [])
|
|
155
156
|
--fields-file <path> Path to a JSON file mapping field names/IDs to their
|
|
156
157
|
Jira API values
|
|
158
|
+
--input-file <path> JSON file describing the whole issue ({ project,
|
|
159
|
+
issueType, fields: {...} }); '-' = stdin. CLI flags
|
|
160
|
+
override matching keys. See: pncli jira schema
|
|
157
161
|
|
|
158
162
|
pncli jira update-issue
|
|
159
163
|
--key <issue-key> Issue key
|
|
@@ -166,6 +170,13 @@ pncli jira update-issue
|
|
|
166
170
|
from file (repeatable) (default: [])
|
|
167
171
|
--fields-file <path> Path to a JSON file mapping field names/IDs to their
|
|
168
172
|
Jira API values
|
|
173
|
+
--input-file <path> JSON file describing fields to update ({ fields: {...}
|
|
174
|
+
}); '-' = stdin. CLI flags override matching keys.
|
|
175
|
+
See: pncli jira schema
|
|
176
|
+
|
|
177
|
+
pncli jira schema
|
|
178
|
+
--example-only Print only the runnable example JSON (no envelope) — pipeable
|
|
179
|
+
straight into --input-file
|
|
169
180
|
|
|
170
181
|
pncli jira transition-issue
|
|
171
182
|
--key <issue-key> Issue key
|
|
@@ -453,7 +464,12 @@ pncli confluence search
|
|
|
453
464
|
pncli confluence create-page
|
|
454
465
|
--space <key> Space key
|
|
455
466
|
--title <title> Page title
|
|
456
|
-
--body <html> Page body (storage format HTML
|
|
467
|
+
--body <html> Page body (storage format HTML or Markdown when
|
|
468
|
+
--markdown is set)
|
|
469
|
+
--body-file <path> Path to a file containing the page body ('-' =
|
|
470
|
+
stdin)
|
|
471
|
+
--markdown Convert body from Markdown to storage format via
|
|
472
|
+
Confluence API
|
|
457
473
|
--parent-id <id> Parent page ID (to nest under a page)
|
|
458
474
|
--representation <format> Body format: storage (default) or wiki (default:
|
|
459
475
|
"storage")
|
|
@@ -461,7 +477,12 @@ pncli confluence create-page
|
|
|
461
477
|
pncli confluence update-page
|
|
462
478
|
--id <page-id> Page ID
|
|
463
479
|
--title <title> New page title
|
|
464
|
-
--body <html> New page body (storage format HTML
|
|
480
|
+
--body <html> New page body (storage format HTML or Markdown when
|
|
481
|
+
--markdown is set)
|
|
482
|
+
--body-file <path> Path to a file containing the new page body ('-' =
|
|
483
|
+
stdin)
|
|
484
|
+
--markdown Convert body from Markdown to storage format via
|
|
485
|
+
Confluence API
|
|
465
486
|
--status <status> Page status: current (default) or draft (default:
|
|
466
487
|
"current")
|
|
467
488
|
--representation <format> Body format: storage (default) or wiki (default:
|
|
@@ -705,18 +726,26 @@ pncli ado work get
|
|
|
705
726
|
--id <n> Work item ID
|
|
706
727
|
|
|
707
728
|
pncli ado work create
|
|
708
|
-
--type <type> Work item type (e.g. Bug, Task, User Story)
|
|
709
|
-
|
|
729
|
+
--type <type> Work item type (e.g. Bug, Task, User Story) (required,
|
|
730
|
+
unless supplied via --input-file)
|
|
731
|
+
--title <title> Work item title (required, unless supplied via
|
|
732
|
+
--input-file)
|
|
710
733
|
--description <text> Description
|
|
711
734
|
--assignee <user> Assigned to (display name or email)
|
|
712
735
|
--priority <n> Priority (1-4)
|
|
713
736
|
--parent <id> Parent work item ID — creates a parent link after
|
|
714
737
|
creation
|
|
715
738
|
--field <name=value> Additional field (repeatable) (default: [])
|
|
739
|
+
--input-file <path> JSON file describing the work item ({ type, fields:
|
|
740
|
+
{...} }); '-' = stdin. CLI flags override matching keys.
|
|
741
|
+
See: pncli ado work schema
|
|
716
742
|
|
|
717
743
|
pncli ado work update
|
|
718
744
|
--id <n> Work item ID
|
|
719
745
|
--field <name=value> Field to update (repeatable) (default: [])
|
|
746
|
+
--input-file <path> JSON file describing fields to update ({ fields: {...}
|
|
747
|
+
}); '-' = stdin. CLI flags override matching keys. See:
|
|
748
|
+
pncli ado work schema
|
|
720
749
|
|
|
721
750
|
pncli ado work transition
|
|
722
751
|
--id <n> Work item ID
|
|
@@ -763,6 +792,12 @@ pncli ado work download-attachment
|
|
|
763
792
|
--attachment-id <guid> Attachment ID from work list-attachments output
|
|
764
793
|
--dir <path> Output directory (default: .pncli relative to cwd)
|
|
765
794
|
|
|
795
|
+
pncli ado work list-areas
|
|
796
|
+
--depth <n> Depth of the area tree to retrieve (default: "10")
|
|
797
|
+
|
|
798
|
+
pncli ado work list-iterations
|
|
799
|
+
--depth <n> Depth of the iteration tree to retrieve (default: "10")
|
|
800
|
+
|
|
766
801
|
pncli ado work types
|
|
767
802
|
--discover Fetch from server (always true for this command)
|
|
768
803
|
--save Save discovered types to ~/.pncli/config.json
|
|
@@ -776,6 +811,10 @@ pncli ado work fields
|
|
|
776
811
|
--discover Fetch from server (always true for this command)
|
|
777
812
|
--save Save discovered fields and aliases to ~/.pncli/config.json
|
|
778
813
|
|
|
814
|
+
pncli ado work schema
|
|
815
|
+
--example-only Print only the runnable example JSON (no envelope) — pipeable
|
|
816
|
+
straight into --input-file
|
|
817
|
+
|
|
779
818
|
pncli ado repo list
|
|
780
819
|
|
|
781
820
|
pncli ado repo get
|
|
@@ -34,8 +34,10 @@ var ENV_KEYS = {
|
|
|
34
34
|
UDEPLOY_USERNAME: "PNCLI_UDEPLOY_USERNAME",
|
|
35
35
|
UDEPLOY_PASSWORD: "PNCLI_UDEPLOY_PASSWORD",
|
|
36
36
|
CHECKMARX_BASE_URL: "PNCLI_CHECKMARX_BASE_URL",
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
CHECKMARX_TENANT_NAME: "PNCLI_CHECKMARX_TENANT_NAME",
|
|
38
|
+
CHECKMARX_API_KEY: "PNCLI_CHECKMARX_API_KEY",
|
|
39
|
+
CHECKMARX_CLIENT_ID: "PNCLI_CHECKMARX_CLIENT_ID",
|
|
40
|
+
CHECKMARX_CLIENT_SECRET: "PNCLI_CHECKMARX_CLIENT_SECRET",
|
|
39
41
|
SERVICENOW_BASE_URL: "PNCLI_SERVICENOW_BASE_URL",
|
|
40
42
|
SERVICENOW_USERNAME: "PNCLI_SERVICENOW_USERNAME",
|
|
41
43
|
SERVICENOW_PASSWORD: "PNCLI_SERVICENOW_PASSWORD",
|
|
@@ -50,6 +52,10 @@ var ENV_KEYS = {
|
|
|
50
52
|
SONATYPEIQ_PASSCODE: "PNCLI_SONATYPEIQ_PASSCODE",
|
|
51
53
|
OPENSHIFT_BASE_URL: "PNCLI_OPENSHIFT_BASE_URL",
|
|
52
54
|
OPENSHIFT_TOKEN: "PNCLI_OPENSHIFT_TOKEN",
|
|
55
|
+
DYNATRACE_BASE_URL: "PNCLI_DYNATRACE_BASE_URL",
|
|
56
|
+
DYNATRACE_API_TOKEN: "PNCLI_DYNATRACE_API_TOKEN",
|
|
57
|
+
DYNATRACE_PLATFORM_URL: "PNCLI_DYNATRACE_PLATFORM_URL",
|
|
58
|
+
DYNATRACE_PLATFORM_TOKEN: "PNCLI_DYNATRACE_PLATFORM_TOKEN",
|
|
53
59
|
CONFIG_PATH: "PNCLI_CONFIG_PATH"
|
|
54
60
|
};
|
|
55
61
|
function getGlobalConfigPath(overridePath) {
|
|
@@ -167,8 +173,10 @@ function loadConfig(opts = {}) {
|
|
|
167
173
|
},
|
|
168
174
|
checkmarx: {
|
|
169
175
|
baseUrl: process.env[ENV_KEYS.CHECKMARX_BASE_URL] ?? globalConfig.checkmarx?.baseUrl,
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
tenantName: process.env[ENV_KEYS.CHECKMARX_TENANT_NAME] ?? globalConfig.checkmarx?.tenantName,
|
|
177
|
+
apiKey: process.env[ENV_KEYS.CHECKMARX_API_KEY] ?? globalConfig.checkmarx?.apiKey,
|
|
178
|
+
clientId: process.env[ENV_KEYS.CHECKMARX_CLIENT_ID] ?? globalConfig.checkmarx?.clientId,
|
|
179
|
+
clientSecret: process.env[ENV_KEYS.CHECKMARX_CLIENT_SECRET] ?? globalConfig.checkmarx?.clientSecret
|
|
172
180
|
},
|
|
173
181
|
servicenow: {
|
|
174
182
|
baseUrl: process.env[ENV_KEYS.SERVICENOW_BASE_URL] ?? globalConfig.servicenow?.baseUrl,
|
|
@@ -192,6 +200,12 @@ function loadConfig(opts = {}) {
|
|
|
192
200
|
baseUrl: process.env[ENV_KEYS.OPENSHIFT_BASE_URL] ?? globalConfig.openshift?.baseUrl,
|
|
193
201
|
token: process.env[ENV_KEYS.OPENSHIFT_TOKEN] ?? globalConfig.openshift?.token
|
|
194
202
|
},
|
|
203
|
+
dynatrace: {
|
|
204
|
+
baseUrl: process.env[ENV_KEYS.DYNATRACE_BASE_URL] ?? globalConfig.dynatrace?.baseUrl,
|
|
205
|
+
apiToken: process.env[ENV_KEYS.DYNATRACE_API_TOKEN] ?? globalConfig.dynatrace?.apiToken,
|
|
206
|
+
platformUrl: process.env[ENV_KEYS.DYNATRACE_PLATFORM_URL] ?? globalConfig.dynatrace?.platformUrl,
|
|
207
|
+
platformToken: process.env[ENV_KEYS.DYNATRACE_PLATFORM_TOKEN] ?? globalConfig.dynatrace?.platformToken
|
|
208
|
+
},
|
|
195
209
|
defaults: mergedDefaults
|
|
196
210
|
};
|
|
197
211
|
}
|
|
@@ -208,6 +222,16 @@ function writeRepoConfig(config) {
|
|
|
208
222
|
const targetDir = repoRoot ?? process.cwd();
|
|
209
223
|
fs.writeFileSync(path.join(targetDir, ".pncli.json"), JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
210
224
|
}
|
|
225
|
+
function parseConfigValue(value) {
|
|
226
|
+
try {
|
|
227
|
+
const parsed = JSON.parse(value);
|
|
228
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
229
|
+
return parsed;
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
}
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
211
235
|
function setConfigValue(key, value, configPath) {
|
|
212
236
|
const filePath = getGlobalConfigPath(configPath);
|
|
213
237
|
const existing = loadJsonFile(filePath) ?? {};
|
|
@@ -220,7 +244,7 @@ function setConfigValue(key, value, configPath) {
|
|
|
220
244
|
}
|
|
221
245
|
current = current[part];
|
|
222
246
|
}
|
|
223
|
-
current[parts[parts.length - 1]] = value;
|
|
247
|
+
current[parts[parts.length - 1]] = parseConfigValue(value);
|
|
224
248
|
writeGlobalConfig(existing, configPath);
|
|
225
249
|
}
|
|
226
250
|
function setRepoConfigValue(key, value) {
|
|
@@ -237,7 +261,7 @@ function setRepoConfigValue(key, value) {
|
|
|
237
261
|
}
|
|
238
262
|
current = current[part];
|
|
239
263
|
}
|
|
240
|
-
current[parts[parts.length - 1]] = value;
|
|
264
|
+
current[parts[parts.length - 1]] = parseConfigValue(value);
|
|
241
265
|
writeRepoConfig(existing);
|
|
242
266
|
}
|
|
243
267
|
function maskConfig(config) {
|
|
@@ -287,7 +311,8 @@ function maskConfig(config) {
|
|
|
287
311
|
},
|
|
288
312
|
checkmarx: {
|
|
289
313
|
...config.checkmarx,
|
|
290
|
-
|
|
314
|
+
apiKey: config.checkmarx.apiKey ? "***" : void 0,
|
|
315
|
+
clientSecret: config.checkmarx.clientSecret ? "***" : void 0
|
|
291
316
|
},
|
|
292
317
|
servicenow: {
|
|
293
318
|
...config.servicenow,
|
|
@@ -306,6 +331,11 @@ function maskConfig(config) {
|
|
|
306
331
|
openshift: {
|
|
307
332
|
...config.openshift,
|
|
308
333
|
token: config.openshift.token ? "***" : void 0
|
|
334
|
+
},
|
|
335
|
+
dynatrace: {
|
|
336
|
+
...config.dynatrace,
|
|
337
|
+
apiToken: config.dynatrace.apiToken ? "***" : void 0,
|
|
338
|
+
platformToken: config.dynatrace.platformToken ? "***" : void 0
|
|
309
339
|
}
|
|
310
340
|
};
|
|
311
341
|
}
|
|
@@ -320,4 +350,4 @@ export {
|
|
|
320
350
|
setRepoConfigValue,
|
|
321
351
|
maskConfig
|
|
322
352
|
};
|
|
323
|
-
//# sourceMappingURL=chunk-
|
|
353
|
+
//# sourceMappingURL=chunk-FXY262BR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/config.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, UdeployDefaults, JenkinsDefaults } from '../types/config.js';\nimport type { CustomFieldDefinition } from '../types/jira.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 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 SDE_CONNECTION: 'PNCLI_SDE_CONNECTION',\n ADO_BASE_URL: 'PNCLI_ADO_BASE_URL',\n ADO_PAT: 'PNCLI_ADO_PAT',\n JENKINS_BASE_URL: 'PNCLI_JENKINS_BASE_URL',\n JENKINS_USERNAME: 'PNCLI_JENKINS_USERNAME',\n JENKINS_API_TOKEN: 'PNCLI_JENKINS_API_TOKEN',\n UDEPLOY_BASE_URL: 'PNCLI_UDEPLOY_BASE_URL',\n UDEPLOY_PAT: 'PNCLI_UDEPLOY_PAT',\n UDEPLOY_USERNAME: 'PNCLI_UDEPLOY_USERNAME',\n UDEPLOY_PASSWORD: 'PNCLI_UDEPLOY_PASSWORD',\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 SERVICENOW_BASE_URL: 'PNCLI_SERVICENOW_BASE_URL',\n SERVICENOW_USERNAME: 'PNCLI_SERVICENOW_USERNAME',\n SERVICENOW_PASSWORD: 'PNCLI_SERVICENOW_PASSWORD',\n SERVICENOW_API_TOKEN: 'PNCLI_SERVICENOW_API_TOKEN',\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 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 for (const f of global ?? []) map.set(f.id, f);\n for (const f of repo ?? []) map.set(f.id, f); // repo wins\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; udeploy: UdeployDefaults; 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 udeploy: { ...global?.udeploy, ...repo?.udeploy },\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] ?? globalConfig.github?.baseUrl,\n token: process.env[ENV_KEYS.GITHUB_TOKEN] ?? 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] ?? 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] ?? 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 udeploy: {\n baseUrl: process.env[ENV_KEYS.UDEPLOY_BASE_URL] ?? globalConfig.udeploy?.baseUrl,\n pat: process.env[ENV_KEYS.UDEPLOY_PAT] ?? globalConfig.udeploy?.pat,\n username: process.env[ENV_KEYS.UDEPLOY_USERNAME] ?? globalConfig.udeploy?.username,\n password: process.env[ENV_KEYS.UDEPLOY_PASSWORD] ?? globalConfig.udeploy?.password,\n },\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 servicenow: {\n baseUrl: process.env[ENV_KEYS.SERVICENOW_BASE_URL] ?? globalConfig.servicenow?.baseUrl,\n username: process.env[ENV_KEYS.SERVICENOW_USERNAME] ?? globalConfig.servicenow?.username,\n password: process.env[ENV_KEYS.SERVICENOW_PASSWORD] ?? globalConfig.servicenow?.password,\n apiToken: process.env[ENV_KEYS.SERVICENOW_API_TOKEN] ?? globalConfig.servicenow?.apiToken,\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 },\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 },\n defaults: mergedDefaults\n };\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 udeploy: {\n ...config.udeploy,\n pat: config.udeploy.pat ? '***' : undefined,\n password: config.udeploy.password ? '***' : undefined\n },\n checkmarx: {\n ...config.checkmarx,\n apiKey: config.checkmarx.apiKey ? '***' : undefined,\n clientSecret: config.checkmarx.clientSecret ? '***' : undefined\n },\n servicenow: {\n ...config.servicenow,\n password: config.servicenow.password ? '***' : undefined,\n apiToken: config.servicenow.apiToken ? '***' : 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 },\n dynatrace: {\n ...config.dynatrace,\n apiToken: config.dynatrace.apiToken ? '***' : undefined,\n platformToken: config.dynatrace.platformToken ? '***' : undefined\n }\n };\n}\n\nexport { getGlobalConfigPath, loadJsonFile };\n"],"mappings":"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","names":[]}
|
|
@@ -49,13 +49,14 @@ function isDebugEnabled() {
|
|
|
49
49
|
function setGlobalUser(user) {
|
|
50
50
|
globalUser = user;
|
|
51
51
|
}
|
|
52
|
-
function buildMeta(service, action, startTime) {
|
|
52
|
+
function buildMeta(service, action, startTime, overrides) {
|
|
53
53
|
return {
|
|
54
54
|
service,
|
|
55
55
|
action,
|
|
56
56
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
57
|
duration_ms: Date.now() - startTime,
|
|
58
|
-
user: globalUser.email ?? globalUser.userId ? globalUser : void 0
|
|
58
|
+
user: globalUser.email ?? globalUser.userId ? globalUser : void 0,
|
|
59
|
+
overrides: overrides && overrides.length > 0 ? overrides : void 0
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
function writeToFile(filePath, content) {
|
|
@@ -69,11 +70,11 @@ function writeToFile(filePath, content) {
|
|
|
69
70
|
process.exitCode = ExitCode.GENERAL_ERROR;
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
function success(data, service, action, startTime) {
|
|
73
|
+
function success(data, service, action, startTime, overrides) {
|
|
73
74
|
const envelope = {
|
|
74
75
|
ok: true,
|
|
75
76
|
data,
|
|
76
|
-
meta: buildMeta(service, action, startTime)
|
|
77
|
+
meta: buildMeta(service, action, startTime, overrides)
|
|
77
78
|
};
|
|
78
79
|
const out = (globalOptions.pretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope)) + "\n";
|
|
79
80
|
if (outputFile) {
|
|
@@ -162,30 +163,33 @@ async function buildAdoFetcher(config) {
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// src/lib/checkmarxFetch.ts
|
|
165
|
-
var CX_CLIENT_ID = "resource_owner_client";
|
|
166
|
-
var CX_CLIENT_SECRET = "014DF517-39D1-4453-B7B3-9930C563627C";
|
|
167
|
-
var CX_SCOPE = "sast_api offline_access";
|
|
168
166
|
function buildCheckmarxFetcher(config) {
|
|
169
|
-
const { baseUrl,
|
|
167
|
+
const { baseUrl, tenantName, apiKey, clientId, clientSecret } = config.checkmarx;
|
|
170
168
|
if (!baseUrl) throw new PncliError("Checkmarx baseUrl not configured. Run: pncli config init", 1);
|
|
171
|
-
if (!
|
|
172
|
-
if (!
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
169
|
+
if (!tenantName) throw new PncliError("Checkmarx tenantName not configured. Run: pncli config init", 1);
|
|
170
|
+
if (!apiKey && (!clientId || !clientSecret)) {
|
|
171
|
+
throw new PncliError(
|
|
172
|
+
"Checkmarx credentials not configured. Set apiKey or clientId and clientSecret. Run: pncli config init",
|
|
173
|
+
1
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const apiHost = new URL(baseUrl).hostname;
|
|
177
|
+
const iamHost = apiHost.replace(/(^|\.)ast\./, "$1iam.");
|
|
178
|
+
const tokenUrl = `https://${iamHost}/auth/realms/${tenantName}/protocol/openid-connect/token`;
|
|
176
179
|
let cache = null;
|
|
177
180
|
async function getToken() {
|
|
178
181
|
const now = Date.now();
|
|
179
182
|
if (cache && cache.expiresAt - now > 6e4) {
|
|
180
183
|
return cache.value;
|
|
181
184
|
}
|
|
182
|
-
const body = new URLSearchParams({
|
|
183
|
-
grant_type: "
|
|
184
|
-
client_id:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
const body = apiKey ? new URLSearchParams({
|
|
186
|
+
grant_type: "refresh_token",
|
|
187
|
+
client_id: getApiKeyClientId(apiKey),
|
|
188
|
+
refresh_token: apiKey
|
|
189
|
+
}) : new URLSearchParams({
|
|
190
|
+
grant_type: "client_credentials",
|
|
191
|
+
client_id: clientId,
|
|
192
|
+
client_secret: clientSecret
|
|
189
193
|
});
|
|
190
194
|
const response = await fetch(tokenUrl, {
|
|
191
195
|
method: "POST",
|
|
@@ -220,6 +224,17 @@ function buildCheckmarxFetcher(config) {
|
|
|
220
224
|
});
|
|
221
225
|
};
|
|
222
226
|
}
|
|
227
|
+
function getApiKeyClientId(apiKey) {
|
|
228
|
+
try {
|
|
229
|
+
const payload = apiKey.split(".")[1];
|
|
230
|
+
if (!payload) return "ast-app";
|
|
231
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
232
|
+
const claims = JSON.parse(Buffer.from(normalized, "base64").toString("utf8"));
|
|
233
|
+
return typeof claims.azp === "string" && claims.azp ? claims.azp : "ast-app";
|
|
234
|
+
} catch {
|
|
235
|
+
return "ast-app";
|
|
236
|
+
}
|
|
237
|
+
}
|
|
223
238
|
|
|
224
239
|
// src/lib/http.ts
|
|
225
240
|
var SENSITIVE_HEADERS = /* @__PURE__ */ new Set(["authorization", "api-key"]);
|
|
@@ -238,7 +253,9 @@ function redactHeaders(headers) {
|
|
|
238
253
|
);
|
|
239
254
|
}
|
|
240
255
|
function buildUrl(base, path, params) {
|
|
241
|
-
const
|
|
256
|
+
const normalizedBase = base.endsWith("/") ? base : base + "/";
|
|
257
|
+
const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
|
|
258
|
+
const url = new URL(normalizedPath, normalizedBase);
|
|
242
259
|
if (params) {
|
|
243
260
|
for (const [key, val] of Object.entries(params)) {
|
|
244
261
|
if (val !== void 0) {
|
|
@@ -555,11 +572,14 @@ Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
|
555
572
|
}
|
|
556
573
|
return request(url, init, opts.timeoutMs ?? 3e4);
|
|
557
574
|
}
|
|
558
|
-
|
|
575
|
+
confluenceToken() {
|
|
559
576
|
const { apiToken } = this.config.confluence;
|
|
560
577
|
if (!apiToken) throw new PncliError("Confluence credentials not configured. Run: pncli config init");
|
|
578
|
+
return apiToken;
|
|
579
|
+
}
|
|
580
|
+
confluenceHeaders() {
|
|
561
581
|
return {
|
|
562
|
-
"Authorization": `Bearer ${
|
|
582
|
+
"Authorization": `Bearer ${this.confluenceToken()}`,
|
|
563
583
|
"Content-Type": "application/json",
|
|
564
584
|
"Accept": "application/json",
|
|
565
585
|
"Connection": "close"
|
|
@@ -947,6 +967,28 @@ Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
|
947
967
|
}
|
|
948
968
|
return results;
|
|
949
969
|
}
|
|
970
|
+
async confluenceUpload(path, formData, opts = {}) {
|
|
971
|
+
const baseUrl = this.config.confluence.baseUrl;
|
|
972
|
+
if (!baseUrl) throw new PncliError("Confluence baseUrl not configured. Run: pncli config init");
|
|
973
|
+
const url = buildUrl(baseUrl, path);
|
|
974
|
+
const headers = {
|
|
975
|
+
"Authorization": `Bearer ${this.confluenceToken()}`,
|
|
976
|
+
"X-Atlassian-Token": "no-check",
|
|
977
|
+
"Accept": "application/json",
|
|
978
|
+
"Connection": "close"
|
|
979
|
+
};
|
|
980
|
+
if (this.dryRun) {
|
|
981
|
+
const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
|
|
982
|
+
const msg = `DRY RUN: POST ${url}
|
|
983
|
+
Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
984
|
+
Body: <multipart/form-data>
|
|
985
|
+
`;
|
|
986
|
+
fs2.writeSync(process.stderr.fd, msg);
|
|
987
|
+
process.exitCode = ExitCode.SUCCESS;
|
|
988
|
+
throw new PncliError("dry-run", 0);
|
|
989
|
+
}
|
|
990
|
+
return request(url, { method: "POST", headers, body: formData }, opts.timeoutMs ?? 6e4);
|
|
991
|
+
}
|
|
950
992
|
async confluencePaginate(fetchPage, maxTotal) {
|
|
951
993
|
const results = [];
|
|
952
994
|
let start = 0;
|
|
@@ -1125,6 +1167,52 @@ Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
|
1125
1167
|
const msg = `DRY RUN: ${init.method} ${url}
|
|
1126
1168
|
Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
1127
1169
|
` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
|
|
1170
|
+
` : "");
|
|
1171
|
+
fs2.writeSync(process.stderr.fd, msg);
|
|
1172
|
+
process.exitCode = ExitCode.SUCCESS;
|
|
1173
|
+
throw new PncliError("dry-run", 0);
|
|
1174
|
+
}
|
|
1175
|
+
return request(url, init, opts.timeoutMs ?? 3e4);
|
|
1176
|
+
}
|
|
1177
|
+
dynatraceHeaders(platform = false) {
|
|
1178
|
+
const token = platform ? this.config.dynatrace.platformToken : this.config.dynatrace.apiToken;
|
|
1179
|
+
if (!token) {
|
|
1180
|
+
throw new PncliError(
|
|
1181
|
+
`${platform ? "Dynatrace platform" : "Dynatrace"} credentials not configured. Run: pncli config init`
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
return {
|
|
1185
|
+
"Authorization": `${platform ? "Bearer" : "Api-Token"} ${token}`,
|
|
1186
|
+
"Content-Type": "application/json",
|
|
1187
|
+
"Accept": "application/json",
|
|
1188
|
+
"Connection": "close"
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
async dynatrace(path, opts = {}) {
|
|
1192
|
+
return this.dynatraceRequest(false, path, opts);
|
|
1193
|
+
}
|
|
1194
|
+
async dynatracePlatform(path, opts = {}) {
|
|
1195
|
+
return this.dynatraceRequest(true, path, opts);
|
|
1196
|
+
}
|
|
1197
|
+
async dynatraceRequest(platform, path, opts) {
|
|
1198
|
+
const baseUrl = platform ? this.config.dynatrace.platformUrl : this.config.dynatrace.baseUrl;
|
|
1199
|
+
if (!baseUrl) {
|
|
1200
|
+
throw new PncliError(
|
|
1201
|
+
`${platform ? "Dynatrace platformUrl" : "Dynatrace baseUrl"} not configured. Run: pncli config init`
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
const url = buildUrl(baseUrl, path, opts.params);
|
|
1205
|
+
const headers = this.dynatraceHeaders(platform);
|
|
1206
|
+
const init = {
|
|
1207
|
+
method: opts.method ?? "GET",
|
|
1208
|
+
headers,
|
|
1209
|
+
body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
|
|
1210
|
+
};
|
|
1211
|
+
if (this.dryRun) {
|
|
1212
|
+
const safeHeaders = { ...headers, Authorization: "[REDACTED]" };
|
|
1213
|
+
const msg = `DRY RUN: ${init.method} ${url}
|
|
1214
|
+
Headers: ${JSON.stringify(safeHeaders, null, 2)}
|
|
1215
|
+
` + (opts.body ? `Body: ${JSON.stringify(opts.body, null, 2)}
|
|
1128
1216
|
` : "");
|
|
1129
1217
|
fs2.writeSync(process.stderr.fd, msg);
|
|
1130
1218
|
process.exitCode = ExitCode.SUCCESS;
|
|
@@ -1201,4 +1289,4 @@ export {
|
|
|
1201
1289
|
HttpClient,
|
|
1202
1290
|
createHttpClient
|
|
1203
1291
|
};
|
|
1204
|
-
//# sourceMappingURL=chunk-
|
|
1292
|
+
//# sourceMappingURL=chunk-WM5NYVEO.js.map
|