@pipeline-builder/pipeline-manager 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +145 -0
  3. package/cdk.json +91 -0
  4. package/config.yml +94 -0
  5. package/dist/agent/ai.d.ts +48 -0
  6. package/dist/agent/ai.d.ts.map +1 -0
  7. package/dist/agent/ai.js +149 -0
  8. package/dist/agent/bootstrap.d.ts +39 -0
  9. package/dist/agent/bootstrap.d.ts.map +1 -0
  10. package/dist/agent/bootstrap.js +66 -0
  11. package/dist/agent/env-file.d.ts +17 -0
  12. package/dist/agent/env-file.d.ts.map +1 -0
  13. package/dist/agent/env-file.js +47 -0
  14. package/dist/agent/executor.d.ts +30 -0
  15. package/dist/agent/executor.d.ts.map +1 -0
  16. package/dist/agent/executor.js +60 -0
  17. package/dist/agent/health.d.ts +43 -0
  18. package/dist/agent/health.d.ts.map +1 -0
  19. package/dist/agent/health.js +109 -0
  20. package/dist/agent/ports.d.ts +26 -0
  21. package/dist/agent/ports.d.ts.map +1 -0
  22. package/dist/agent/ports.js +132 -0
  23. package/dist/agent/post-steps.d.ts +61 -0
  24. package/dist/agent/post-steps.d.ts.map +1 -0
  25. package/dist/agent/post-steps.js +131 -0
  26. package/dist/agent/prereqs.d.ts +26 -0
  27. package/dist/agent/prereqs.d.ts.map +1 -0
  28. package/dist/agent/prereqs.js +134 -0
  29. package/dist/agent/targets.d.ts +128 -0
  30. package/dist/agent/targets.d.ts.map +1 -0
  31. package/dist/agent/targets.js +265 -0
  32. package/dist/agent/tools.d.ts +13 -0
  33. package/dist/agent/tools.d.ts.map +1 -0
  34. package/dist/agent/tools.js +75 -0
  35. package/dist/agent/troubleshoot.d.ts +30 -0
  36. package/dist/agent/troubleshoot.d.ts.map +1 -0
  37. package/dist/agent/troubleshoot.js +87 -0
  38. package/dist/boilerplate.d.ts +3 -0
  39. package/dist/boilerplate.d.ts.map +1 -0
  40. package/dist/boilerplate.js +54 -0
  41. package/dist/cdk.json +91 -0
  42. package/dist/cli.d.ts +62 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +463 -0
  45. package/dist/commands/audit-stacks.d.ts +24 -0
  46. package/dist/commands/audit-stacks.d.ts.map +1 -0
  47. package/dist/commands/audit-stacks.js +182 -0
  48. package/dist/commands/audit-tokens.d.ts +21 -0
  49. package/dist/commands/audit-tokens.d.ts.map +1 -0
  50. package/dist/commands/audit-tokens.js +153 -0
  51. package/dist/commands/bootstrap.d.ts +11 -0
  52. package/dist/commands/bootstrap.d.ts.map +1 -0
  53. package/dist/commands/bootstrap.js +159 -0
  54. package/dist/commands/create-pat.d.ts +27 -0
  55. package/dist/commands/create-pat.d.ts.map +1 -0
  56. package/dist/commands/create-pat.js +194 -0
  57. package/dist/commands/create-pipeline.d.ts +12 -0
  58. package/dist/commands/create-pipeline.d.ts.map +1 -0
  59. package/dist/commands/create-pipeline.js +315 -0
  60. package/dist/commands/deploy.d.ts +15 -0
  61. package/dist/commands/deploy.d.ts.map +1 -0
  62. package/dist/commands/deploy.js +157 -0
  63. package/dist/commands/entity-get.d.ts +51 -0
  64. package/dist/commands/entity-get.d.ts.map +1 -0
  65. package/dist/commands/entity-get.js +69 -0
  66. package/dist/commands/entity-list.d.ts +39 -0
  67. package/dist/commands/entity-list.d.ts.map +1 -0
  68. package/dist/commands/entity-list.js +88 -0
  69. package/dist/commands/get-pipeline.d.ts +13 -0
  70. package/dist/commands/get-pipeline.d.ts.map +1 -0
  71. package/dist/commands/get-pipeline.js +49 -0
  72. package/dist/commands/get-plugin.d.ts +13 -0
  73. package/dist/commands/get-plugin.d.ts.map +1 -0
  74. package/dist/commands/get-plugin.js +51 -0
  75. package/dist/commands/instantiate-template.d.ts +20 -0
  76. package/dist/commands/instantiate-template.d.ts.map +1 -0
  77. package/dist/commands/instantiate-template.js +274 -0
  78. package/dist/commands/list-pipelines.d.ts +20 -0
  79. package/dist/commands/list-pipelines.d.ts.map +1 -0
  80. package/dist/commands/list-pipelines.js +99 -0
  81. package/dist/commands/list-plugins.d.ts +20 -0
  82. package/dist/commands/list-plugins.d.ts.map +1 -0
  83. package/dist/commands/list-plugins.js +92 -0
  84. package/dist/commands/login.d.ts +21 -0
  85. package/dist/commands/login.d.ts.map +1 -0
  86. package/dist/commands/login.js +174 -0
  87. package/dist/commands/new-plugin.d.ts +12 -0
  88. package/dist/commands/new-plugin.d.ts.map +1 -0
  89. package/dist/commands/new-plugin.js +129 -0
  90. package/dist/commands/org-export.d.ts +25 -0
  91. package/dist/commands/org-export.d.ts.map +1 -0
  92. package/dist/commands/org-export.js +100 -0
  93. package/dist/commands/provision.d.ts +122 -0
  94. package/dist/commands/provision.d.ts.map +1 -0
  95. package/dist/commands/provision.js +867 -0
  96. package/dist/commands/redrive-events.d.ts +24 -0
  97. package/dist/commands/redrive-events.d.ts.map +1 -0
  98. package/dist/commands/redrive-events.js +127 -0
  99. package/dist/commands/register.d.ts +38 -0
  100. package/dist/commands/register.d.ts.map +1 -0
  101. package/dist/commands/register.js +160 -0
  102. package/dist/commands/setup-events.d.ts +15 -0
  103. package/dist/commands/setup-events.d.ts.map +1 -0
  104. package/dist/commands/setup-events.js +168 -0
  105. package/dist/commands/status.d.ts +11 -0
  106. package/dist/commands/status.d.ts.map +1 -0
  107. package/dist/commands/status.js +81 -0
  108. package/dist/commands/store-token.d.ts +26 -0
  109. package/dist/commands/store-token.d.ts.map +1 -0
  110. package/dist/commands/store-token.js +305 -0
  111. package/dist/commands/synth.d.ts +21 -0
  112. package/dist/commands/synth.d.ts.map +1 -0
  113. package/dist/commands/synth.js +158 -0
  114. package/dist/commands/upload-plugin.d.ts +21 -0
  115. package/dist/commands/upload-plugin.d.ts.map +1 -0
  116. package/dist/commands/upload-plugin.js +275 -0
  117. package/dist/commands/validate-plugin.d.ts +12 -0
  118. package/dist/commands/validate-plugin.d.ts.map +1 -0
  119. package/dist/commands/validate-plugin.js +175 -0
  120. package/dist/commands/validate-templates.d.ts +11 -0
  121. package/dist/commands/validate-templates.d.ts.map +1 -0
  122. package/dist/commands/validate-templates.js +116 -0
  123. package/dist/commands/version.d.ts +12 -0
  124. package/dist/commands/version.d.ts.map +1 -0
  125. package/dist/commands/version.js +216 -0
  126. package/dist/config/cli.constants.d.ts +116 -0
  127. package/dist/config/cli.constants.d.ts.map +1 -0
  128. package/dist/config/cli.constants.js +194 -0
  129. package/dist/config.yml +94 -0
  130. package/dist/lambda/token-renew-handler.d.ts +2 -0
  131. package/dist/lambda/token-renew-handler.d.ts.map +1 -0
  132. package/dist/lambda/token-renew-handler.js +125 -0
  133. package/dist/templates/events-stack.json +174 -0
  134. package/dist/templates/token-renew-stack.json +122 -0
  135. package/dist/types/config.d.ts +53 -0
  136. package/dist/types/config.d.ts.map +1 -0
  137. package/dist/types/config.js +4 -0
  138. package/dist/types/error.d.ts +61 -0
  139. package/dist/types/error.d.ts.map +1 -0
  140. package/dist/types/error.js +35 -0
  141. package/dist/types/index.d.ts +9 -0
  142. package/dist/types/index.d.ts.map +1 -0
  143. package/dist/types/index.js +11 -0
  144. package/dist/types/pipeline-template.d.ts +48 -0
  145. package/dist/types/pipeline-template.d.ts.map +1 -0
  146. package/dist/types/pipeline-template.js +4 -0
  147. package/dist/types/pipeline.d.ts +121 -0
  148. package/dist/types/pipeline.d.ts.map +1 -0
  149. package/dist/types/pipeline.js +4 -0
  150. package/dist/types/plugin.d.ts +135 -0
  151. package/dist/types/plugin.d.ts.map +1 -0
  152. package/dist/types/plugin.js +4 -0
  153. package/dist/utils/api-client.d.ts +26 -0
  154. package/dist/utils/api-client.d.ts.map +1 -0
  155. package/dist/utils/api-client.js +151 -0
  156. package/dist/utils/audit-log.d.ts +8 -0
  157. package/dist/utils/audit-log.d.ts.map +1 -0
  158. package/dist/utils/audit-log.js +57 -0
  159. package/dist/utils/auth-guard.d.ts +20 -0
  160. package/dist/utils/auth-guard.d.ts.map +1 -0
  161. package/dist/utils/auth-guard.js +22 -0
  162. package/dist/utils/auth-utils.d.ts +68 -0
  163. package/dist/utils/auth-utils.d.ts.map +1 -0
  164. package/dist/utils/auth-utils.js +77 -0
  165. package/dist/utils/aws-env.d.ts +21 -0
  166. package/dist/utils/aws-env.d.ts.map +1 -0
  167. package/dist/utils/aws-env.js +34 -0
  168. package/dist/utils/aws-secrets.d.ts +48 -0
  169. package/dist/utils/aws-secrets.d.ts.map +1 -0
  170. package/dist/utils/aws-secrets.js +115 -0
  171. package/dist/utils/banner.d.ts +19 -0
  172. package/dist/utils/banner.d.ts.map +1 -0
  173. package/dist/utils/banner.js +52 -0
  174. package/dist/utils/cdk-utils.d.ts +74 -0
  175. package/dist/utils/cdk-utils.d.ts.map +1 -0
  176. package/dist/utils/cdk-utils.js +152 -0
  177. package/dist/utils/command-utils.d.ts +75 -0
  178. package/dist/utils/command-utils.d.ts.map +1 -0
  179. package/dist/utils/command-utils.js +155 -0
  180. package/dist/utils/config-loader.d.ts +33 -0
  181. package/dist/utils/config-loader.d.ts.map +1 -0
  182. package/dist/utils/config-loader.js +154 -0
  183. package/dist/utils/cron.d.ts +28 -0
  184. package/dist/utils/cron.d.ts.map +1 -0
  185. package/dist/utils/cron.js +119 -0
  186. package/dist/utils/deploy-runner.d.ts +38 -0
  187. package/dist/utils/deploy-runner.d.ts.map +1 -0
  188. package/dist/utils/deploy-runner.js +112 -0
  189. package/dist/utils/error-handler.d.ts +29 -0
  190. package/dist/utils/error-handler.d.ts.map +1 -0
  191. package/dist/utils/error-handler.js +302 -0
  192. package/dist/utils/list-command-utils.d.ts +23 -0
  193. package/dist/utils/list-command-utils.d.ts.map +1 -0
  194. package/dist/utils/list-command-utils.js +57 -0
  195. package/dist/utils/output-utils.d.ts +40 -0
  196. package/dist/utils/output-utils.d.ts.map +1 -0
  197. package/dist/utils/output-utils.js +250 -0
  198. package/dist/utils/pipeline-config.d.ts +33 -0
  199. package/dist/utils/pipeline-config.d.ts.map +1 -0
  200. package/dist/utils/pipeline-config.js +55 -0
  201. package/dist/utils/platform-secret.d.ts +27 -0
  202. package/dist/utils/platform-secret.d.ts.map +1 -0
  203. package/dist/utils/platform-secret.js +92 -0
  204. package/dist/utils/plugin-resolver.d.ts +17 -0
  205. package/dist/utils/plugin-resolver.d.ts.map +1 -0
  206. package/dist/utils/plugin-resolver.js +101 -0
  207. package/dist/utils/preflight.d.ts +26 -0
  208. package/dist/utils/preflight.d.ts.map +1 -0
  209. package/dist/utils/preflight.js +59 -0
  210. package/dist/utils/rate-limiter.d.ts +15 -0
  211. package/dist/utils/rate-limiter.d.ts.map +1 -0
  212. package/dist/utils/rate-limiter.js +164 -0
  213. package/dist/utils/registry.d.ts +86 -0
  214. package/dist/utils/registry.d.ts.map +1 -0
  215. package/dist/utils/registry.js +140 -0
  216. package/dist/utils/response-utils.d.ts +21 -0
  217. package/dist/utils/response-utils.d.ts.map +1 -0
  218. package/dist/utils/response-utils.js +70 -0
  219. package/dist/utils/tls.d.ts +52 -0
  220. package/dist/utils/tls.d.ts.map +1 -0
  221. package/dist/utils/tls.js +88 -0
  222. package/package.json +181 -0
@@ -0,0 +1,140 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { promises as fs } from 'fs';
4
+ import { homedir } from 'os';
5
+ import { join } from 'path';
6
+ import { parsePlatformBaseUrl } from '@pipeline-builder/pipeline-core';
7
+ import { resolveAwsRegion } from './aws-env.js';
8
+ import { printInfo } from './output-utils.js';
9
+ import { defaultPipelineName } from '../config/cli.constants.js';
10
+ /**
11
+ * Helpers for registering a deployed pipeline ARN with the platform.
12
+ *
13
+ * The registry table maps deployed CodePipeline ARNs back to pipeline records
14
+ * and orgs. It's how the dashboard's "Deployed pipelines" panel and the event
15
+ * reporting Lambda resolve incoming events to a pipeline definition.
16
+ *
17
+ * Two failure modes are handled here:
18
+ *
19
+ * 1. Platform unreachable at deploy time. The CDK stack lands in AWS but the
20
+ * registry POST fails. Without retry the deploy command would have to
21
+ * re-run cdk-deploy (slow, sometimes blocked by stack state) just to
22
+ * record the ARN. Instead, we write a pending intent to a local file;
23
+ * `pipeline-manager pipeline register` drains them.
24
+ *
25
+ * 2. User explicitly invokes `pipeline-manager pipeline register --id <pipelineId>`
26
+ * after a successful deploy that didn't register. Same path: rebuilds
27
+ * the ARN from STS, POSTs to the platform.
28
+ *
29
+ * Pending intents store ONLY the registration payload — never tokens or URLs.
30
+ * Auth is supplied by whichever command drains the intent (deploy or register),
31
+ * so a stale intent file is never an authentication risk.
32
+ */
33
+ /**
34
+ * Platform-sourced registry pull target for the CDK synth, derived from the
35
+ * platform base URL the CLI deploys against (the same host that serves the
36
+ * registry `/v2/` data path via nginx). Reuses pipeline-core's
37
+ * `parsePlatformBaseUrl` so host/port parsing stays identical on both sides.
38
+ * Returns `undefined` for an unparseable/absent URL. (Only the pull host/port
39
+ * are returned — `registry.http` describes the in-cluster push hop, which the
40
+ * synth never reads, so deriving it from the public URL would be misleading.)
41
+ */
42
+ export function registryOverrideFromBaseUrl(baseUrl) {
43
+ const parsed = parsePlatformBaseUrl(baseUrl);
44
+ return parsed ? { pullHost: parsed.host, pullPort: parsed.port } : undefined;
45
+ }
46
+ /**
47
+ * Bake the platform-derived registry pull target into the synth props
48
+ * (`BuilderProps.registry`) so the CodeBuild image URIs use a host AWS CodeBuild
49
+ * can resolve — not the in-cluster `registry:5000` default. Shared by the
50
+ * `deploy` and `synth` commands.
51
+ *
52
+ * An explicit `IMAGE_REGISTRY_PULL_HOST` in the synth env takes precedence, so
53
+ * this is a no-op when it is set (the synth's `loadRegistryConfig` already
54
+ * honors it). Also a no-op for an unparseable/absent base URL.
55
+ */
56
+ export function bakePlatformRegistry(props, baseUrl) {
57
+ if (process.env.IMAGE_REGISTRY_PULL_HOST)
58
+ return; // explicit env wins
59
+ const override = registryOverrideFromBaseUrl(baseUrl);
60
+ if (!override)
61
+ return;
62
+ props.registry = override;
63
+ printInfo('Registry pull target', { host: override.pullHost, port: override.pullPort });
64
+ }
65
+ /** Where pending registration intents are persisted between CLI invocations. */
66
+ const PENDING_INTENTS_DIR = join(homedir(), '.pipeline-manager', 'pending-registrations');
67
+ /**
68
+ * Build a RegistryPayload from the platform's pipeline metadata. No AWS calls
69
+ * and no ARN/account: the events Lambda attributes events via the pipeline's
70
+ * `pb.pipeline-id` tag (= pipelineId), so the registry only needs the stable
71
+ * pipelineId + display metadata.
72
+ */
73
+ export async function buildRegistryPayload(pipeline, regionOverride) {
74
+ const region = resolveAwsRegion(regionOverride);
75
+ const pipelineName = pipeline.pipelineName
76
+ || defaultPipelineName(pipeline.organization, pipeline.project);
77
+ const stackName = `${pipeline.project}-${pipeline.organization}`.toLowerCase();
78
+ return {
79
+ pipelineId: pipeline.id,
80
+ orgId: pipeline.orgId,
81
+ pipelineName,
82
+ region,
83
+ project: pipeline.project,
84
+ organization: pipeline.organization,
85
+ stackName,
86
+ };
87
+ }
88
+ /**
89
+ * Persist a registration intent for later retry.
90
+ *
91
+ * Intent files are keyed by pipelineId so re-running deploy on the same
92
+ * pipeline overwrites rather than accumulates. We deliberately store the
93
+ * payload plain (not the full pipeline doc, not auth) so a stale file is
94
+ * safe to leave around indefinitely.
95
+ */
96
+ export async function writePendingIntent(payload) {
97
+ await fs.mkdir(PENDING_INTENTS_DIR, { recursive: true });
98
+ const path = join(PENDING_INTENTS_DIR, `${payload.pipelineId}.json`);
99
+ await fs.writeFile(path, JSON.stringify(payload, null, 2), 'utf8');
100
+ return path;
101
+ }
102
+ /** Remove a pending intent after a successful drain. */
103
+ export async function clearPendingIntent(pipelineId) {
104
+ const path = join(PENDING_INTENTS_DIR, `${pipelineId}.json`);
105
+ try {
106
+ await fs.unlink(path);
107
+ }
108
+ catch (err) {
109
+ // ENOENT is fine — already cleared. Anything else is a real problem.
110
+ if (err.code !== 'ENOENT')
111
+ throw err;
112
+ }
113
+ }
114
+ /** Read all pending intents currently on disk. Empty array if dir doesn't exist. */
115
+ export async function readPendingIntents() {
116
+ let entries;
117
+ try {
118
+ entries = await fs.readdir(PENDING_INTENTS_DIR);
119
+ }
120
+ catch (err) {
121
+ if (err.code === 'ENOENT')
122
+ return [];
123
+ throw err;
124
+ }
125
+ const intents = [];
126
+ for (const file of entries) {
127
+ if (!file.endsWith('.json'))
128
+ continue;
129
+ try {
130
+ const text = await fs.readFile(join(PENDING_INTENTS_DIR, file), 'utf8');
131
+ intents.push(JSON.parse(text));
132
+ }
133
+ catch {
134
+ // Skip unreadable / malformed files — they'll need manual cleanup but
135
+ // shouldn't block valid intents from draining.
136
+ }
137
+ }
138
+ return intents;
139
+ }
140
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQzdCLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDNUIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdkUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVIOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLDJCQUEyQixDQUN6QyxPQUEyQjtJQUUzQixNQUFNLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDL0UsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxLQUE4QixFQUFFLE9BQTJCO0lBQzlGLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0I7UUFBRSxPQUFPLENBQUMsb0JBQW9CO0lBQ3RFLE1BQU0sUUFBUSxHQUFHLDJCQUEyQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTztJQUN0QixLQUFLLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMxQixTQUFTLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7QUFDMUYsQ0FBQztBQXNCRCxnRkFBZ0Y7QUFDaEYsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztBQUUxRjs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsb0JBQW9CLENBQ3hDLFFBQTZCLEVBQzdCLGNBQXVCO0lBRXZCLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBRWhELE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxZQUFZO1dBQ3JDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sU0FBUyxHQUFHLEdBQUcsUUFBUSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsWUFBWSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFL0UsT0FBTztRQUNMLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRTtRQUN2QixLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUs7UUFDckIsWUFBWTtRQUNaLE1BQU07UUFDTixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87UUFDekIsWUFBWSxFQUFFLFFBQVEsQ0FBQyxZQUFZO1FBQ25DLFNBQVM7S0FDVixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGtCQUFrQixDQUFDLE9BQXdCO0lBQy9ELE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLE9BQU8sQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ25FLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVELHdEQUF3RDtBQUN4RCxNQUFNLENBQUMsS0FBSyxVQUFVLGtCQUFrQixDQUFDLFVBQWtCO0lBQ3pELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLFVBQVUsT0FBTyxDQUFDLENBQUM7SUFDN0QsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hCLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IscUVBQXFFO1FBQ3JFLElBQUssR0FBNkIsQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLE1BQU0sR0FBRyxDQUFDO0lBQ2xFLENBQUM7QUFDSCxDQUFDO0FBRUQsb0ZBQW9GO0FBQ3BGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsa0JBQWtCO0lBQ3RDLElBQUksT0FBaUIsQ0FBQztJQUN0QixJQUFJLENBQUM7UUFDSCxPQUFPLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixJQUFLLEdBQTZCLENBQUMsSUFBSSxLQUFLLFFBQVE7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUNoRSxNQUFNLEdBQUcsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBc0IsRUFBRSxDQUFDO0lBQ3RDLEtBQUssTUFBTSxJQUFJLElBQUksT0FBTyxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO1lBQUUsU0FBUztRQUN0QyxJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQW9CLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1Asc0VBQXNFO1lBQ3RFLCtDQUErQztRQUNqRCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSAnb3MnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcGFyc2VQbGF0Zm9ybUJhc2VVcmwgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCB7IHJlc29sdmVBd3NSZWdpb24gfSBmcm9tICcuL2F3cy1lbnYuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvIH0gZnJvbSAnLi9vdXRwdXQtdXRpbHMuanMnO1xuaW1wb3J0IHsgZGVmYXVsdFBpcGVsaW5lTmFtZSB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcblxuLyoqXG4gKiBIZWxwZXJzIGZvciByZWdpc3RlcmluZyBhIGRlcGxveWVkIHBpcGVsaW5lIEFSTiB3aXRoIHRoZSBwbGF0Zm9ybS5cbiAqXG4gKiBUaGUgcmVnaXN0cnkgdGFibGUgbWFwcyBkZXBsb3llZCBDb2RlUGlwZWxpbmUgQVJOcyBiYWNrIHRvIHBpcGVsaW5lIHJlY29yZHNcbiAqIGFuZCBvcmdzLiBJdCdzIGhvdyB0aGUgZGFzaGJvYXJkJ3MgXCJEZXBsb3llZCBwaXBlbGluZXNcIiBwYW5lbCBhbmQgdGhlIGV2ZW50XG4gKiByZXBvcnRpbmcgTGFtYmRhIHJlc29sdmUgaW5jb21pbmcgZXZlbnRzIHRvIGEgcGlwZWxpbmUgZGVmaW5pdGlvbi5cbiAqXG4gKiBUd28gZmFpbHVyZSBtb2RlcyBhcmUgaGFuZGxlZCBoZXJlOlxuICpcbiAqICAgMS4gUGxhdGZvcm0gdW5yZWFjaGFibGUgYXQgZGVwbG95IHRpbWUuIFRoZSBDREsgc3RhY2sgbGFuZHMgaW4gQVdTIGJ1dCB0aGVcbiAqICAgICAgcmVnaXN0cnkgUE9TVCBmYWlscy4gV2l0aG91dCByZXRyeSB0aGUgZGVwbG95IGNvbW1hbmQgd291bGQgaGF2ZSB0b1xuICogICAgICByZS1ydW4gY2RrLWRlcGxveSAoc2xvdywgc29tZXRpbWVzIGJsb2NrZWQgYnkgc3RhY2sgc3RhdGUpIGp1c3QgdG9cbiAqICAgICAgcmVjb3JkIHRoZSBBUk4uIEluc3RlYWQsIHdlIHdyaXRlIGEgcGVuZGluZyBpbnRlbnQgdG8gYSBsb2NhbCBmaWxlO1xuICogICAgICBgcGlwZWxpbmUtbWFuYWdlciBwaXBlbGluZSByZWdpc3RlcmAgZHJhaW5zIHRoZW0uXG4gKlxuICogICAyLiBVc2VyIGV4cGxpY2l0bHkgaW52b2tlcyBgcGlwZWxpbmUtbWFuYWdlciBwaXBlbGluZSByZWdpc3RlciAtLWlkIDxwaXBlbGluZUlkPmBcbiAqICAgICAgYWZ0ZXIgYSBzdWNjZXNzZnVsIGRlcGxveSB0aGF0IGRpZG4ndCByZWdpc3Rlci4gU2FtZSBwYXRoOiByZWJ1aWxkc1xuICogICAgICB0aGUgQVJOIGZyb20gU1RTLCBQT1NUcyB0byB0aGUgcGxhdGZvcm0uXG4gKlxuICogUGVuZGluZyBpbnRlbnRzIHN0b3JlIE9OTFkgdGhlIHJlZ2lzdHJhdGlvbiBwYXlsb2FkIOKAlCBuZXZlciB0b2tlbnMgb3IgVVJMcy5cbiAqIEF1dGggaXMgc3VwcGxpZWQgYnkgd2hpY2hldmVyIGNvbW1hbmQgZHJhaW5zIHRoZSBpbnRlbnQgKGRlcGxveSBvciByZWdpc3RlciksXG4gKiBzbyBhIHN0YWxlIGludGVudCBmaWxlIGlzIG5ldmVyIGFuIGF1dGhlbnRpY2F0aW9uIHJpc2suXG4gKi9cblxuLyoqXG4gKiBQbGF0Zm9ybS1zb3VyY2VkIHJlZ2lzdHJ5IHB1bGwgdGFyZ2V0IGZvciB0aGUgQ0RLIHN5bnRoLCBkZXJpdmVkIGZyb20gdGhlXG4gKiBwbGF0Zm9ybSBiYXNlIFVSTCB0aGUgQ0xJIGRlcGxveXMgYWdhaW5zdCAodGhlIHNhbWUgaG9zdCB0aGF0IHNlcnZlcyB0aGVcbiAqIHJlZ2lzdHJ5IGAvdjIvYCBkYXRhIHBhdGggdmlhIG5naW54KS4gUmV1c2VzIHBpcGVsaW5lLWNvcmUnc1xuICogYHBhcnNlUGxhdGZvcm1CYXNlVXJsYCBzbyBob3N0L3BvcnQgcGFyc2luZyBzdGF5cyBpZGVudGljYWwgb24gYm90aCBzaWRlcy5cbiAqIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yIGFuIHVucGFyc2VhYmxlL2Fic2VudCBVUkwuIChPbmx5IHRoZSBwdWxsIGhvc3QvcG9ydFxuICogYXJlIHJldHVybmVkIOKAlCBgcmVnaXN0cnkuaHR0cGAgZGVzY3JpYmVzIHRoZSBpbi1jbHVzdGVyIHB1c2ggaG9wLCB3aGljaCB0aGVcbiAqIHN5bnRoIG5ldmVyIHJlYWRzLCBzbyBkZXJpdmluZyBpdCBmcm9tIHRoZSBwdWJsaWMgVVJMIHdvdWxkIGJlIG1pc2xlYWRpbmcuKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0cnlPdmVycmlkZUZyb21CYXNlVXJsKFxuICBiYXNlVXJsOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiB7IHB1bGxIb3N0OiBzdHJpbmc7IHB1bGxQb3J0OiBudW1iZXIgfSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHBhcnNlZCA9IHBhcnNlUGxhdGZvcm1CYXNlVXJsKGJhc2VVcmwpO1xuICByZXR1cm4gcGFyc2VkID8geyBwdWxsSG9zdDogcGFyc2VkLmhvc3QsIHB1bGxQb3J0OiBwYXJzZWQucG9ydCB9IDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEJha2UgdGhlIHBsYXRmb3JtLWRlcml2ZWQgcmVnaXN0cnkgcHVsbCB0YXJnZXQgaW50byB0aGUgc3ludGggcHJvcHNcbiAqIChgQnVpbGRlclByb3BzLnJlZ2lzdHJ5YCkgc28gdGhlIENvZGVCdWlsZCBpbWFnZSBVUklzIHVzZSBhIGhvc3QgQVdTIENvZGVCdWlsZFxuICogY2FuIHJlc29sdmUg4oCUIG5vdCB0aGUgaW4tY2x1c3RlciBgcmVnaXN0cnk6NTAwMGAgZGVmYXVsdC4gU2hhcmVkIGJ5IHRoZVxuICogYGRlcGxveWAgYW5kIGBzeW50aGAgY29tbWFuZHMuXG4gKlxuICogQW4gZXhwbGljaXQgYElNQUdFX1JFR0lTVFJZX1BVTExfSE9TVGAgaW4gdGhlIHN5bnRoIGVudiB0YWtlcyBwcmVjZWRlbmNlLCBzb1xuICogdGhpcyBpcyBhIG5vLW9wIHdoZW4gaXQgaXMgc2V0ICh0aGUgc3ludGgncyBgbG9hZFJlZ2lzdHJ5Q29uZmlnYCBhbHJlYWR5XG4gKiBob25vcnMgaXQpLiBBbHNvIGEgbm8tb3AgZm9yIGFuIHVucGFyc2VhYmxlL2Fic2VudCBiYXNlIFVSTC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJha2VQbGF0Zm9ybVJlZ2lzdHJ5KHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgYmFzZVVybDogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gIGlmIChwcm9jZXNzLmVudi5JTUFHRV9SRUdJU1RSWV9QVUxMX0hPU1QpIHJldHVybjsgLy8gZXhwbGljaXQgZW52IHdpbnNcbiAgY29uc3Qgb3ZlcnJpZGUgPSByZWdpc3RyeU92ZXJyaWRlRnJvbUJhc2VVcmwoYmFzZVVybCk7XG4gIGlmICghb3ZlcnJpZGUpIHJldHVybjtcbiAgcHJvcHMucmVnaXN0cnkgPSBvdmVycmlkZTtcbiAgcHJpbnRJbmZvKCdSZWdpc3RyeSBwdWxsIHRhcmdldCcsIHsgaG9zdDogb3ZlcnJpZGUucHVsbEhvc3QsIHBvcnQ6IG92ZXJyaWRlLnB1bGxQb3J0IH0pO1xufVxuXG4vKiogU2hhcGUgb2YgdGhlIGJvZHkgUE9TVGVkIHRvIC9hcGkvcGlwZWxpbmVzL3JlZ2lzdHJ5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpc3RyeVBheWxvYWQge1xuICBwaXBlbGluZUlkOiBzdHJpbmc7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHBpcGVsaW5lTmFtZTogc3RyaW5nO1xuICByZWdpb246IHN0cmluZztcbiAgcHJvamVjdDogc3RyaW5nO1xuICBvcmdhbml6YXRpb246IHN0cmluZztcbiAgc3RhY2tOYW1lOiBzdHJpbmc7XG59XG5cbi8qKiBQaXBlbGluZSBmaWVsZHMgbmVlZGVkIHRvIGNvbnN0cnVjdCBhIFJlZ2lzdHJ5UGF5bG9hZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGlwZWxpbmVGb3JSZWdpc3RyeSB7XG4gIGlkOiBzdHJpbmc7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHBpcGVsaW5lTmFtZT86IHN0cmluZztcbiAgcHJvamVjdDogc3RyaW5nO1xuICBvcmdhbml6YXRpb246IHN0cmluZztcbn1cblxuLyoqIFdoZXJlIHBlbmRpbmcgcmVnaXN0cmF0aW9uIGludGVudHMgYXJlIHBlcnNpc3RlZCBiZXR3ZWVuIENMSSBpbnZvY2F0aW9ucy4gKi9cbmNvbnN0IFBFTkRJTkdfSU5URU5UU19ESVIgPSBqb2luKGhvbWVkaXIoKSwgJy5waXBlbGluZS1tYW5hZ2VyJywgJ3BlbmRpbmctcmVnaXN0cmF0aW9ucycpO1xuXG4vKipcbiAqIEJ1aWxkIGEgUmVnaXN0cnlQYXlsb2FkIGZyb20gdGhlIHBsYXRmb3JtJ3MgcGlwZWxpbmUgbWV0YWRhdGEuIE5vIEFXUyBjYWxsc1xuICogYW5kIG5vIEFSTi9hY2NvdW50OiB0aGUgZXZlbnRzIExhbWJkYSBhdHRyaWJ1dGVzIGV2ZW50cyB2aWEgdGhlIHBpcGVsaW5lJ3NcbiAqIGBwYi5waXBlbGluZS1pZGAgdGFnICg9IHBpcGVsaW5lSWQpLCBzbyB0aGUgcmVnaXN0cnkgb25seSBuZWVkcyB0aGUgc3RhYmxlXG4gKiBwaXBlbGluZUlkICsgZGlzcGxheSBtZXRhZGF0YS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkUmVnaXN0cnlQYXlsb2FkKFxuICBwaXBlbGluZTogUGlwZWxpbmVGb3JSZWdpc3RyeSxcbiAgcmVnaW9uT3ZlcnJpZGU/OiBzdHJpbmcsXG4pOiBQcm9taXNlPFJlZ2lzdHJ5UGF5bG9hZD4ge1xuICBjb25zdCByZWdpb24gPSByZXNvbHZlQXdzUmVnaW9uKHJlZ2lvbk92ZXJyaWRlKTtcblxuICBjb25zdCBwaXBlbGluZU5hbWUgPSBwaXBlbGluZS5waXBlbGluZU5hbWVcbiAgICB8fCBkZWZhdWx0UGlwZWxpbmVOYW1lKHBpcGVsaW5lLm9yZ2FuaXphdGlvbiwgcGlwZWxpbmUucHJvamVjdCk7XG4gIGNvbnN0IHN0YWNrTmFtZSA9IGAke3BpcGVsaW5lLnByb2plY3R9LSR7cGlwZWxpbmUub3JnYW5pemF0aW9ufWAudG9Mb3dlckNhc2UoKTtcblxuICByZXR1cm4ge1xuICAgIHBpcGVsaW5lSWQ6IHBpcGVsaW5lLmlkLFxuICAgIG9yZ0lkOiBwaXBlbGluZS5vcmdJZCxcbiAgICBwaXBlbGluZU5hbWUsXG4gICAgcmVnaW9uLFxuICAgIHByb2plY3Q6IHBpcGVsaW5lLnByb2plY3QsXG4gICAgb3JnYW5pemF0aW9uOiBwaXBlbGluZS5vcmdhbml6YXRpb24sXG4gICAgc3RhY2tOYW1lLFxuICB9O1xufVxuXG4vKipcbiAqIFBlcnNpc3QgYSByZWdpc3RyYXRpb24gaW50ZW50IGZvciBsYXRlciByZXRyeS5cbiAqXG4gKiBJbnRlbnQgZmlsZXMgYXJlIGtleWVkIGJ5IHBpcGVsaW5lSWQgc28gcmUtcnVubmluZyBkZXBsb3kgb24gdGhlIHNhbWVcbiAqIHBpcGVsaW5lIG92ZXJ3cml0ZXMgcmF0aGVyIHRoYW4gYWNjdW11bGF0ZXMuIFdlIGRlbGliZXJhdGVseSBzdG9yZSB0aGVcbiAqIHBheWxvYWQgcGxhaW4gKG5vdCB0aGUgZnVsbCBwaXBlbGluZSBkb2MsIG5vdCBhdXRoKSBzbyBhIHN0YWxlIGZpbGUgaXNcbiAqIHNhZmUgdG8gbGVhdmUgYXJvdW5kIGluZGVmaW5pdGVseS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlUGVuZGluZ0ludGVudChwYXlsb2FkOiBSZWdpc3RyeVBheWxvYWQpOiBQcm9taXNlPHN0cmluZz4ge1xuICBhd2FpdCBmcy5ta2RpcihQRU5ESU5HX0lOVEVOVFNfRElSLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgY29uc3QgcGF0aCA9IGpvaW4oUEVORElOR19JTlRFTlRTX0RJUiwgYCR7cGF5bG9hZC5waXBlbGluZUlkfS5qc29uYCk7XG4gIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLCBKU09OLnN0cmluZ2lmeShwYXlsb2FkLCBudWxsLCAyKSwgJ3V0ZjgnKTtcbiAgcmV0dXJuIHBhdGg7XG59XG5cbi8qKiBSZW1vdmUgYSBwZW5kaW5nIGludGVudCBhZnRlciBhIHN1Y2Nlc3NmdWwgZHJhaW4uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xlYXJQZW5kaW5nSW50ZW50KHBpcGVsaW5lSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwYXRoID0gam9pbihQRU5ESU5HX0lOVEVOVFNfRElSLCBgJHtwaXBlbGluZUlkfS5qc29uYCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMudW5saW5rKHBhdGgpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICAvLyBFTk9FTlQgaXMgZmluZSDigJQgYWxyZWFkeSBjbGVhcmVkLiBBbnl0aGluZyBlbHNlIGlzIGEgcmVhbCBwcm9ibGVtLlxuICAgIGlmICgoZXJyIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSAhPT0gJ0VOT0VOVCcpIHRocm93IGVycjtcbiAgfVxufVxuXG4vKiogUmVhZCBhbGwgcGVuZGluZyBpbnRlbnRzIGN1cnJlbnRseSBvbiBkaXNrLiBFbXB0eSBhcnJheSBpZiBkaXIgZG9lc24ndCBleGlzdC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUGVuZGluZ0ludGVudHMoKTogUHJvbWlzZTxSZWdpc3RyeVBheWxvYWRbXT4ge1xuICBsZXQgZW50cmllczogc3RyaW5nW107XG4gIHRyeSB7XG4gICAgZW50cmllcyA9IGF3YWl0IGZzLnJlYWRkaXIoUEVORElOR19JTlRFTlRTX0RJUik7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmICgoZXJyIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gJ0VOT0VOVCcpIHJldHVybiBbXTtcbiAgICB0aHJvdyBlcnI7XG4gIH1cblxuICBjb25zdCBpbnRlbnRzOiBSZWdpc3RyeVBheWxvYWRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGZpbGUgb2YgZW50cmllcykge1xuICAgIGlmICghZmlsZS5lbmRzV2l0aCgnLmpzb24nKSkgY29udGludWU7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCBmcy5yZWFkRmlsZShqb2luKFBFTkRJTkdfSU5URU5UU19ESVIsIGZpbGUpLCAndXRmOCcpO1xuICAgICAgaW50ZW50cy5wdXNoKEpTT04ucGFyc2UodGV4dCkgYXMgUmVnaXN0cnlQYXlsb2FkKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFNraXAgdW5yZWFkYWJsZSAvIG1hbGZvcm1lZCBmaWxlcyDigJQgdGhleSdsbCBuZWVkIG1hbnVhbCBjbGVhbnVwIGJ1dFxuICAgICAgLy8gc2hvdWxkbid0IGJsb2NrIHZhbGlkIGludGVudHMgZnJvbSBkcmFpbmluZy5cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGludGVudHM7XG59XG4iXX0=
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Unwrap a sendSuccess API envelope: { success, statusCode, data: { ... } }
3
+ * Returns the inner `data` object, or the original response if not wrapped.
4
+ */
5
+ export declare function unwrapEnvelope(response: unknown): Record<string, unknown>;
6
+ /**
7
+ * Extract a single entity from an API response, handling envelope formats.
8
+ * Tries: payload[entityKey], payload directly (if identifierKey exists), or undefined.
9
+ */
10
+ export declare function extractSingleResponse<T>(response: unknown, entityKey: string, identifierKey: string): T | undefined;
11
+ export interface ListResponseResult<T> {
12
+ items: T[];
13
+ total?: number;
14
+ hasMore: boolean;
15
+ }
16
+ /**
17
+ * Extract items from an API list response, handling multiple response formats.
18
+ * Supports: `{ <key>: T[] }`, `{ items: T[] }`, `T[]`, or invalid formats.
19
+ */
20
+ export declare function extractListResponse<T>(response: unknown, itemsKey: string): ListResponseResult<T>;
21
+ //# sourceMappingURL=response-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-utils.d.ts","sourceRoot":"","sources":["../../src/utils/response-utils.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAQnH;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAoCjG"}
@@ -0,0 +1,70 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // API response-envelope parsing. Split out of output-utils (which is about
4
+ // rendering) — this is purely about reading the `{ success, data }` shapes the
5
+ // platform returns and pulling out single entities / lists.
6
+ import { printError, printWarning } from './output-utils.js';
7
+ /**
8
+ * Unwrap a sendSuccess API envelope: { success, statusCode, data: { ... } }
9
+ * Returns the inner `data` object, or the original response if not wrapped.
10
+ */
11
+ export function unwrapEnvelope(response) {
12
+ if (response && typeof response === 'object') {
13
+ const obj = response;
14
+ if ('success' in obj && 'data' in obj && obj.data && typeof obj.data === 'object') {
15
+ return obj.data;
16
+ }
17
+ return obj;
18
+ }
19
+ return {};
20
+ }
21
+ /**
22
+ * Extract a single entity from an API response, handling envelope formats.
23
+ * Tries: payload[entityKey], payload directly (if identifierKey exists), or undefined.
24
+ */
25
+ export function extractSingleResponse(response, entityKey, identifierKey) {
26
+ const payload = unwrapEnvelope(response);
27
+ // Direct entity: payload has the identifier (e.g. payload.id, payload.props, payload.name)
28
+ if (identifierKey in payload)
29
+ return payload;
30
+ // Nested under entity key: payload.pipeline, payload.plugin
31
+ const nested = payload[entityKey];
32
+ if (nested && typeof nested === 'object' && identifierKey in nested)
33
+ return nested;
34
+ return undefined;
35
+ }
36
+ /**
37
+ * Extract items from an API list response, handling multiple response formats.
38
+ * Supports: `{ <key>: T[] }`, `{ items: T[] }`, `T[]`, or invalid formats.
39
+ */
40
+ export function extractListResponse(response, itemsKey) {
41
+ if (Array.isArray(response)) {
42
+ return { items: response, total: undefined, hasMore: false };
43
+ }
44
+ if (response && typeof response === 'object') {
45
+ const obj = unwrapEnvelope(response);
46
+ // A `{ success, data: [...] }` envelope unwraps to the bare array — return it directly
47
+ // (the `itemsKey in obj` / `'items' in obj` checks below are false for an array, so
48
+ // without this such list envelopes would silently yield zero items).
49
+ if (Array.isArray(obj)) {
50
+ return { items: obj, total: undefined, hasMore: false };
51
+ }
52
+ // Extract pagination metadata if present
53
+ const pagination = obj.pagination;
54
+ const total = (pagination?.total ?? obj.total);
55
+ const hasMore = (pagination?.hasMore ?? obj.hasMore) || false;
56
+ // Try primary key (e.g. 'pipelines', 'plugins')
57
+ if (itemsKey in obj && Array.isArray(obj[itemsKey])) {
58
+ return { items: obj[itemsKey], total, hasMore };
59
+ }
60
+ // Try generic 'items' key
61
+ if ('items' in obj && Array.isArray(obj.items)) {
62
+ return { items: obj.items, total, hasMore };
63
+ }
64
+ printWarning('Unexpected response format, attempting to handle');
65
+ return { items: [], total: undefined, hasMore: false };
66
+ }
67
+ printError('Invalid response format from API');
68
+ throw new Error('Unexpected API response format');
69
+ }
70
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcmVzcG9uc2UtdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QywyRUFBMkU7QUFDM0UsK0VBQStFO0FBQy9FLDREQUE0RDtBQUU1RCxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRTdEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsUUFBaUI7SUFDOUMsSUFBSSxRQUFRLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDN0MsTUFBTSxHQUFHLEdBQUcsUUFBbUMsQ0FBQztRQUNoRCxJQUFJLFNBQVMsSUFBSSxHQUFHLElBQUksTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLE9BQU8sR0FBRyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNsRixPQUFPLEdBQUcsQ0FBQyxJQUErQixDQUFDO1FBQzdDLENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUksUUFBaUIsRUFBRSxTQUFpQixFQUFFLGFBQXFCO0lBQ2xHLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6QywyRkFBMkY7SUFDM0YsSUFBSSxhQUFhLElBQUksT0FBTztRQUFFLE9BQU8sT0FBdUIsQ0FBQztJQUM3RCw0REFBNEQ7SUFDNUQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBd0MsQ0FBQztJQUN6RSxJQUFJLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksYUFBYSxJQUFJLE1BQU07UUFBRSxPQUFPLE1BQXNCLENBQUM7SUFDbkcsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQVFEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBSSxRQUFpQixFQUFFLFFBQWdCO0lBQ3hFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQzVCLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQy9ELENBQUM7SUFFRCxJQUFJLFFBQVEsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM3QyxNQUFNLEdBQUcsR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFckMsdUZBQXVGO1FBQ3ZGLG9GQUFvRjtRQUNwRixxRUFBcUU7UUFDckUsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFVLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDakUsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsVUFBaUQsQ0FBQztRQUN6RSxNQUFNLEtBQUssR0FBRyxDQUFDLFVBQVUsRUFBRSxLQUFLLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBdUIsQ0FBQztRQUNyRSxNQUFNLE9BQU8sR0FBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBYSxJQUFJLEtBQUssQ0FBQztRQUUzRSxnREFBZ0Q7UUFDaEQsSUFBSSxRQUFRLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNwRCxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQVEsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDekQsQ0FBQztRQUVELDBCQUEwQjtRQUMxQixJQUFJLE9BQU8sSUFBSSxHQUFHLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMvQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFZLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3JELENBQUM7UUFFRCxZQUFZLENBQUMsa0RBQWtELENBQUMsQ0FBQztRQUNqRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUN6RCxDQUFDO0lBRUQsVUFBVSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7SUFDL0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0FBQ3BELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLy8gQVBJIHJlc3BvbnNlLWVudmVsb3BlIHBhcnNpbmcuIFNwbGl0IG91dCBvZiBvdXRwdXQtdXRpbHMgKHdoaWNoIGlzIGFib3V0XG4vLyByZW5kZXJpbmcpIOKAlCB0aGlzIGlzIHB1cmVseSBhYm91dCByZWFkaW5nIHRoZSBgeyBzdWNjZXNzLCBkYXRhIH1gIHNoYXBlcyB0aGVcbi8vIHBsYXRmb3JtIHJldHVybnMgYW5kIHB1bGxpbmcgb3V0IHNpbmdsZSBlbnRpdGllcyAvIGxpc3RzLlxuXG5pbXBvcnQgeyBwcmludEVycm9yLCBwcmludFdhcm5pbmcgfSBmcm9tICcuL291dHB1dC11dGlscy5qcyc7XG5cbi8qKlxuICogVW53cmFwIGEgc2VuZFN1Y2Nlc3MgQVBJIGVudmVsb3BlOiB7IHN1Y2Nlc3MsIHN0YXR1c0NvZGUsIGRhdGE6IHsgLi4uIH0gfVxuICogUmV0dXJucyB0aGUgaW5uZXIgYGRhdGFgIG9iamVjdCwgb3IgdGhlIG9yaWdpbmFsIHJlc3BvbnNlIGlmIG5vdCB3cmFwcGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW53cmFwRW52ZWxvcGUocmVzcG9uc2U6IHVua25vd24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGlmIChyZXNwb25zZSAmJiB0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnKSB7XG4gICAgY29uc3Qgb2JqID0gcmVzcG9uc2UgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgaWYgKCdzdWNjZXNzJyBpbiBvYmogJiYgJ2RhdGEnIGluIG9iaiAmJiBvYmouZGF0YSAmJiB0eXBlb2Ygb2JqLmRhdGEgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gb2JqLmRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfVxuICAgIHJldHVybiBvYmo7XG4gIH1cbiAgcmV0dXJuIHt9O1xufVxuXG4vKipcbiAqIEV4dHJhY3QgYSBzaW5nbGUgZW50aXR5IGZyb20gYW4gQVBJIHJlc3BvbnNlLCBoYW5kbGluZyBlbnZlbG9wZSBmb3JtYXRzLlxuICogVHJpZXM6IHBheWxvYWRbZW50aXR5S2V5XSwgcGF5bG9hZCBkaXJlY3RseSAoaWYgaWRlbnRpZmllcktleSBleGlzdHMpLCBvciB1bmRlZmluZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0U2luZ2xlUmVzcG9uc2U8VD4ocmVzcG9uc2U6IHVua25vd24sIGVudGl0eUtleTogc3RyaW5nLCBpZGVudGlmaWVyS2V5OiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcGF5bG9hZCA9IHVud3JhcEVudmVsb3BlKHJlc3BvbnNlKTtcbiAgLy8gRGlyZWN0IGVudGl0eTogcGF5bG9hZCBoYXMgdGhlIGlkZW50aWZpZXIgKGUuZy4gcGF5bG9hZC5pZCwgcGF5bG9hZC5wcm9wcywgcGF5bG9hZC5uYW1lKVxuICBpZiAoaWRlbnRpZmllcktleSBpbiBwYXlsb2FkKSByZXR1cm4gcGF5bG9hZCBhcyB1bmtub3duIGFzIFQ7XG4gIC8vIE5lc3RlZCB1bmRlciBlbnRpdHkga2V5OiBwYXlsb2FkLnBpcGVsaW5lLCBwYXlsb2FkLnBsdWdpblxuICBjb25zdCBuZXN0ZWQgPSBwYXlsb2FkW2VudGl0eUtleV0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gIGlmIChuZXN0ZWQgJiYgdHlwZW9mIG5lc3RlZCA9PT0gJ29iamVjdCcgJiYgaWRlbnRpZmllcktleSBpbiBuZXN0ZWQpIHJldHVybiBuZXN0ZWQgYXMgdW5rbm93biBhcyBUO1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpc3RSZXNwb25zZVJlc3VsdDxUPiB7XG4gIGl0ZW1zOiBUW107XG4gIHRvdGFsPzogbnVtYmVyO1xuICBoYXNNb3JlOiBib29sZWFuO1xufVxuXG4vKipcbiAqIEV4dHJhY3QgaXRlbXMgZnJvbSBhbiBBUEkgbGlzdCByZXNwb25zZSwgaGFuZGxpbmcgbXVsdGlwbGUgcmVzcG9uc2UgZm9ybWF0cy5cbiAqIFN1cHBvcnRzOiBgeyA8a2V5PjogVFtdIH1gLCBgeyBpdGVtczogVFtdIH1gLCBgVFtdYCwgb3IgaW52YWxpZCBmb3JtYXRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdExpc3RSZXNwb25zZTxUPihyZXNwb25zZTogdW5rbm93biwgaXRlbXNLZXk6IHN0cmluZyk6IExpc3RSZXNwb25zZVJlc3VsdDxUPiB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJlc3BvbnNlKSkge1xuICAgIHJldHVybiB7IGl0ZW1zOiByZXNwb25zZSwgdG90YWw6IHVuZGVmaW5lZCwgaGFzTW9yZTogZmFsc2UgfTtcbiAgfVxuXG4gIGlmIChyZXNwb25zZSAmJiB0eXBlb2YgcmVzcG9uc2UgPT09ICdvYmplY3QnKSB7XG4gICAgY29uc3Qgb2JqID0gdW53cmFwRW52ZWxvcGUocmVzcG9uc2UpO1xuXG4gICAgLy8gQSBgeyBzdWNjZXNzLCBkYXRhOiBbLi4uXSB9YCBlbnZlbG9wZSB1bndyYXBzIHRvIHRoZSBiYXJlIGFycmF5IOKAlCByZXR1cm4gaXQgZGlyZWN0bHlcbiAgICAvLyAodGhlIGBpdGVtc0tleSBpbiBvYmpgIC8gYCdpdGVtcycgaW4gb2JqYCBjaGVja3MgYmVsb3cgYXJlIGZhbHNlIGZvciBhbiBhcnJheSwgc29cbiAgICAvLyB3aXRob3V0IHRoaXMgc3VjaCBsaXN0IGVudmVsb3BlcyB3b3VsZCBzaWxlbnRseSB5aWVsZCB6ZXJvIGl0ZW1zKS5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICByZXR1cm4geyBpdGVtczogb2JqIGFzIFRbXSwgdG90YWw6IHVuZGVmaW5lZCwgaGFzTW9yZTogZmFsc2UgfTtcbiAgICB9XG5cbiAgICAvLyBFeHRyYWN0IHBhZ2luYXRpb24gbWV0YWRhdGEgaWYgcHJlc2VudFxuICAgIGNvbnN0IHBhZ2luYXRpb24gPSBvYmoucGFnaW5hdGlvbiBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCB0b3RhbCA9IChwYWdpbmF0aW9uPy50b3RhbCA/PyBvYmoudG90YWwpIGFzIG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBoYXNNb3JlID0gKChwYWdpbmF0aW9uPy5oYXNNb3JlID8/IG9iai5oYXNNb3JlKSBhcyBib29sZWFuKSB8fCBmYWxzZTtcblxuICAgIC8vIFRyeSBwcmltYXJ5IGtleSAoZS5nLiAncGlwZWxpbmVzJywgJ3BsdWdpbnMnKVxuICAgIGlmIChpdGVtc0tleSBpbiBvYmogJiYgQXJyYXkuaXNBcnJheShvYmpbaXRlbXNLZXldKSkge1xuICAgICAgcmV0dXJuIHsgaXRlbXM6IG9ialtpdGVtc0tleV0gYXMgVFtdLCB0b3RhbCwgaGFzTW9yZSB9O1xuICAgIH1cblxuICAgIC8vIFRyeSBnZW5lcmljICdpdGVtcycga2V5XG4gICAgaWYgKCdpdGVtcycgaW4gb2JqICYmIEFycmF5LmlzQXJyYXkob2JqLml0ZW1zKSkge1xuICAgICAgcmV0dXJuIHsgaXRlbXM6IG9iai5pdGVtcyBhcyBUW10sIHRvdGFsLCBoYXNNb3JlIH07XG4gICAgfVxuXG4gICAgcHJpbnRXYXJuaW5nKCdVbmV4cGVjdGVkIHJlc3BvbnNlIGZvcm1hdCwgYXR0ZW1wdGluZyB0byBoYW5kbGUnKTtcbiAgICByZXR1cm4geyBpdGVtczogW10sIHRvdGFsOiB1bmRlZmluZWQsIGhhc01vcmU6IGZhbHNlIH07XG4gIH1cblxuICBwcmludEVycm9yKCdJbnZhbGlkIHJlc3BvbnNlIGZvcm1hdCBmcm9tIEFQSScpO1xuICB0aHJvdyBuZXcgRXJyb3IoJ1VuZXhwZWN0ZWQgQVBJIHJlc3BvbnNlIGZvcm1hdCcpO1xufVxuIl19
@@ -0,0 +1,52 @@
1
+ import https from 'https';
2
+ /**
3
+ * Hosts that legitimately front a self-signed certificate — local dev stacks and
4
+ * kubectl port-forwards. Everything else (a real deploy domain) is expected to
5
+ * present a valid (ACM) certificate and MUST be verified, so a post-deploy probe
6
+ * can't be silently MITM'd.
7
+ */
8
+ export declare function isLocalHttpsHost(url: string): boolean;
9
+ /**
10
+ * Return an https.Agent that skips certificate verification ONLY for local /
11
+ * self-signed hosts; returns `undefined` (Node's default verification) for real
12
+ * domains. Pass the result straight to axios' `httpsAgent` — `undefined` keeps the
13
+ * default secure behavior.
14
+ */
15
+ export declare function httpsAgentForUrl(url: string): https.Agent | undefined;
16
+ /**
17
+ * Single source of truth for "is this a production run?" — the whole CLI keys its
18
+ * TLS-disable refusal off `NODE_ENV=production`. Centralized here (rather than a
19
+ * bare `process.env.NODE_ENV === 'production'` copied into config-loader, login,
20
+ * platform-secret and the renew handler) so the policy can't drift between the
21
+ * paths that transmit passwords/JWTs and the paths that merely read config.
22
+ */
23
+ export declare function isProductionEnv(): boolean;
24
+ /**
25
+ * Guard for the credential-transmitting SSL-disable paths (login, inline-login,
26
+ * token renewal, and every authenticated command via `getConfigWithOptions`).
27
+ *
28
+ * When a caller asks to disable certificate verification AND the run is
29
+ * production, this THROWS a clear error rather than silently proceeding — a MITM
30
+ * on a "prod with --no-verify-ssl" run would otherwise harvest the very
31
+ * passwords/JWTs these paths send. In non-production it is a no-op, so
32
+ * `--no-verify-ssl` / `PLATFORM_VERIFY_SSL=false` still work against self-signed
33
+ * dev platforms.
34
+ *
35
+ * @param context - short description of the path being guarded, for the message.
36
+ * @throws Error in production; returns `void` otherwise.
37
+ */
38
+ export declare function assertSslDisableAllowed(context?: string): void;
39
+ /**
40
+ * Apply the `--no-verify-ssl` relaxation as a process-wide env flag
41
+ * (`NODE_TLS_REJECT_UNAUTHORIZED=0`) so spawned CDK subprocesses (Lambda,
42
+ * CodeBuild synth) inherit it — but REFUSE in production, mirroring the guard in
43
+ * config-loader. That flag disables certificate validation for ALL outbound TLS
44
+ * (including the AWS SDK), so it must never be silently enabled for a prod
45
+ * deploy/synth.
46
+ *
47
+ * @param verifySsl - the command's `--verify-ssl` value (`false` = user asked to disable).
48
+ * @param warn - warning sink (e.g. `printWarning`).
49
+ * @returns true if verification was disabled; false if left enabled.
50
+ */
51
+ export declare function relaxTlsForCli(verifySsl: boolean | undefined, warn: (message: string) => void): boolean;
52
+ //# sourceMappingURL=tls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../src/utils/tls.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAgBrD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,SAAS,CAErE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,OAAO,GAAG,SAAS,EAC9B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC9B,OAAO,CAQT"}
@@ -0,0 +1,88 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import https from 'https';
4
+ /**
5
+ * Hosts that legitimately front a self-signed certificate — local dev stacks and
6
+ * kubectl port-forwards. Everything else (a real deploy domain) is expected to
7
+ * present a valid (ACM) certificate and MUST be verified, so a post-deploy probe
8
+ * can't be silently MITM'd.
9
+ */
10
+ export function isLocalHttpsHost(url) {
11
+ let hostname;
12
+ try {
13
+ hostname = new URL(url).hostname;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ return (hostname === 'localhost' ||
19
+ hostname === '127.0.0.1' ||
20
+ hostname === '::1' ||
21
+ hostname.endsWith('.local') ||
22
+ /^10\./.test(hostname) ||
23
+ /^192\.168\./.test(hostname) ||
24
+ /^172\.(1[6-9]|2\d|3[01])\./.test(hostname));
25
+ }
26
+ /**
27
+ * Return an https.Agent that skips certificate verification ONLY for local /
28
+ * self-signed hosts; returns `undefined` (Node's default verification) for real
29
+ * domains. Pass the result straight to axios' `httpsAgent` — `undefined` keeps the
30
+ * default secure behavior.
31
+ */
32
+ export function httpsAgentForUrl(url) {
33
+ return isLocalHttpsHost(url) ? new https.Agent({ rejectUnauthorized: false }) : undefined;
34
+ }
35
+ /**
36
+ * Single source of truth for "is this a production run?" — the whole CLI keys its
37
+ * TLS-disable refusal off `NODE_ENV=production`. Centralized here (rather than a
38
+ * bare `process.env.NODE_ENV === 'production'` copied into config-loader, login,
39
+ * platform-secret and the renew handler) so the policy can't drift between the
40
+ * paths that transmit passwords/JWTs and the paths that merely read config.
41
+ */
42
+ export function isProductionEnv() {
43
+ return process.env.NODE_ENV === 'production';
44
+ }
45
+ /**
46
+ * Guard for the credential-transmitting SSL-disable paths (login, inline-login,
47
+ * token renewal, and every authenticated command via `getConfigWithOptions`).
48
+ *
49
+ * When a caller asks to disable certificate verification AND the run is
50
+ * production, this THROWS a clear error rather than silently proceeding — a MITM
51
+ * on a "prod with --no-verify-ssl" run would otherwise harvest the very
52
+ * passwords/JWTs these paths send. In non-production it is a no-op, so
53
+ * `--no-verify-ssl` / `PLATFORM_VERIFY_SSL=false` still work against self-signed
54
+ * dev platforms.
55
+ *
56
+ * @param context - short description of the path being guarded, for the message.
57
+ * @throws Error in production; returns `void` otherwise.
58
+ */
59
+ export function assertSslDisableAllowed(context) {
60
+ if (isProductionEnv()) {
61
+ throw new Error(`Refusing to disable TLS certificate verification in production (NODE_ENV=production)${context ? ` — ${context}` : ''}. `
62
+ + 'Credentials and tokens must never be transmitted over an unverified TLS connection. '
63
+ + 'Use a platform with a valid certificate, or unset NODE_ENV for local/self-signed development.');
64
+ }
65
+ }
66
+ /**
67
+ * Apply the `--no-verify-ssl` relaxation as a process-wide env flag
68
+ * (`NODE_TLS_REJECT_UNAUTHORIZED=0`) so spawned CDK subprocesses (Lambda,
69
+ * CodeBuild synth) inherit it — but REFUSE in production, mirroring the guard in
70
+ * config-loader. That flag disables certificate validation for ALL outbound TLS
71
+ * (including the AWS SDK), so it must never be silently enabled for a prod
72
+ * deploy/synth.
73
+ *
74
+ * @param verifySsl - the command's `--verify-ssl` value (`false` = user asked to disable).
75
+ * @param warn - warning sink (e.g. `printWarning`).
76
+ * @returns true if verification was disabled; false if left enabled.
77
+ */
78
+ export function relaxTlsForCli(verifySsl, warn) {
79
+ if (verifySsl !== false)
80
+ return false;
81
+ if (isProductionEnv()) {
82
+ warn('Refusing to disable TLS verification in production (NODE_ENV=production) — certificate validation remains enabled.');
83
+ return false;
84
+ }
85
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
86
+ return true;
87
+ }
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Rscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUUxQjs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFXO0lBQzFDLElBQUksUUFBZ0IsQ0FBQztJQUNyQixJQUFJLENBQUM7UUFDSCxRQUFRLEdBQUcsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDO0lBQ25DLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxPQUFPLENBQ0wsUUFBUSxLQUFLLFdBQVc7UUFDeEIsUUFBUSxLQUFLLFdBQVc7UUFDeEIsUUFBUSxLQUFLLEtBQUs7UUFDbEIsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDM0IsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDdEIsYUFBYSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDNUIsNEJBQTRCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUM1QyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQVc7SUFDMUMsT0FBTyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVGLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsZUFBZTtJQUM3QixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLFlBQVksQ0FBQztBQUMvQyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxPQUFnQjtJQUN0RCxJQUFJLGVBQWUsRUFBRSxFQUFFLENBQUM7UUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FDYix1RkFBdUYsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUk7Y0FDdkgsc0ZBQXNGO2NBQ3RGLCtGQUErRixDQUNsRyxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQzVCLFNBQThCLEVBQzlCLElBQStCO0lBRS9CLElBQUksU0FBUyxLQUFLLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN0QyxJQUFJLGVBQWUsRUFBRSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLG9IQUFvSCxDQUFDLENBQUM7UUFDM0gsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsR0FBRyxHQUFHLENBQUM7SUFDL0MsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCBodHRwcyBmcm9tICdodHRwcyc7XG5cbi8qKlxuICogSG9zdHMgdGhhdCBsZWdpdGltYXRlbHkgZnJvbnQgYSBzZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSDigJQgbG9jYWwgZGV2IHN0YWNrcyBhbmRcbiAqIGt1YmVjdGwgcG9ydC1mb3J3YXJkcy4gRXZlcnl0aGluZyBlbHNlIChhIHJlYWwgZGVwbG95IGRvbWFpbikgaXMgZXhwZWN0ZWQgdG9cbiAqIHByZXNlbnQgYSB2YWxpZCAoQUNNKSBjZXJ0aWZpY2F0ZSBhbmQgTVVTVCBiZSB2ZXJpZmllZCwgc28gYSBwb3N0LWRlcGxveSBwcm9iZVxuICogY2FuJ3QgYmUgc2lsZW50bHkgTUlUTSdkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNMb2NhbEh0dHBzSG9zdCh1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBsZXQgaG9zdG5hbWU6IHN0cmluZztcbiAgdHJ5IHtcbiAgICBob3N0bmFtZSA9IG5ldyBVUkwodXJsKS5ob3N0bmFtZTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiAoXG4gICAgaG9zdG5hbWUgPT09ICdsb2NhbGhvc3QnIHx8XG4gICAgaG9zdG5hbWUgPT09ICcxMjcuMC4wLjEnIHx8XG4gICAgaG9zdG5hbWUgPT09ICc6OjEnIHx8XG4gICAgaG9zdG5hbWUuZW5kc1dpdGgoJy5sb2NhbCcpIHx8XG4gICAgL14xMFxcLi8udGVzdChob3N0bmFtZSkgfHxcbiAgICAvXjE5MlxcLjE2OFxcLi8udGVzdChob3N0bmFtZSkgfHxcbiAgICAvXjE3MlxcLigxWzYtOV18MlxcZHwzWzAxXSlcXC4vLnRlc3QoaG9zdG5hbWUpXG4gICk7XG59XG5cbi8qKlxuICogUmV0dXJuIGFuIGh0dHBzLkFnZW50IHRoYXQgc2tpcHMgY2VydGlmaWNhdGUgdmVyaWZpY2F0aW9uIE9OTFkgZm9yIGxvY2FsIC9cbiAqIHNlbGYtc2lnbmVkIGhvc3RzOyByZXR1cm5zIGB1bmRlZmluZWRgIChOb2RlJ3MgZGVmYXVsdCB2ZXJpZmljYXRpb24pIGZvciByZWFsXG4gKiBkb21haW5zLiBQYXNzIHRoZSByZXN1bHQgc3RyYWlnaHQgdG8gYXhpb3MnIGBodHRwc0FnZW50YCDigJQgYHVuZGVmaW5lZGAga2VlcHMgdGhlXG4gKiBkZWZhdWx0IHNlY3VyZSBiZWhhdmlvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGh0dHBzQWdlbnRGb3JVcmwodXJsOiBzdHJpbmcpOiBodHRwcy5BZ2VudCB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBpc0xvY2FsSHR0cHNIb3N0KHVybCkgPyBuZXcgaHR0cHMuQWdlbnQoeyByZWplY3RVbmF1dGhvcml6ZWQ6IGZhbHNlIH0pIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIFwiaXMgdGhpcyBhIHByb2R1Y3Rpb24gcnVuP1wiIOKAlCB0aGUgd2hvbGUgQ0xJIGtleXMgaXRzXG4gKiBUTFMtZGlzYWJsZSByZWZ1c2FsIG9mZiBgTk9ERV9FTlY9cHJvZHVjdGlvbmAuIENlbnRyYWxpemVkIGhlcmUgKHJhdGhlciB0aGFuIGFcbiAqIGJhcmUgYHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbidgIGNvcGllZCBpbnRvIGNvbmZpZy1sb2FkZXIsIGxvZ2luLFxuICogcGxhdGZvcm0tc2VjcmV0IGFuZCB0aGUgcmVuZXcgaGFuZGxlcikgc28gdGhlIHBvbGljeSBjYW4ndCBkcmlmdCBiZXR3ZWVuIHRoZVxuICogcGF0aHMgdGhhdCB0cmFuc21pdCBwYXNzd29yZHMvSldUcyBhbmQgdGhlIHBhdGhzIHRoYXQgbWVyZWx5IHJlYWQgY29uZmlnLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQcm9kdWN0aW9uRW52KCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJztcbn1cblxuLyoqXG4gKiBHdWFyZCBmb3IgdGhlIGNyZWRlbnRpYWwtdHJhbnNtaXR0aW5nIFNTTC1kaXNhYmxlIHBhdGhzIChsb2dpbiwgaW5saW5lLWxvZ2luLFxuICogdG9rZW4gcmVuZXdhbCwgYW5kIGV2ZXJ5IGF1dGhlbnRpY2F0ZWQgY29tbWFuZCB2aWEgYGdldENvbmZpZ1dpdGhPcHRpb25zYCkuXG4gKlxuICogV2hlbiBhIGNhbGxlciBhc2tzIHRvIGRpc2FibGUgY2VydGlmaWNhdGUgdmVyaWZpY2F0aW9uIEFORCB0aGUgcnVuIGlzXG4gKiBwcm9kdWN0aW9uLCB0aGlzIFRIUk9XUyBhIGNsZWFyIGVycm9yIHJhdGhlciB0aGFuIHNpbGVudGx5IHByb2NlZWRpbmcg4oCUIGEgTUlUTVxuICogb24gYSBcInByb2Qgd2l0aCAtLW5vLXZlcmlmeS1zc2xcIiBydW4gd291bGQgb3RoZXJ3aXNlIGhhcnZlc3QgdGhlIHZlcnlcbiAqIHBhc3N3b3Jkcy9KV1RzIHRoZXNlIHBhdGhzIHNlbmQuIEluIG5vbi1wcm9kdWN0aW9uIGl0IGlzIGEgbm8tb3AsIHNvXG4gKiBgLS1uby12ZXJpZnktc3NsYCAvIGBQTEFURk9STV9WRVJJRllfU1NMPWZhbHNlYCBzdGlsbCB3b3JrIGFnYWluc3Qgc2VsZi1zaWduZWRcbiAqIGRldiBwbGF0Zm9ybXMuXG4gKlxuICogQHBhcmFtIGNvbnRleHQgLSBzaG9ydCBkZXNjcmlwdGlvbiBvZiB0aGUgcGF0aCBiZWluZyBndWFyZGVkLCBmb3IgdGhlIG1lc3NhZ2UuXG4gKiBAdGhyb3dzIEVycm9yIGluIHByb2R1Y3Rpb247IHJldHVybnMgYHZvaWRgIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFNzbERpc2FibGVBbGxvd2VkKGNvbnRleHQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKGlzUHJvZHVjdGlvbkVudigpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFJlZnVzaW5nIHRvIGRpc2FibGUgVExTIGNlcnRpZmljYXRlIHZlcmlmaWNhdGlvbiBpbiBwcm9kdWN0aW9uIChOT0RFX0VOVj1wcm9kdWN0aW9uKSR7Y29udGV4dCA/IGAg4oCUICR7Y29udGV4dH1gIDogJyd9LiBgXG4gICAgICArICdDcmVkZW50aWFscyBhbmQgdG9rZW5zIG11c3QgbmV2ZXIgYmUgdHJhbnNtaXR0ZWQgb3ZlciBhbiB1bnZlcmlmaWVkIFRMUyBjb25uZWN0aW9uLiAnXG4gICAgICArICdVc2UgYSBwbGF0Zm9ybSB3aXRoIGEgdmFsaWQgY2VydGlmaWNhdGUsIG9yIHVuc2V0IE5PREVfRU5WIGZvciBsb2NhbC9zZWxmLXNpZ25lZCBkZXZlbG9wbWVudC4nLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBBcHBseSB0aGUgYC0tbm8tdmVyaWZ5LXNzbGAgcmVsYXhhdGlvbiBhcyBhIHByb2Nlc3Mtd2lkZSBlbnYgZmxhZ1xuICogKGBOT0RFX1RMU19SRUpFQ1RfVU5BVVRIT1JJWkVEPTBgKSBzbyBzcGF3bmVkIENESyBzdWJwcm9jZXNzZXMgKExhbWJkYSxcbiAqIENvZGVCdWlsZCBzeW50aCkgaW5oZXJpdCBpdCDigJQgYnV0IFJFRlVTRSBpbiBwcm9kdWN0aW9uLCBtaXJyb3JpbmcgdGhlIGd1YXJkIGluXG4gKiBjb25maWctbG9hZGVyLiBUaGF0IGZsYWcgZGlzYWJsZXMgY2VydGlmaWNhdGUgdmFsaWRhdGlvbiBmb3IgQUxMIG91dGJvdW5kIFRMU1xuICogKGluY2x1ZGluZyB0aGUgQVdTIFNESyksIHNvIGl0IG11c3QgbmV2ZXIgYmUgc2lsZW50bHkgZW5hYmxlZCBmb3IgYSBwcm9kXG4gKiBkZXBsb3kvc3ludGguXG4gKlxuICogQHBhcmFtIHZlcmlmeVNzbCAtIHRoZSBjb21tYW5kJ3MgYC0tdmVyaWZ5LXNzbGAgdmFsdWUgKGBmYWxzZWAgPSB1c2VyIGFza2VkIHRvIGRpc2FibGUpLlxuICogQHBhcmFtIHdhcm4gLSB3YXJuaW5nIHNpbmsgKGUuZy4gYHByaW50V2FybmluZ2ApLlxuICogQHJldHVybnMgdHJ1ZSBpZiB2ZXJpZmljYXRpb24gd2FzIGRpc2FibGVkOyBmYWxzZSBpZiBsZWZ0IGVuYWJsZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWxheFRsc0ZvckNsaShcbiAgdmVyaWZ5U3NsOiBib29sZWFuIHwgdW5kZWZpbmVkLFxuICB3YXJuOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkLFxuKTogYm9vbGVhbiB7XG4gIGlmICh2ZXJpZnlTc2wgIT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gIGlmIChpc1Byb2R1Y3Rpb25FbnYoKSkge1xuICAgIHdhcm4oJ1JlZnVzaW5nIHRvIGRpc2FibGUgVExTIHZlcmlmaWNhdGlvbiBpbiBwcm9kdWN0aW9uIChOT0RFX0VOVj1wcm9kdWN0aW9uKSDigJQgY2VydGlmaWNhdGUgdmFsaWRhdGlvbiByZW1haW5zIGVuYWJsZWQuJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHByb2Nlc3MuZW52Lk5PREVfVExTX1JFSkVDVF9VTkFVVEhPUklaRUQgPSAnMCc7XG4gIHJldHVybiB0cnVlO1xufVxuIl19
package/package.json ADDED
@@ -0,0 +1,181 @@
1
+ {
2
+ "name": "@pipeline-builder/pipeline-manager",
3
+ "description": "CLI for Pipeline Builder self-service AWS CodePipeline platform with 125 reusable containerized plugins, per-org compliance enforcement, and per-organization (and team) isolation.",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/mwashburn160/pipeline-builder.git"
7
+ },
8
+ "bin": {
9
+ "pipeline-manager": "./dist/cli.js"
10
+ },
11
+ "devDependencies": {
12
+ "@jest/globals": "30.4.1",
13
+ "@stylistic/eslint-plugin": "^2",
14
+ "@types/figlet": "1.7.0",
15
+ "@types/node": "^24",
16
+ "@types/progress": "2.0.7",
17
+ "@typescript-eslint/eslint-plugin": "^8",
18
+ "@typescript-eslint/parser": "^8",
19
+ "@typescript/native": "npm:typescript@^7.0.2",
20
+ "copyfiles": "2.4.1",
21
+ "eslint": "^9",
22
+ "eslint-import-resolver-typescript": "^4.4.4",
23
+ "eslint-plugin-import": "^2.32.0",
24
+ "jest": "30.4.2",
25
+ "jest-junit": "^17",
26
+ "ts-jest": "29.4.12",
27
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
28
+ },
29
+ "dependencies": {
30
+ "@aws-sdk/client-cloudformation": "3.1101.0",
31
+ "@aws-sdk/client-lambda": "3.1101.0",
32
+ "@aws-sdk/client-secrets-manager": "3.1101.0",
33
+ "@aws-sdk/client-sqs": "3.1101.0",
34
+ "@aws-sdk/client-sts": "3.1101.0",
35
+ "aws-cdk-lib": "2.263.0",
36
+ "axios": "1.19.0",
37
+ "commander": "15.0.0",
38
+ "constructs": "10.7.0",
39
+ "figlet": "1.11.4",
40
+ "form-data": "4.0.6",
41
+ "ora": "9.4.1",
42
+ "picocolors": "1.1.1",
43
+ "progress": "2.0.3",
44
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
45
+ "yaml": "2.9.0",
46
+ "zod": "4.4.3",
47
+ "@pipeline-builder/ai-core": "0.0.1",
48
+ "@pipeline-builder/api-core": "0.0.1",
49
+ "@pipeline-builder/pipeline-core": "0.0.1"
50
+ },
51
+ "keywords": [
52
+ "ci-cd",
53
+ "cicd",
54
+ "continuous-delivery",
55
+ "devops",
56
+ "self-service",
57
+ "platform-engineering",
58
+ "internal-developer-platform",
59
+ "developer-platform",
60
+ "aws",
61
+ "aws-cdk",
62
+ "cdk",
63
+ "codepipeline",
64
+ "codebuild",
65
+ "cloudformation",
66
+ "pipeline",
67
+ "pipeline-as-code",
68
+ "infrastructure-as-code",
69
+ "iac",
70
+ "compliance",
71
+ "policy-as-code",
72
+ "governance",
73
+ "golden-paths",
74
+ "multi-tenant",
75
+ "rbac",
76
+ "ai",
77
+ "ai-pipeline-generation",
78
+ "llm",
79
+ "bedrock",
80
+ "plugins",
81
+ "plugin-marketplace",
82
+ "containerized",
83
+ "docker",
84
+ "kubernetes",
85
+ "typescript",
86
+ "cli"
87
+ ],
88
+ "engines": {
89
+ "node": ">= 24.14.0"
90
+ },
91
+ "devEngines": {
92
+ "packageManager": {
93
+ "name": "pnpm",
94
+ "version": ">=10",
95
+ "onFail": "ignore"
96
+ }
97
+ },
98
+ "license": "Apache-2.0",
99
+ "homepage": "https://mwashburn160.github.io/pipeline-builder/",
100
+ "publishConfig": {
101
+ "access": "public",
102
+ "registry": "https://registry.npmjs.org/"
103
+ },
104
+ "version": "0.0.1",
105
+ "bugs": {
106
+ "url": "https://github.com/mwashburn160/pipeline-builder/issues"
107
+ },
108
+ "jest": {
109
+ "coverageProvider": "v8",
110
+ "testMatch": [
111
+ "<rootDir>/@(src|test)/**/*(*.)@(spec|test).[jt]s?(x)",
112
+ "<rootDir>/@(src|test)/**/__tests__/**/*.[jt]s?(x)"
113
+ ],
114
+ "clearMocks": true,
115
+ "collectCoverage": true,
116
+ "coverageReporters": [
117
+ "json",
118
+ "lcov",
119
+ "clover",
120
+ "cobertura",
121
+ "text"
122
+ ],
123
+ "coverageDirectory": "coverage",
124
+ "coveragePathIgnorePatterns": [
125
+ "/node_modules/"
126
+ ],
127
+ "testPathIgnorePatterns": [
128
+ "/node_modules/"
129
+ ],
130
+ "watchPathIgnorePatterns": [
131
+ "/node_modules/"
132
+ ],
133
+ "reporters": [
134
+ "default",
135
+ [
136
+ "jest-junit",
137
+ {
138
+ "outputDirectory": "test-reports"
139
+ }
140
+ ]
141
+ ],
142
+ "transform": {
143
+ "^.+\\.[t]sx?$": [
144
+ "ts-jest",
145
+ {
146
+ "useESM": true,
147
+ "tsconfig": "tsconfig.dev.json",
148
+ "diagnostics": {
149
+ "ignoreCodes": [
150
+ 151002
151
+ ]
152
+ }
153
+ }
154
+ ]
155
+ },
156
+ "extensionsToTreatAsEsm": [
157
+ ".ts",
158
+ ".tsx"
159
+ ],
160
+ "moduleNameMapper": {
161
+ "^uuid$": "<rootDir>/../../jest-uuid-stub.js",
162
+ "^(\\.{1,2}/.*)\\.js$": "$1"
163
+ }
164
+ },
165
+ "type": "module",
166
+ "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm dlx projen\".",
167
+ "scripts": {
168
+ "audit": "pnpm dlx projen audit",
169
+ "build": "pnpm dlx projen build",
170
+ "compile": "pnpm dlx projen compile",
171
+ "default": "pnpm dlx projen default",
172
+ "eslint": "pnpm dlx projen eslint",
173
+ "package": "pnpm dlx projen package",
174
+ "post-compile": "pnpm dlx projen post-compile",
175
+ "pre-compile": "pnpm dlx projen pre-compile",
176
+ "test": "pnpm dlx projen test",
177
+ "test:watch": "pnpm dlx projen test:watch",
178
+ "watch": "pnpm dlx projen watch",
179
+ "projen": "pnpm dlx projen"
180
+ }
181
+ }