@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,21 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `login` command with the CLI program.
4
+ *
5
+ * Authenticates against the platform API and prints an export statement
6
+ * for `PLATFORM_TOKEN` on success. Does NOT require `PLATFORM_TOKEN`
7
+ * to be set beforehand (unlike other commands).
8
+ *
9
+ * @param program - The root Commander program instance to attach the command to.
10
+ *
11
+ * @example
12
+ * ```bash
13
+ * pipeline-manager auth login --identifier admin@example.com --password secret
14
+ * pipeline-manager auth login -u admin@example.com -p secret
15
+ * pipeline-manager auth login -u admin@example.com -p secret --url https://myhost:8443
16
+ * eval $(pipeline-manager auth login -u admin@example.com -p secret --quiet)
17
+ * pipeline-manager auth login --refresh <refresh-token>
18
+ * ```
19
+ */
20
+ export declare function login(program: Command): void;
21
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoK5C"}
@@ -0,0 +1,174 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import axios from 'axios';
4
+ import { Command } from 'commander';
5
+ import pico from 'picocolors';
6
+ import { TIMEOUTS } from '../config/cli.constants.js';
7
+ import { assertCredentialTlsAllowed, credentialHttpsAgent, postLogin, resolveCredentials, switchOrganization } from '../utils/auth-utils.js';
8
+ import { printCommandHeader, withSslOptions } from '../utils/command-utils.js';
9
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
10
+ import { printDebug, printError, printInfo, printSuccess, printWarning } from '../utils/output-utils.js';
11
+ import { checkAuthRateLimit, recordAuthFailure, recordAuthSuccess } from '../utils/rate-limiter.js';
12
+ const { green } = pico;
13
+ /**
14
+ * Registers the `login` command with the CLI program.
15
+ *
16
+ * Authenticates against the platform API and prints an export statement
17
+ * for `PLATFORM_TOKEN` on success. Does NOT require `PLATFORM_TOKEN`
18
+ * to be set beforehand (unlike other commands).
19
+ *
20
+ * @param program - The root Commander program instance to attach the command to.
21
+ *
22
+ * @example
23
+ * ```bash
24
+ * pipeline-manager auth login --identifier admin@example.com --password secret
25
+ * pipeline-manager auth login -u admin@example.com -p secret
26
+ * pipeline-manager auth login -u admin@example.com -p secret --url https://myhost:8443
27
+ * eval $(pipeline-manager auth login -u admin@example.com -p secret --quiet)
28
+ * pipeline-manager auth login --refresh <refresh-token>
29
+ * ```
30
+ */
31
+ export function login(program) {
32
+ withSslOptions(program
33
+ .command('login')
34
+ .description('Authenticate with the platform and obtain a PLATFORM_TOKEN')
35
+ .option('-u, --identifier <identifier>', 'Username or email')
36
+ .option('-p, --password <password>', 'Password')
37
+ .option('--refresh <refreshToken>', 'Use a refresh token instead of login credentials')
38
+ .option('--org <orgId>', 'Switch to a specific organization after login')
39
+ .option('--url <url>', 'Platform base URL', process.env.PLATFORM_BASE_URL || 'https://localhost:8443'))
40
+ .option('--quiet', 'Only print the export statement (useful for eval)')
41
+ .action(async (options) => {
42
+ const isRefresh = !!options.refresh;
43
+ const quiet = options.quiet ?? false;
44
+ const executionId = printCommandHeader(isRefresh ? 'Token Refresh' : 'Login', isRefresh ? 'Token Refresh' : 'Platform Authentication', { quiet });
45
+ // SECURITY: login/refresh POST plaintext passwords and JWTs. Never send them
46
+ // over an unverified TLS connection in production — a MITM would harvest them.
47
+ // In non-production, --no-verify-ssl is still honored (self-signed dev platforms).
48
+ assertCredentialTlsAllowed(options.verifySsl);
49
+ // Credentials may come from flags OR the PLATFORM_IDENTIFIER/PLATFORM_PASSWORD
50
+ // env vars (so the password need not appear in shell history / `ps`).
51
+ const { identifier, password } = resolveCredentials(options);
52
+ let loginSucceeded = false;
53
+ try {
54
+ // Validate required options
55
+ if (!isRefresh && (!identifier || !password)) {
56
+ printError('Login requires --identifier and --password (or PLATFORM_IDENTIFIER/PLATFORM_PASSWORD env), or --refresh <token>');
57
+ process.exit(ERROR_CODES.AUTHENTICATION);
58
+ }
59
+ if (!isRefresh && options.password) {
60
+ printWarning('Passing --password on the command line can expose it via shell history; prefer the PLATFORM_PASSWORD env var.');
61
+ }
62
+ // Rate limiting — prevent brute force (login only)
63
+ if (!isRefresh) {
64
+ const rateLimitMsg = checkAuthRateLimit(identifier, options.url);
65
+ if (rateLimitMsg) {
66
+ printError(rateLimitMsg);
67
+ process.exit(ERROR_CODES.AUTHENTICATION);
68
+ }
69
+ }
70
+ if (!quiet) {
71
+ printInfo(isRefresh ? 'Refreshing access token' : 'Authenticating', {
72
+ ...(identifier ? { identifier } : {}),
73
+ url: options.url,
74
+ verifySsl: options.verifySsl,
75
+ });
76
+ }
77
+ const httpsAgent = credentialHttpsAgent(options.verifySsl);
78
+ let token;
79
+ if (isRefresh) {
80
+ const refreshUrl = `${options.url}/api/auth/refresh`;
81
+ printDebug('POST', { url: refreshUrl });
82
+ const response = await axios.post(refreshUrl, { refreshToken: options.refresh }, {
83
+ headers: { 'Content-Type': 'application/json' },
84
+ httpsAgent,
85
+ timeout: TIMEOUTS.HTTP_REQUEST,
86
+ });
87
+ token = response.data?.data?.accessToken;
88
+ }
89
+ else {
90
+ // identifier/password validated non-null above (the `!isRefresh` guard).
91
+ token = await postLogin({
92
+ url: options.url,
93
+ identifier: identifier,
94
+ password: password,
95
+ httpsAgent,
96
+ timeout: TIMEOUTS.HTTP_REQUEST,
97
+ });
98
+ }
99
+ if (!token) {
100
+ if (!isRefresh)
101
+ recordAuthFailure(identifier, options.url);
102
+ printError(`${isRefresh ? 'Token refresh' : 'Login'} failed: no access token in response`);
103
+ process.exit(ERROR_CODES.AUTHENTICATION);
104
+ }
105
+ if (!isRefresh)
106
+ recordAuthSuccess(identifier, options.url);
107
+ // Past this point authentication has already succeeded — a later failure
108
+ // (e.g. the --org switch below) must NOT be recorded as an auth failure,
109
+ // or a valid-credential user would accrue toward brute-force lockout.
110
+ loginSucceeded = true;
111
+ // Switch to a specific organization if --org is provided
112
+ if (options.org) {
113
+ if (!quiet) {
114
+ printInfo('Switching to organization', { orgId: options.org });
115
+ }
116
+ token = await switchOrganization({
117
+ url: options.url,
118
+ orgId: options.org,
119
+ accessToken: token,
120
+ httpsAgent,
121
+ timeout: TIMEOUTS.HTTP_REQUEST,
122
+ quiet,
123
+ });
124
+ }
125
+ if (!quiet) {
126
+ console.log('');
127
+ printSuccess(isRefresh ? 'Token refreshed successfully' : 'Login successful');
128
+ console.log('');
129
+ }
130
+ console.log(`export PLATFORM_TOKEN=${token}`);
131
+ if (!quiet) {
132
+ console.log('');
133
+ printInfo('Tip: Run the following to set the token in your shell:');
134
+ const orgFlag = options.org ? ` --org ${options.org}` : '';
135
+ if (isRefresh) {
136
+ console.log(green(` eval $(pipeline-manager auth login --refresh '<refresh-token>'${orgFlag} --quiet)`));
137
+ }
138
+ else {
139
+ console.log(green(` eval $(pipeline-manager auth login -u ${identifier} -p '***'${orgFlag} --quiet)`));
140
+ }
141
+ }
142
+ }
143
+ catch (error) {
144
+ // Key the failure to (identifier, url) like the check/success/no-token
145
+ // paths — a bad-password 401 throws to here, so keying it to the shared
146
+ // default bucket meant brute-force attempts never accrued toward lockout.
147
+ // Skip when login already succeeded (a failed post-login --org switch is
148
+ // not an authentication failure).
149
+ if (!isRefresh && !loginSucceeded)
150
+ recordAuthFailure(identifier, options.url);
151
+ // Provide a clear failure message for auth errors
152
+ if (axios.isAxiosError(error)) {
153
+ const status = error.response?.status;
154
+ const message = error.response?.data?.message;
155
+ printError(`${isRefresh ? 'Token refresh' : 'Login'} failed`, {
156
+ status: status ?? 'no response',
157
+ ...(message ? { message } : {}),
158
+ });
159
+ process.exit(ERROR_CODES.AUTHENTICATION);
160
+ }
161
+ handleError(error, ERROR_CODES.AUTHENTICATION, {
162
+ debug: program.opts().debug,
163
+ exit: true,
164
+ context: {
165
+ command: 'login',
166
+ executionId,
167
+ identifier: options.identifier,
168
+ url: options.url,
169
+ },
170
+ });
171
+ }
172
+ });
173
+ }
174
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvbG9naW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLElBQUksTUFBTSxZQUFZLENBQUM7QUFDOUIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RELE9BQU8sRUFBRSwwQkFBMEIsRUFBcUIsb0JBQW9CLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEssT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVwRyxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRXZCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxLQUFLLENBQUMsT0FBZ0I7SUFDcEMsY0FBYyxDQUFDLE9BQU87U0FDbkIsT0FBTyxDQUFDLE9BQU8sQ0FBQztTQUNoQixXQUFXLENBQUMsNERBQTRELENBQUM7U0FDekUsTUFBTSxDQUFDLCtCQUErQixFQUFFLG1CQUFtQixDQUFDO1NBQzVELE1BQU0sQ0FBQywyQkFBMkIsRUFBRSxVQUFVLENBQUM7U0FDL0MsTUFBTSxDQUFDLDBCQUEwQixFQUFFLGtEQUFrRCxDQUFDO1NBQ3RGLE1BQU0sQ0FBQyxlQUFlLEVBQUUsK0NBQStDLENBQUM7U0FDeEUsTUFBTSxDQUFDLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixJQUFJLHdCQUF3QixDQUFDLENBQUM7U0FDdEcsTUFBTSxDQUFDLFNBQVMsRUFBRSxtREFBbUQsQ0FBQztTQUN0RSxNQUFNLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQ3hCLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQ3BDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDO1FBQ3JDLE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUNwQyxTQUFTLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUNyQyxTQUFTLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMseUJBQXlCLEVBQ3ZELEVBQUUsS0FBSyxFQUFFLENBQ1YsQ0FBQztRQUVGLDZFQUE2RTtRQUM3RSwrRUFBK0U7UUFDL0UsbUZBQW1GO1FBQ25GLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU5QywrRUFBK0U7UUFDL0Usc0VBQXNFO1FBQ3RFLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFN0QsSUFBSSxjQUFjLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQztZQUVILDRCQUE0QjtZQUM1QixJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUM3QyxVQUFVLENBQUMsaUhBQWlILENBQUMsQ0FBQztnQkFDOUgsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDM0MsQ0FBQztZQUNELElBQUksQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNuQyxZQUFZLENBQUMsK0dBQStHLENBQUMsQ0FBQztZQUNoSSxDQUFDO1lBRUQsbURBQW1EO1lBQ25ELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNqRSxJQUFJLFlBQVksRUFBRSxDQUFDO29CQUNqQixVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ3pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUMzQyxDQUFDO1lBQ0gsQ0FBQztZQUVELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEVBQUU7b0JBQ2xFLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDckMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO29CQUNoQixTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7aUJBQzdCLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxNQUFNLFVBQVUsR0FBRyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFM0QsSUFBSSxLQUF5QixDQUFDO1lBRTlCLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxVQUFVLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxtQkFBbUIsQ0FBQztnQkFDckQsVUFBVSxDQUFDLE1BQU0sRUFBRSxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUV4QyxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQy9CLFVBQVUsRUFDVixFQUFFLFlBQVksRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQ2pDO29CQUNFLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRTtvQkFDL0MsVUFBVTtvQkFDVixPQUFPLEVBQUUsUUFBUSxDQUFDLFlBQVk7aUJBQy9CLENBQ0YsQ0FBQztnQkFFRixLQUFLLEdBQUcsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDO1lBQzNDLENBQUM7aUJBQU0sQ0FBQztnQkFDTix5RUFBeUU7Z0JBQ3pFLEtBQUssR0FBRyxNQUFNLFNBQVMsQ0FBQztvQkFDdEIsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO29CQUNoQixVQUFVLEVBQUUsVUFBVztvQkFDdkIsUUFBUSxFQUFFLFFBQVM7b0JBQ25CLFVBQVU7b0JBQ1YsT0FBTyxFQUFFLFFBQVEsQ0FBQyxZQUFZO2lCQUMvQixDQUFDLENBQUM7WUFDTCxDQUFDO1lBRUQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNYLElBQUksQ0FBQyxTQUFTO29CQUFFLGlCQUFpQixDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzNELFVBQVUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxPQUFPLHNDQUFzQyxDQUFDLENBQUM7Z0JBQzNGLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzNDLENBQUM7WUFFRCxJQUFJLENBQUMsU0FBUztnQkFBRSxpQkFBaUIsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzNELHlFQUF5RTtZQUN6RSx5RUFBeUU7WUFDekUsc0VBQXNFO1lBQ3RFLGNBQWMsR0FBRyxJQUFJLENBQUM7WUFFdEIseURBQXlEO1lBQ3pELElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ1gsU0FBUyxDQUFDLDJCQUEyQixFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dCQUNqRSxDQUFDO2dCQUVELEtBQUssR0FBRyxNQUFNLGtCQUFrQixDQUFDO29CQUMvQixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBQ2hCLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRztvQkFDbEIsV0FBVyxFQUFFLEtBQUs7b0JBQ2xCLFVBQVU7b0JBQ1YsT0FBTyxFQUFFLFFBQVEsQ0FBQyxZQUFZO29CQUM5QixLQUFLO2lCQUNOLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1gsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDaEIsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsOEJBQThCLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBQzlFLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbEIsQ0FBQztZQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEtBQUssRUFBRSxDQUFDLENBQUM7WUFFOUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNYLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLFNBQVMsQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO2dCQUNwRSxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxVQUFVLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUMzRCxJQUFJLFNBQVMsRUFBRSxDQUFDO29CQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLG1FQUFtRSxPQUFPLFdBQVcsQ0FBQyxDQUFDLENBQUM7Z0JBQzVHLENBQUM7cUJBQU0sQ0FBQztvQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQywyQ0FBMkMsVUFBVSxZQUFZLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFDMUcsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLHVFQUF1RTtZQUN2RSx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLHlFQUF5RTtZQUN6RSxrQ0FBa0M7WUFDbEMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWM7Z0JBQUUsaUJBQWlCLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM5RSxrREFBa0Q7WUFDbEQsSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzlCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDO2dCQUN0QyxNQUFNLE9BQU8sR0FBSSxLQUFLLENBQUMsUUFBUSxFQUFFLElBQTZCLEVBQUUsT0FBTyxDQUFDO2dCQUV4RSxVQUFVLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsT0FBTyxTQUFTLEVBQUU7b0JBQzVELE1BQU0sRUFBRSxNQUFNLElBQUksYUFBYTtvQkFDL0IsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2lCQUNoQyxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDM0MsQ0FBQztZQUVELFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLGNBQWMsRUFBRTtnQkFDN0MsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUU7b0JBQ1AsT0FBTyxFQUFFLE9BQU87b0JBQ2hCLFdBQVc7b0JBQ1gsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVO29CQUM5QixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7aUJBQ2pCO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgcGljbyBmcm9tICdwaWNvY29sb3JzJztcbmltcG9ydCB7IFRJTUVPVVRTIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXNzZXJ0Q3JlZGVudGlhbFRsc0FsbG93ZWQsIHR5cGUgQXV0aFJlc3BvbnNlLCBjcmVkZW50aWFsSHR0cHNBZ2VudCwgcG9zdExvZ2luLCByZXNvbHZlQ3JlZGVudGlhbHMsIHN3aXRjaE9yZ2FuaXphdGlvbiB9IGZyb20gJy4uL3V0aWxzL2F1dGgtdXRpbHMuanMnO1xuaW1wb3J0IHsgcHJpbnRDb21tYW5kSGVhZGVyLCB3aXRoU3NsT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL2NvbW1hbmQtdXRpbHMuanMnO1xuaW1wb3J0IHsgRVJST1JfQ09ERVMsIGhhbmRsZUVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBwcmludERlYnVnLCBwcmludEVycm9yLCBwcmludEluZm8sIHByaW50U3VjY2VzcywgcHJpbnRXYXJuaW5nIH0gZnJvbSAnLi4vdXRpbHMvb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IGNoZWNrQXV0aFJhdGVMaW1pdCwgcmVjb3JkQXV0aEZhaWx1cmUsIHJlY29yZEF1dGhTdWNjZXNzIH0gZnJvbSAnLi4vdXRpbHMvcmF0ZS1saW1pdGVyLmpzJztcblxuY29uc3QgeyBncmVlbiB9ID0gcGljbztcblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBsb2dpbmAgY29tbWFuZCB3aXRoIHRoZSBDTEkgcHJvZ3JhbS5cbiAqXG4gKiBBdXRoZW50aWNhdGVzIGFnYWluc3QgdGhlIHBsYXRmb3JtIEFQSSBhbmQgcHJpbnRzIGFuIGV4cG9ydCBzdGF0ZW1lbnRcbiAqIGZvciBgUExBVEZPUk1fVE9LRU5gIG9uIHN1Y2Nlc3MuICBEb2VzIE5PVCByZXF1aXJlIGBQTEFURk9STV9UT0tFTmBcbiAqIHRvIGJlIHNldCBiZWZvcmVoYW5kICh1bmxpa2Ugb3RoZXIgY29tbWFuZHMpLlxuICpcbiAqIEBwYXJhbSBwcm9ncmFtIC0gVGhlIHJvb3QgQ29tbWFuZGVyIHByb2dyYW0gaW5zdGFuY2UgdG8gYXR0YWNoIHRoZSBjb21tYW5kIHRvLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLS1pZGVudGlmaWVyIGFkbWluQGV4YW1wbGUuY29tIC0tcGFzc3dvcmQgc2VjcmV0XG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLXUgYWRtaW5AZXhhbXBsZS5jb20gLXAgc2VjcmV0XG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLXUgYWRtaW5AZXhhbXBsZS5jb20gLXAgc2VjcmV0IC0tdXJsIGh0dHBzOi8vbXlob3N0Ojg0NDNcbiAqIGV2YWwgJChwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLXUgYWRtaW5AZXhhbXBsZS5jb20gLXAgc2VjcmV0IC0tcXVpZXQpXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLS1yZWZyZXNoIDxyZWZyZXNoLXRva2VuPlxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dpbihwcm9ncmFtOiBDb21tYW5kKTogdm9pZCB7XG4gIHdpdGhTc2xPcHRpb25zKHByb2dyYW1cbiAgICAuY29tbWFuZCgnbG9naW4nKVxuICAgIC5kZXNjcmlwdGlvbignQXV0aGVudGljYXRlIHdpdGggdGhlIHBsYXRmb3JtIGFuZCBvYnRhaW4gYSBQTEFURk9STV9UT0tFTicpXG4gICAgLm9wdGlvbignLXUsIC0taWRlbnRpZmllciA8aWRlbnRpZmllcj4nLCAnVXNlcm5hbWUgb3IgZW1haWwnKVxuICAgIC5vcHRpb24oJy1wLCAtLXBhc3N3b3JkIDxwYXNzd29yZD4nLCAnUGFzc3dvcmQnKVxuICAgIC5vcHRpb24oJy0tcmVmcmVzaCA8cmVmcmVzaFRva2VuPicsICdVc2UgYSByZWZyZXNoIHRva2VuIGluc3RlYWQgb2YgbG9naW4gY3JlZGVudGlhbHMnKVxuICAgIC5vcHRpb24oJy0tb3JnIDxvcmdJZD4nLCAnU3dpdGNoIHRvIGEgc3BlY2lmaWMgb3JnYW5pemF0aW9uIGFmdGVyIGxvZ2luJylcbiAgICAub3B0aW9uKCctLXVybCA8dXJsPicsICdQbGF0Zm9ybSBiYXNlIFVSTCcsIHByb2Nlc3MuZW52LlBMQVRGT1JNX0JBU0VfVVJMIHx8ICdodHRwczovL2xvY2FsaG9zdDo4NDQzJykpXG4gICAgLm9wdGlvbignLS1xdWlldCcsICdPbmx5IHByaW50IHRoZSBleHBvcnQgc3RhdGVtZW50ICh1c2VmdWwgZm9yIGV2YWwpJylcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBpc1JlZnJlc2ggPSAhIW9wdGlvbnMucmVmcmVzaDtcbiAgICAgIGNvbnN0IHF1aWV0ID0gb3B0aW9ucy5xdWlldCA/PyBmYWxzZTtcbiAgICAgIGNvbnN0IGV4ZWN1dGlvbklkID0gcHJpbnRDb21tYW5kSGVhZGVyKFxuICAgICAgICBpc1JlZnJlc2ggPyAnVG9rZW4gUmVmcmVzaCcgOiAnTG9naW4nLFxuICAgICAgICBpc1JlZnJlc2ggPyAnVG9rZW4gUmVmcmVzaCcgOiAnUGxhdGZvcm0gQXV0aGVudGljYXRpb24nLFxuICAgICAgICB7IHF1aWV0IH0sXG4gICAgICApO1xuXG4gICAgICAvLyBTRUNVUklUWTogbG9naW4vcmVmcmVzaCBQT1NUIHBsYWludGV4dCBwYXNzd29yZHMgYW5kIEpXVHMuIE5ldmVyIHNlbmQgdGhlbVxuICAgICAgLy8gb3ZlciBhbiB1bnZlcmlmaWVkIFRMUyBjb25uZWN0aW9uIGluIHByb2R1Y3Rpb24g4oCUIGEgTUlUTSB3b3VsZCBoYXJ2ZXN0IHRoZW0uXG4gICAgICAvLyBJbiBub24tcHJvZHVjdGlvbiwgLS1uby12ZXJpZnktc3NsIGlzIHN0aWxsIGhvbm9yZWQgKHNlbGYtc2lnbmVkIGRldiBwbGF0Zm9ybXMpLlxuICAgICAgYXNzZXJ0Q3JlZGVudGlhbFRsc0FsbG93ZWQob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICAvLyBDcmVkZW50aWFscyBtYXkgY29tZSBmcm9tIGZsYWdzIE9SIHRoZSBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEXG4gICAgICAvLyBlbnYgdmFycyAoc28gdGhlIHBhc3N3b3JkIG5lZWQgbm90IGFwcGVhciBpbiBzaGVsbCBoaXN0b3J5IC8gYHBzYCkuXG4gICAgICBjb25zdCB7IGlkZW50aWZpZXIsIHBhc3N3b3JkIH0gPSByZXNvbHZlQ3JlZGVudGlhbHMob3B0aW9ucyk7XG5cbiAgICAgIGxldCBsb2dpblN1Y2NlZWRlZCA9IGZhbHNlO1xuICAgICAgdHJ5IHtcblxuICAgICAgICAvLyBWYWxpZGF0ZSByZXF1aXJlZCBvcHRpb25zXG4gICAgICAgIGlmICghaXNSZWZyZXNoICYmICghaWRlbnRpZmllciB8fCAhcGFzc3dvcmQpKSB7XG4gICAgICAgICAgcHJpbnRFcnJvcignTG9naW4gcmVxdWlyZXMgLS1pZGVudGlmaWVyIGFuZCAtLXBhc3N3b3JkIChvciBQTEFURk9STV9JREVOVElGSUVSL1BMQVRGT1JNX1BBU1NXT1JEIGVudiksIG9yIC0tcmVmcmVzaCA8dG9rZW4+Jyk7XG4gICAgICAgICAgcHJvY2Vzcy5leGl0KEVSUk9SX0NPREVTLkFVVEhFTlRJQ0FUSU9OKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzUmVmcmVzaCAmJiBvcHRpb25zLnBhc3N3b3JkKSB7XG4gICAgICAgICAgcHJpbnRXYXJuaW5nKCdQYXNzaW5nIC0tcGFzc3dvcmQgb24gdGhlIGNvbW1hbmQgbGluZSBjYW4gZXhwb3NlIGl0IHZpYSBzaGVsbCBoaXN0b3J5OyBwcmVmZXIgdGhlIFBMQVRGT1JNX1BBU1NXT1JEIGVudiB2YXIuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSYXRlIGxpbWl0aW5nIOKAlCBwcmV2ZW50IGJydXRlIGZvcmNlIChsb2dpbiBvbmx5KVxuICAgICAgICBpZiAoIWlzUmVmcmVzaCkge1xuICAgICAgICAgIGNvbnN0IHJhdGVMaW1pdE1zZyA9IGNoZWNrQXV0aFJhdGVMaW1pdChpZGVudGlmaWVyLCBvcHRpb25zLnVybCk7XG4gICAgICAgICAgaWYgKHJhdGVMaW1pdE1zZykge1xuICAgICAgICAgICAgcHJpbnRFcnJvcihyYXRlTGltaXRNc2cpO1xuICAgICAgICAgICAgcHJvY2Vzcy5leGl0KEVSUk9SX0NPREVTLkFVVEhFTlRJQ0FUSU9OKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXF1aWV0KSB7XG4gICAgICAgICAgcHJpbnRJbmZvKGlzUmVmcmVzaCA/ICdSZWZyZXNoaW5nIGFjY2VzcyB0b2tlbicgOiAnQXV0aGVudGljYXRpbmcnLCB7XG4gICAgICAgICAgICAuLi4oaWRlbnRpZmllciA/IHsgaWRlbnRpZmllciB9IDoge30pLFxuICAgICAgICAgICAgdXJsOiBvcHRpb25zLnVybCxcbiAgICAgICAgICAgIHZlcmlmeVNzbDogb3B0aW9ucy52ZXJpZnlTc2wsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBodHRwc0FnZW50ID0gY3JlZGVudGlhbEh0dHBzQWdlbnQob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICAgIGxldCB0b2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChpc1JlZnJlc2gpIHtcbiAgICAgICAgICBjb25zdCByZWZyZXNoVXJsID0gYCR7b3B0aW9ucy51cmx9L2FwaS9hdXRoL3JlZnJlc2hgO1xuICAgICAgICAgIHByaW50RGVidWcoJ1BPU1QnLCB7IHVybDogcmVmcmVzaFVybCB9KTtcblxuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MucG9zdDxBdXRoUmVzcG9uc2U+KFxuICAgICAgICAgICAgcmVmcmVzaFVybCxcbiAgICAgICAgICAgIHsgcmVmcmVzaFRva2VuOiBvcHRpb25zLnJlZnJlc2ggfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICAgICAgICAgIGh0dHBzQWdlbnQsXG4gICAgICAgICAgICAgIHRpbWVvdXQ6IFRJTUVPVVRTLkhUVFBfUkVRVUVTVCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRva2VuID0gcmVzcG9uc2UuZGF0YT8uZGF0YT8uYWNjZXNzVG9rZW47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gaWRlbnRpZmllci9wYXNzd29yZCB2YWxpZGF0ZWQgbm9uLW51bGwgYWJvdmUgKHRoZSBgIWlzUmVmcmVzaGAgZ3VhcmQpLlxuICAgICAgICAgIHRva2VuID0gYXdhaXQgcG9zdExvZ2luKHtcbiAgICAgICAgICAgIHVybDogb3B0aW9ucy51cmwsXG4gICAgICAgICAgICBpZGVudGlmaWVyOiBpZGVudGlmaWVyISxcbiAgICAgICAgICAgIHBhc3N3b3JkOiBwYXNzd29yZCEsXG4gICAgICAgICAgICBodHRwc0FnZW50LFxuICAgICAgICAgICAgdGltZW91dDogVElNRU9VVFMuSFRUUF9SRVFVRVNULFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0b2tlbikge1xuICAgICAgICAgIGlmICghaXNSZWZyZXNoKSByZWNvcmRBdXRoRmFpbHVyZShpZGVudGlmaWVyLCBvcHRpb25zLnVybCk7XG4gICAgICAgICAgcHJpbnRFcnJvcihgJHtpc1JlZnJlc2ggPyAnVG9rZW4gcmVmcmVzaCcgOiAnTG9naW4nfSBmYWlsZWQ6IG5vIGFjY2VzcyB0b2tlbiBpbiByZXNwb25zZWApO1xuICAgICAgICAgIHByb2Nlc3MuZXhpdChFUlJPUl9DT0RFUy5BVVRIRU5USUNBVElPTik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzUmVmcmVzaCkgcmVjb3JkQXV0aFN1Y2Nlc3MoaWRlbnRpZmllciwgb3B0aW9ucy51cmwpO1xuICAgICAgICAvLyBQYXN0IHRoaXMgcG9pbnQgYXV0aGVudGljYXRpb24gaGFzIGFscmVhZHkgc3VjY2VlZGVkIOKAlCBhIGxhdGVyIGZhaWx1cmVcbiAgICAgICAgLy8gKGUuZy4gdGhlIC0tb3JnIHN3aXRjaCBiZWxvdykgbXVzdCBOT1QgYmUgcmVjb3JkZWQgYXMgYW4gYXV0aCBmYWlsdXJlLFxuICAgICAgICAvLyBvciBhIHZhbGlkLWNyZWRlbnRpYWwgdXNlciB3b3VsZCBhY2NydWUgdG93YXJkIGJydXRlLWZvcmNlIGxvY2tvdXQuXG4gICAgICAgIGxvZ2luU3VjY2VlZGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBTd2l0Y2ggdG8gYSBzcGVjaWZpYyBvcmdhbml6YXRpb24gaWYgLS1vcmcgaXMgcHJvdmlkZWRcbiAgICAgICAgaWYgKG9wdGlvbnMub3JnKSB7XG4gICAgICAgICAgaWYgKCFxdWlldCkge1xuICAgICAgICAgICAgcHJpbnRJbmZvKCdTd2l0Y2hpbmcgdG8gb3JnYW5pemF0aW9uJywgeyBvcmdJZDogb3B0aW9ucy5vcmcgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdG9rZW4gPSBhd2FpdCBzd2l0Y2hPcmdhbml6YXRpb24oe1xuICAgICAgICAgICAgdXJsOiBvcHRpb25zLnVybCxcbiAgICAgICAgICAgIG9yZ0lkOiBvcHRpb25zLm9yZyxcbiAgICAgICAgICAgIGFjY2Vzc1Rva2VuOiB0b2tlbixcbiAgICAgICAgICAgIGh0dHBzQWdlbnQsXG4gICAgICAgICAgICB0aW1lb3V0OiBUSU1FT1VUUy5IVFRQX1JFUVVFU1QsXG4gICAgICAgICAgICBxdWlldCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcXVpZXQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRTdWNjZXNzKGlzUmVmcmVzaCA/ICdUb2tlbiByZWZyZXNoZWQgc3VjY2Vzc2Z1bGx5JyA6ICdMb2dpbiBzdWNjZXNzZnVsJyk7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5sb2coYGV4cG9ydCBQTEFURk9STV9UT0tFTj0ke3Rva2VufWApO1xuXG4gICAgICAgIGlmICghcXVpZXQpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRJbmZvKCdUaXA6IFJ1biB0aGUgZm9sbG93aW5nIHRvIHNldCB0aGUgdG9rZW4gaW4geW91ciBzaGVsbDonKTtcbiAgICAgICAgICBjb25zdCBvcmdGbGFnID0gb3B0aW9ucy5vcmcgPyBgIC0tb3JnICR7b3B0aW9ucy5vcmd9YCA6ICcnO1xuICAgICAgICAgIGlmIChpc1JlZnJlc2gpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGdyZWVuKGAgIGV2YWwgJChwaXBlbGluZS1tYW5hZ2VyIGF1dGggbG9naW4gLS1yZWZyZXNoICc8cmVmcmVzaC10b2tlbj4nJHtvcmdGbGFnfSAtLXF1aWV0KWApKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5sb2coZ3JlZW4oYCAgZXZhbCAkKHBpcGVsaW5lLW1hbmFnZXIgYXV0aCBsb2dpbiAtdSAke2lkZW50aWZpZXJ9IC1wICcqKionJHtvcmdGbGFnfSAtLXF1aWV0KWApKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEtleSB0aGUgZmFpbHVyZSB0byAoaWRlbnRpZmllciwgdXJsKSBsaWtlIHRoZSBjaGVjay9zdWNjZXNzL25vLXRva2VuXG4gICAgICAgIC8vIHBhdGhzIOKAlCBhIGJhZC1wYXNzd29yZCA0MDEgdGhyb3dzIHRvIGhlcmUsIHNvIGtleWluZyBpdCB0byB0aGUgc2hhcmVkXG4gICAgICAgIC8vIGRlZmF1bHQgYnVja2V0IG1lYW50IGJydXRlLWZvcmNlIGF0dGVtcHRzIG5ldmVyIGFjY3J1ZWQgdG93YXJkIGxvY2tvdXQuXG4gICAgICAgIC8vIFNraXAgd2hlbiBsb2dpbiBhbHJlYWR5IHN1Y2NlZWRlZCAoYSBmYWlsZWQgcG9zdC1sb2dpbiAtLW9yZyBzd2l0Y2ggaXNcbiAgICAgICAgLy8gbm90IGFuIGF1dGhlbnRpY2F0aW9uIGZhaWx1cmUpLlxuICAgICAgICBpZiAoIWlzUmVmcmVzaCAmJiAhbG9naW5TdWNjZWVkZWQpIHJlY29yZEF1dGhGYWlsdXJlKGlkZW50aWZpZXIsIG9wdGlvbnMudXJsKTtcbiAgICAgICAgLy8gUHJvdmlkZSBhIGNsZWFyIGZhaWx1cmUgbWVzc2FnZSBmb3IgYXV0aCBlcnJvcnNcbiAgICAgICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnJvcikpIHtcbiAgICAgICAgICBjb25zdCBzdGF0dXMgPSBlcnJvci5yZXNwb25zZT8uc3RhdHVzO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSAoZXJyb3IucmVzcG9uc2U/LmRhdGEgYXMgeyBtZXNzYWdlPzogc3RyaW5nIH0pPy5tZXNzYWdlO1xuXG4gICAgICAgICAgcHJpbnRFcnJvcihgJHtpc1JlZnJlc2ggPyAnVG9rZW4gcmVmcmVzaCcgOiAnTG9naW4nfSBmYWlsZWRgLCB7XG4gICAgICAgICAgICBzdGF0dXM6IHN0YXR1cyA/PyAnbm8gcmVzcG9uc2UnLFxuICAgICAgICAgICAgLi4uKG1lc3NhZ2UgPyB7IG1lc3NhZ2UgfSA6IHt9KSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoRVJST1JfQ09ERVMuQVVUSEVOVElDQVRJT04pO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkFVVEhFTlRJQ0FUSU9OLCB7XG4gICAgICAgICAgZGVidWc6IHByb2dyYW0ub3B0cygpLmRlYnVnLFxuICAgICAgICAgIGV4aXQ6IHRydWUsXG4gICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgY29tbWFuZDogJ2xvZ2luJyxcbiAgICAgICAgICAgIGV4ZWN1dGlvbklkLFxuICAgICAgICAgICAgaWRlbnRpZmllcjogb3B0aW9ucy5pZGVudGlmaWVyLFxuICAgICAgICAgICAgdXJsOiBvcHRpb25zLnVybCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the `new-plugin` command — scaffold a local plugin directory
4
+ * (`config.yaml`, `plugin-spec.yaml`, and a starter `Dockerfile`) that
5
+ * `validate-plugin` accepts and `upload-plugin` can package.
6
+ *
7
+ * Usage:
8
+ * pipeline-manager plugin new --name my-linter --category quality
9
+ * pipeline-manager plugin new --name approve --type ManualApprovalStep
10
+ */
11
+ export declare function newPlugin(program: Command): void;
12
+ //# sourceMappingURL=new-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new-plugin.d.ts","sourceRoot":"","sources":["../../src/commands/new-plugin.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2GhD"}
@@ -0,0 +1,129 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { Command } from 'commander';
6
+ import YAML from 'yaml';
7
+ import { printCommandHeader } from '../utils/command-utils.js';
8
+ import { ERROR_CODES, handleError, ValidationError } from '../utils/error-handler.js';
9
+ import { printInfo, printSection, printSuccess, fileExists, ensureOutputDirectory } from '../utils/output-utils.js';
10
+ const PLUGIN_TYPES = ['CodeBuildStep', 'ShellStep', 'ManualApprovalStep'];
11
+ const COMPUTE_TYPES = ['SMALL', 'MEDIUM', 'LARGE', 'X2_LARGE'];
12
+ const BUILD_TYPES = ['build_image', 'prebuilt', 'metadata_only'];
13
+ /**
14
+ * Register the `new-plugin` command — scaffold a local plugin directory
15
+ * (`config.yaml`, `plugin-spec.yaml`, and a starter `Dockerfile`) that
16
+ * `validate-plugin` accepts and `upload-plugin` can package.
17
+ *
18
+ * Usage:
19
+ * pipeline-manager plugin new --name my-linter --category quality
20
+ * pipeline-manager plugin new --name approve --type ManualApprovalStep
21
+ */
22
+ export function newPlugin(program) {
23
+ program
24
+ .command('new')
25
+ .description('Scaffold a local plugin directory (config.yaml, plugin-spec.yaml, Dockerfile)')
26
+ .requiredOption('--name <name>', 'Plugin name (lowercase letters, digits, hyphens)')
27
+ .option('--category <category>', 'Plugin category (e.g. quality, security, language)', 'general')
28
+ .option('--type <type>', `Plugin type: ${PLUGIN_TYPES.join(' | ')}`, 'CodeBuildStep')
29
+ .option('--compute <compute>', `Compute type: ${COMPUTE_TYPES.join(' | ')}`, 'SMALL')
30
+ .option('--build-type <buildType>', `Build type: ${BUILD_TYPES.join(' | ')}`, 'build_image')
31
+ .option('--dir <path>', 'Target directory (default ./<name>)')
32
+ .option('--force', 'Overwrite an existing directory', false)
33
+ .action((options) => {
34
+ const executionId = printCommandHeader('New Plugin');
35
+ try {
36
+ const name = options.name ?? '';
37
+ // Canonical plugin-name pattern (matches validate-plugin, upload-plugin,
38
+ // and the server's NAME_PATTERN).
39
+ if (!/^[a-z0-9-]+$/.test(name)) {
40
+ throw new ValidationError('Plugin name must contain only lowercase letters, digits, and hyphens (/^[a-z0-9-]+$/)');
41
+ }
42
+ const pluginType = options.type ?? 'CodeBuildStep';
43
+ if (!PLUGIN_TYPES.includes(pluginType))
44
+ throw new ValidationError(`--type must be one of: ${PLUGIN_TYPES.join(', ')}`);
45
+ const computeType = options.compute ?? 'SMALL';
46
+ if (!COMPUTE_TYPES.includes(computeType))
47
+ throw new ValidationError(`--compute must be one of: ${COMPUTE_TYPES.join(', ')}`);
48
+ const buildType = options.buildType ?? 'build_image';
49
+ if (!BUILD_TYPES.includes(buildType))
50
+ throw new ValidationError(`--build-type must be one of: ${BUILD_TYPES.join(', ')}`);
51
+ const targetDir = path.resolve(options.dir ?? `./${name}`);
52
+ if (fileExists(targetDir) && !options.force) {
53
+ throw new ValidationError(`Directory already exists: ${targetDir} (use --force to overwrite)`);
54
+ }
55
+ ensureOutputDirectory(targetDir);
56
+ const isApproval = pluginType === 'ManualApprovalStep';
57
+ // Dockerfile only for image builds of a real build step.
58
+ const needsDockerfile = buildType === 'build_image' && !isApproval;
59
+ // config.yaml — build manifest.
60
+ const config = { pluginSpec: 'plugin-spec.yaml', buildType };
61
+ if (needsDockerfile)
62
+ config.dockerfile = 'Dockerfile';
63
+ fs.writeFileSync(path.join(targetDir, 'config.yaml'), YAML.stringify(config), 'utf-8');
64
+ // plugin-spec.yaml — the PluginSpec.
65
+ const spec = {
66
+ name,
67
+ version: '1.0.0',
68
+ description: `${name} plugin`,
69
+ keywords: [],
70
+ category: options.category ?? 'general',
71
+ pluginType,
72
+ computeType,
73
+ timeout: isApproval ? 0 : 10,
74
+ failureBehavior: 'fail',
75
+ secrets: [],
76
+ };
77
+ if (!isApproval) {
78
+ spec.installCommands = ['echo "install step — add your setup commands"'];
79
+ spec.commands = [`echo "run step for ${name} — replace with real commands"`];
80
+ if (needsDockerfile)
81
+ spec.dockerfile = 'Dockerfile';
82
+ }
83
+ fs.writeFileSync(path.join(targetDir, 'plugin-spec.yaml'), YAML.stringify(spec), 'utf-8');
84
+ // Starter Dockerfile.
85
+ if (needsDockerfile) {
86
+ const dockerfile = [
87
+ `# Dockerfile for the ${name} plugin.`,
88
+ '# The base image provides the toolchain your commands need — keep it minimal and pinned.',
89
+ 'FROM alpine:3.20',
90
+ '',
91
+ '# TODO: install the tools your plugin-spec commands invoke, e.g.:',
92
+ '# RUN apk add --no-cache python3',
93
+ '',
94
+ 'WORKDIR /workspace',
95
+ '',
96
+ ].join('\n');
97
+ fs.writeFileSync(path.join(targetDir, 'Dockerfile'), dockerfile, 'utf-8');
98
+ }
99
+ // README.
100
+ const relDir = options.dir ?? `./${name}`;
101
+ fs.writeFileSync(path.join(targetDir, 'README.md'), [
102
+ `# ${name}`,
103
+ '',
104
+ `${name} plugin.`,
105
+ '',
106
+ 'Validate before upload:',
107
+ '',
108
+ ` pipeline-manager plugin validate --dir ${relDir}`,
109
+ '',
110
+ 'Package and upload:',
111
+ '',
112
+ ` (cd ${relDir} && zip -r ../${name}.zip .)`,
113
+ ` pipeline-manager plugin upload --file ${name}.zip --organization <org>`,
114
+ '',
115
+ ].join('\n'), 'utf-8');
116
+ printSection('Scaffolded plugin', targetDir);
117
+ printInfo('Created files', { files: ['config.yaml', 'plugin-spec.yaml', ...(needsDockerfile ? ['Dockerfile'] : []), 'README.md'] });
118
+ printSuccess('Plugin scaffold created — edit plugin-spec.yaml then run validate-plugin', { executionId, dir: targetDir });
119
+ }
120
+ catch (err) {
121
+ handleError(err, err instanceof ValidationError ? ERROR_CODES.VALIDATION : ERROR_CODES.GENERAL, {
122
+ debug: program.opts().debug,
123
+ exit: true,
124
+ context: { command: 'new-plugin', executionId },
125
+ });
126
+ }
127
+ });
128
+ }
129
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LXBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9uZXctcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3BCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN0RixPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFZcEgsTUFBTSxZQUFZLEdBQUcsQ0FBQyxlQUFlLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixDQUFDLENBQUM7QUFDMUUsTUFBTSxhQUFhLEdBQUcsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztBQUMvRCxNQUFNLFdBQVcsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFFakU7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLE9BQWdCO0lBQ3hDLE9BQU87U0FDSixPQUFPLENBQUMsS0FBSyxDQUFDO1NBQ2QsV0FBVyxDQUFDLCtFQUErRSxDQUFDO1NBQzVGLGNBQWMsQ0FBQyxlQUFlLEVBQUUsa0RBQWtELENBQUM7U0FDbkYsTUFBTSxDQUFDLHVCQUF1QixFQUFFLG9EQUFvRCxFQUFFLFNBQVMsQ0FBQztTQUNoRyxNQUFNLENBQUMsZUFBZSxFQUFFLGdCQUFn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QkFDVixPQUFPLEVBQUUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRTthQUNoRCxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IFlBTUwgZnJvbSAneWFtbCc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBwcmludEluZm8sIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzLCBmaWxlRXhpc3RzLCBlbnN1cmVPdXRwdXREaXJlY3RvcnkgfSBmcm9tICcuLi91dGlscy9vdXRwdXQtdXRpbHMuanMnO1xuXG5pbnRlcmZhY2UgTmV3UGx1Z2luT3B0aW9ucyB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIGNhdGVnb3J5Pzogc3RyaW5nO1xuICB0eXBlPzogc3RyaW5nO1xuICBjb21wdXRlPzogc3RyaW5nO1xuICBidWlsZFR5cGU/OiBzdHJpbmc7XG4gIGRpcj86IHN0cmluZztcbiAgZm9yY2U/OiBib29sZWFuO1xufVxuXG5jb25zdCBQTFVHSU5fVFlQRVMgPSBbJ0NvZGVCdWlsZFN0ZXAnLCAnU2hlbGxTdGVwJywgJ01hbnVhbEFwcHJvdmFsU3RlcCddO1xuY29uc3QgQ09NUFVURV9UWVBFUyA9IFsnU01BTEwnLCAnTUVESVVNJywgJ0xBUkdFJywgJ1gyX0xBUkdFJ107XG5jb25zdCBCVUlMRF9UWVBFUyA9IFsnYnVpbGRfaW1hZ2UnLCAncHJlYnVpbHQnLCAnbWV0YWRhdGFfb25seSddO1xuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBgbmV3LXBsdWdpbmAgY29tbWFuZCDigJQgc2NhZmZvbGQgYSBsb2NhbCBwbHVnaW4gZGlyZWN0b3J5XG4gKiAoYGNvbmZpZy55YW1sYCwgYHBsdWdpbi1zcGVjLnlhbWxgLCBhbmQgYSBzdGFydGVyIGBEb2NrZXJmaWxlYCkgdGhhdFxuICogYHZhbGlkYXRlLXBsdWdpbmAgYWNjZXB0cyBhbmQgYHVwbG9hZC1wbHVnaW5gIGNhbiBwYWNrYWdlLlxuICpcbiAqIFVzYWdlOlxuICogICBwaXBlbGluZS1tYW5hZ2VyIHBsdWdpbiBuZXcgLS1uYW1lIG15LWxpbnRlciAtLWNhdGVnb3J5IHF1YWxpdHlcbiAqICAgcGlwZWxpbmUtbWFuYWdlciBwbHVnaW4gbmV3IC0tbmFtZSBhcHByb3ZlIC0tdHlwZSBNYW51YWxBcHByb3ZhbFN0ZXBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5ld1BsdWdpbihwcm9ncmFtOiBDb21tYW5kKTogdm9pZCB7XG4gIHByb2dyYW1cbiAgICAuY29tbWFuZCgnbmV3JylcbiAgICAuZGVzY3JpcHRpb24oJ1NjYWZmb2xkIGEgbG9jYWwgcGx1Z2luIGRpcmVjdG9yeSAoY29uZmlnLnlhbWwsIHBsdWdpbi1zcGVjLnlhbWwsIERvY2tlcmZpbGUpJylcbiAgICAucmVxdWlyZWRPcHRpb24oJy0tbmFtZSA8bmFtZT4nLCAnUGx1Z2luIG5hbWUgKGxvd2VyY2FzZSBsZXR0ZXJzLCBkaWdpdHMsIGh5cGhlbnMpJylcbiAgICAub3B0aW9uKCctLWNhdGVnb3J5IDxjYXRlZ29yeT4nLCAnUGx1Z2luIGNhdGVnb3J5IChlLmcuIHF1YWxpdHksIHNlY3VyaXR5LCBsYW5ndWFnZSknLCAnZ2VuZXJhbCcpXG4gICAgLm9wdGlvbignLS10eXBlIDx0eXBlPicsIGBQbHVnaW4gdHlwZTogJHtQTFVHSU5fVFlQRVMuam9pbignIHwgJyl9YCwgJ0NvZGVCdWlsZFN0ZXAnKVxuICAgIC5vcHRpb24oJy0tY29tcHV0ZSA8Y29tcHV0ZT4nLCBgQ29tcHV0ZSB0eXBlOiAke0NPTVBVVEVfVFlQRVMuam9pbignIHwgJyl9YCwgJ1NNQUxMJylcbiAgICAub3B0aW9uKCctLWJ1aWxkLXR5cGUgPGJ1aWxkVHlwZT4nLCBgQnVpbGQgdHlwZTogJHtCVUlMRF9UWVBFUy5qb2luKCcgfCAnKX1gLCAnYnVpbGRfaW1hZ2UnKVxuICAgIC5vcHRpb24oJy0tZGlyIDxwYXRoPicsICdUYXJnZXQgZGlyZWN0b3J5IChkZWZhdWx0IC4vPG5hbWU+KScpXG4gICAgLm9wdGlvbignLS1mb3JjZScsICdPdmVyd3JpdGUgYW4gZXhpc3RpbmcgZGlyZWN0b3J5JywgZmFsc2UpXG4gICAgLmFjdGlvbigob3B0aW9uczogTmV3UGx1Z2luT3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ05ldyBQbHVnaW4nKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBvcHRpb25zLm5hbWUgPz8gJyc7XG4gICAgICAgIC8vIENhbm9uaWNhbCBwbHVnaW4tbmFtZSBwYXR0ZXJuIChtYXRjaGVzIHZhbGlkYXRlLXBsdWdpbiwgdXBsb2FkLXBsdWdpbixcbiAgICAgICAgLy8gYW5kIHRoZSBzZXJ2ZXIncyBOQU1FX1BBVFRFUk4pLlxuICAgICAgICBpZiAoIS9eW2EtejAtOS1dKyQvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdQbHVnaW4gbmFtZSBtdXN0IGNvbnRhaW4gb25seSBsb3dlcmNhc2UgbGV0dGVycywgZGlnaXRzLCBhbmQgaHlwaGVucyAoL15bYS16MC05LV0rJC8pJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGx1Z2luVHlwZSA9IG9wdGlvbnMudHlwZSA/PyAnQ29kZUJ1aWxkU3RlcCc7XG4gICAgICAgIGlmICghUExVR0lOX1RZUEVTLmluY2x1ZGVzKHBsdWdpblR5cGUpKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGAtLXR5cGUgbXVzdCBiZSBvbmUgb2Y6ICR7UExVR0lOX1RZUEVTLmpvaW4oJywgJyl9YCk7XG4gICAgICAgIGNvbnN0IGNvbXB1dGVUeXBlID0gb3B0aW9ucy5jb21wdXRlID8/ICdTTUFMTCc7XG4gICAgICAgIGlmICghQ09NUFVURV9UWVBFUy5pbmNsdWRlcyhjb21wdXRlVHlwZSkpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYC0tY29tcHV0ZSBtdXN0IGJlIG9uZSBvZjogJHtDT01QVVRFX1RZUEVTLmpvaW4oJywgJyl9YCk7XG4gICAgICAgIGNvbnN0IGJ1aWxkVHlwZSA9IG9wdGlvbnMuYnVpbGRUeXBlID8/ICdidWlsZF9pbWFnZSc7XG4gICAgICAgIGlmICghQlVJTERfVFlQRVMuaW5jbHVkZXMoYnVpbGRUeXBlKSkgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihgLS1idWlsZC10eXBlIG11c3QgYmUgb25lIG9mOiAke0JVSUxEX1RZUEVTLmpvaW4oJywgJyl9YCk7XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0RGlyID0gcGF0aC5yZXNvbHZlKG9wdGlvbnMuZGlyID8/IGAuLyR7bmFtZX1gKTtcbiAgICAgICAgaWYgKGZpbGVFeGlzdHModGFyZ2V0RGlyKSAmJiAhb3B0aW9ucy5mb3JjZSkge1xuICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYERpcmVjdG9yeSBhbHJlYWR5IGV4aXN0czogJHt0YXJnZXREaXJ9ICh1c2UgLS1mb3JjZSB0byBvdmVyd3JpdGUpYCk7XG4gICAgICAgIH1cbiAgICAgICAgZW5zdXJlT3V0cHV0RGlyZWN0b3J5KHRhcmdldERpcik7XG5cbiAgICAgICAgY29uc3QgaXNBcHByb3ZhbCA9IHBsdWdpblR5cGUgPT09ICdNYW51YWxBcHByb3ZhbFN0ZXAnO1xuICAgICAgICAvLyBEb2NrZXJmaWxlIG9ubHkgZm9yIGltYWdlIGJ1aWxkcyBvZiBhIHJlYWwgYnVpbGQgc3RlcC5cbiAgICAgICAgY29uc3QgbmVlZHNEb2NrZXJmaWxlID0gYnVpbGRUeXBlID09PSAnYnVpbGRfaW1hZ2UnICYmICFpc0FwcHJvdmFsO1xuXG4gICAgICAgIC8vIGNvbmZpZy55YW1sIOKAlCBidWlsZCBtYW5pZmVzdC5cbiAgICAgICAgY29uc3QgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHsgcGx1Z2luU3BlYzogJ3BsdWdpbi1zcGVjLnlhbWwnLCBidWlsZFR5cGUgfTtcbiAgICAgICAgaWYgKG5lZWRzRG9ja2VyZmlsZSkgY29uZmlnLmRvY2tlcmZpbGUgPSAnRG9ja2VyZmlsZSc7XG4gICAgICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKHRhcmdldERpciwgJ2NvbmZpZy55YW1sJyksIFlBTUwuc3RyaW5naWZ5KGNvbmZpZyksICd1dGYtOCcpO1xuXG4gICAgICAgIC8vIHBsdWdpbi1zcGVjLnlhbWwg4oCUIHRoZSBQbHVnaW5TcGVjLlxuICAgICAgICBjb25zdCBzcGVjOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHZlcnNpb246ICcxLjAuMCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246IGAke25hbWV9IHBsdWdpbmAsXG4gICAgICAgICAga2V5d29yZHM6IFtdIGFzIHN0cmluZ1tdLFxuICAgICAgICAgIGNhdGVnb3J5OiBvcHRpb25zLmNhdGVnb3J5ID8/ICdnZW5lcmFsJyxcbiAgICAgICAgICBwbHVnaW5UeXBlLFxuICAgICAgICAgIGNvbXB1dGVUeXBlLFxuICAgICAgICAgIHRpbWVvdXQ6IGlzQXBwcm92YWwgPyAwIDogMTAsXG4gICAgICAgICAgZmFpbHVyZUJlaGF2aW9yOiAnZmFpbCcsXG4gICAgICAgICAgc2VjcmV0czogW10gYXMgdW5rbm93bltdLFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIWlzQXBwcm92YWwpIHtcbiAgICAgICAgICBzcGVjLmluc3RhbGxDb21tYW5kcyA9IFsnZWNobyBcImluc3RhbGwgc3RlcCDigJQgYWRkIHlvdXIgc2V0dXAgY29tbWFuZHNcIiddO1xuICAgICAgICAgIHNwZWMuY29tbWFuZHMgPSBbYGVjaG8gXCJydW4gc3RlcCBmb3IgJHtuYW1lfSDigJQgcmVwbGFjZSB3aXRoIHJlYWwgY29tbWFuZHNcImBdO1xuICAgICAgICAgIGlmIChuZWVkc0RvY2tlcmZpbGUpIHNwZWMuZG9ja2VyZmlsZSA9ICdEb2NrZXJmaWxlJztcbiAgICAgICAgfVxuICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbih0YXJnZXREaXIsICdwbHVnaW4tc3BlYy55YW1sJyksIFlBTUwuc3RyaW5naWZ5KHNwZWMpLCAndXRmLTgnKTtcblxuICAgICAgICAvLyBTdGFydGVyIERvY2tlcmZpbGUuXG4gICAgICAgIGlmIChuZWVkc0RvY2tlcmZpbGUpIHtcbiAgICAgICAgICBjb25zdCBkb2NrZXJmaWxlID0gW1xuICAgICAgICAgICAgYCMgRG9ja2VyZmlsZSBmb3IgdGhlICR7bmFtZX0gcGx1Z2luLmAsXG4gICAgICAgICAgICAnIyBUaGUgYmFzZSBpbWFnZSBwcm92aWRlcyB0aGUgdG9vbGNoYWluIHlvdXIgY29tbWFuZHMgbmVlZCDigJQga2VlcCBpdCBtaW5pbWFsIGFuZCBwaW5uZWQuJyxcbiAgICAgICAgICAgICdGUk9NIGFscGluZTozLjIwJyxcbiAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgJyMgVE9ETzogaW5zdGFsbCB0aGUgdG9vbHMgeW91ciBwbHVnaW4tc3BlYyBjb21tYW5kcyBpbnZva2UsIGUuZy46JyxcbiAgICAgICAgICAgICcjIFJVTiBhcGsgYWRkIC0tbm8tY2FjaGUgcHl0aG9uMycsXG4gICAgICAgICAgICAnJyxcbiAgICAgICAgICAgICdXT1JLRElSIC93b3Jrc3BhY2UnLFxuICAgICAgICAgICAgJycsXG4gICAgICAgICAgXS5qb2luKCdcXG4nKTtcbiAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbih0YXJnZXREaXIsICdEb2NrZXJmaWxlJyksIGRvY2tlcmZpbGUsICd1dGYtOCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUkVBRE1FLlxuICAgICAgICBjb25zdCByZWxEaXIgPSBvcHRpb25zLmRpciA/PyBgLi8ke25hbWV9YDtcbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4odGFyZ2V0RGlyLCAnUkVBRE1FLm1kJyksIFtcbiAgICAgICAgICBgIyAke25hbWV9YCxcbiAgICAgICAgICAnJyxcbiAgICAgICAgICBgJHtuYW1lfSBwbHVnaW4uYCxcbiAgICAgICAgICAnJyxcbiAgICAgICAgICAnVmFsaWRhdGUgYmVmb3JlIHVwbG9hZDonLFxuICAgICAgICAgICcnLFxuICAgICAgICAgIGAgICAgcGlwZWxpbmUtbWFuYWdlciBwbHVnaW4gdmFsaWRhdGUgLS1kaXIgJHtyZWxEaXJ9YCxcbiAgICAgICAgICAnJyxcbiAgICAgICAgICAnUGFja2FnZSBhbmQgdXBsb2FkOicsXG4gICAgICAgICAgJycsXG4gICAgICAgICAgYCAgICAoY2QgJHtyZWxEaXJ9ICYmIHppcCAtciAuLi8ke25hbWV9LnppcCAuKWAsXG4gICAgICAgICAgYCAgICBwaXBlbGluZS1tYW5hZ2VyIHBsdWdpbiB1cGxvYWQgLS1maWxlICR7bmFtZX0uemlwIC0tb3JnYW5pemF0aW9uIDxvcmc+YCxcbiAgICAgICAgICAnJyxcbiAgICAgICAgXS5qb2luKCdcXG4nKSwgJ3V0Zi04Jyk7XG5cbiAgICAgICAgcHJpbnRTZWN0aW9uKCdTY2FmZm9sZGVkIHBsdWdpbicsIHRhcmdldERpcik7XG4gICAgICAgIHByaW50SW5mbygnQ3JlYXRlZCBmaWxlcycsIHsgZmlsZXM6IFsnY29uZmlnLnlhbWwnLCAncGx1Z2luLXNwZWMueWFtbCcsIC4uLihuZWVkc0RvY2tlcmZpbGUgPyBbJ0RvY2tlcmZpbGUnXSA6IFtdKSwgJ1JFQURNRS5tZCddIH0pO1xuICAgICAgICBwcmludFN1Y2Nlc3MoJ1BsdWdpbiBzY2FmZm9sZCBjcmVhdGVkIOKAlCBlZGl0IHBsdWdpbi1zcGVjLnlhbWwgdGhlbiBydW4gdmFsaWRhdGUtcGx1Z2luJywgeyBleGVjdXRpb25JZCwgZGlyOiB0YXJnZXREaXIgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyLCBlcnIgaW5zdGFuY2VvZiBWYWxpZGF0aW9uRXJyb3IgPyBFUlJPUl9DT0RFUy5WQUxJREFUSU9OIDogRVJST1JfQ09ERVMuR0VORVJBTCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHsgY29tbWFuZDogJ25ldy1wbHVnaW4nLCBleGVjdXRpb25JZCB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,25 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * CLI `pipeline-manager org export --id <orgId> --output <file>`.
4
+ *
5
+ * Fetches the GDPR portability dump from `GET /api/organization/:id/export`
6
+ * on the platform service and writes it to disk (or stdout). The endpoint
7
+ * is gated server-side * • System admins (admin/owner in the `system` org) may export any org.
8
+ * • Org admins / owners may export ONLY their own org.
9
+ * • Everything else gets 403.
10
+ *
11
+ * The CLI itself does no role checking the caller's PLATFORM_TOKEN drives
12
+ * what the server accepts. Run `pipeline-manager status` first to confirm
13
+ * the token's role + org.
14
+ *
15
+ * @example
16
+ * ```bash
17
+ * # Sysadmin: any org
18
+ * pipeline-manager org export --id org-acme --output acme.json
19
+ *
20
+ * # Org admin: own org only (server rejects other ids with 403)
21
+ * pipeline-manager org export --id org-acme --output acme.json
22
+ * ```
23
+ */
24
+ export declare function orgExport(program: Command): void;
25
+ //# sourceMappingURL=org-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-export.d.ts","sourceRoot":"","sources":["../../src/commands/org-export.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6EhD"}
@@ -0,0 +1,100 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { Command } from 'commander';
6
+ import pico from 'picocolors';
7
+ import { createAuthenticatedClient, printCommandHeader, printExecutionSummary, printSslWarning, validateEntityId, withSslOptions } from '../utils/command-utils.js';
8
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
9
+ import { printError, printInfo, printKeyValue, printSection, printSuccess } from '../utils/output-utils.js';
10
+ const { bold, green } = pico;
11
+ /**
12
+ * CLI `pipeline-manager org export --id <orgId> --output <file>`.
13
+ *
14
+ * Fetches the GDPR portability dump from `GET /api/organization/:id/export`
15
+ * on the platform service and writes it to disk (or stdout). The endpoint
16
+ * is gated server-side * • System admins (admin/owner in the `system` org) may export any org.
17
+ * • Org admins / owners may export ONLY their own org.
18
+ * • Everything else gets 403.
19
+ *
20
+ * The CLI itself does no role checking the caller's PLATFORM_TOKEN drives
21
+ * what the server accepts. Run `pipeline-manager status` first to confirm
22
+ * the token's role + org.
23
+ *
24
+ * @example
25
+ * ```bash
26
+ * # Sysadmin: any org
27
+ * pipeline-manager org export --id org-acme --output acme.json
28
+ *
29
+ * # Org admin: own org only (server rejects other ids with 403)
30
+ * pipeline-manager org export --id org-acme --output acme.json
31
+ * ```
32
+ */
33
+ export function orgExport(program) {
34
+ withSslOptions(program
35
+ .command('export')
36
+ .description('Export an organization\'s data as JSON (GDPR portability, ).')
37
+ .requiredOption('-i, --id <id>', 'Organization ID to export')
38
+ .option('-o, --output <file>', 'Output file path (default: org-<id>-export.json in CWD)'))
39
+ .action(async (options) => {
40
+ const executionId = printCommandHeader('Org Export');
41
+ try {
42
+ printSslWarning(options.verifySsl);
43
+ const orgId = validateEntityId(options.id, 'Organization');
44
+ const outputPath = options.output
45
+ ? path.resolve(options.output)
46
+ : path.resolve(process.cwd(), `org-${orgId}-export.json`);
47
+ printInfo('Request parameters', {
48
+ orgId,
49
+ output: outputPath,
50
+ });
51
+ const client = createAuthenticatedClient(options);
52
+ console.log('');
53
+ printSection('Fetching Export');
54
+ const startTime = Date.now();
55
+ // The endpoint streams a large JSON attachment for orgs with long
56
+ // histories. The ApiClient returns the parsed body directly, which
57
+ // for `application/json` is a JS object we re-serialize to disk.
58
+ const response = await client.get(`${client.getConfig().api.baseUrl}/api/organization/${encodeURIComponent(orgId)}/export`);
59
+ const duration = Date.now() - startTime;
60
+ if (!response || typeof response !== 'object') {
61
+ printError('Empty / unparseable export payload');
62
+ throw new Error(`Export returned no data for org ${orgId}`);
63
+ }
64
+ // Re-serialize so we keep the same pretty-printed shape the server
65
+ // produced (2-space indent matches the platform's handler) and so
66
+ // we don't lose Date precision on a round-trip through JSON.parse.
67
+ //
68
+ // GUARD: this writes the raw server payload straight to disk. The export
69
+ // payload must NEVER contain an AWS account id — orgId is the marketplace
70
+ // customerIdentifier, never an AWS account id. It is account-id-free today;
71
+ // if a future server change ever adds one, it must be stripped/redacted
72
+ // here BEFORE this write, not persisted through the CLI.
73
+ const json = JSON.stringify(response, null, 2);
74
+ fs.writeFileSync(outputPath, json, 'utf8');
75
+ const sizeKb = (json.length / 1024).toFixed(1);
76
+ const postgresTables = response.postgres && typeof response.postgres === 'object'
77
+ ? Object.keys(response.postgres).length
78
+ : 0;
79
+ console.log('');
80
+ printSection('Export Saved');
81
+ printKeyValue({
82
+ 'Org ID': green(bold(orgId)),
83
+ 'Output': outputPath,
84
+ 'Size': `${sizeKb} KB`,
85
+ 'Postgres tables': String(postgresTables),
86
+ 'Exported at': typeof response.exportedAt === 'string' ? response.exportedAt : '(not set)',
87
+ });
88
+ printExecutionSummary(executionId, duration);
89
+ printSuccess('Organization export complete', { path: outputPath });
90
+ }
91
+ catch (error) {
92
+ handleError(error, ERROR_CODES.API_REQUEST, {
93
+ debug: program.opts().debug,
94
+ exit: true,
95
+ context: { command: 'org-export', executionId, orgId: options.id },
96
+ });
97
+ }
98
+ });
99
+ }
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnLWV4cG9ydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9vcmctZXhwb3J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLElBQUksTUFBTSxZQUFZLENBQUM7QUFDOUIsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGtCQUFrQixFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwSyxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFNUcsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFFN0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsT0FBZ0I7SUFDeEMsY0FBYyxDQUFDLE9BQU87U0FDbkIsT0FBTyxDQUFDLFFBQVEsQ0FBQztTQUNqQixXQUFXLENBQUMsOERBQThELENBQUM7U0FDM0UsY0FBYyxDQUFDLGVBQWUsRUFBRSwyQkFBMkIsQ0FBQztTQUM1RCxNQUFNLENBQUMscUJBQXFCLEVBQUUseURBQXlELENBQUMsQ0FBQztTQUN6RixNQUFNLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQ3hCLE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRXJELElBQUks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LENBQUMsQ0FBQztZQUM3QyxZQUFZLENBQUMsOEJBQThCLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsSUFBSTtnQkFDVixPQUFPLEVBQUUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRTthQUNuRSxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCBwaWNvIGZyb20gJ3BpY29jb2xvcnMnO1xuaW1wb3J0IHsgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudCwgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludEV4ZWN1dGlvblN1bW1hcnksIHByaW50U3NsV2FybmluZywgdmFsaWRhdGVFbnRpdHlJZCwgd2l0aFNzbE9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRFcnJvciwgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbmNvbnN0IHsgYm9sZCwgZ3JlZW4gfSA9IHBpY287XG5cbi8qKlxuICogQ0xJICBgcGlwZWxpbmUtbWFuYWdlciBvcmcgZXhwb3J0IC0taWQgPG9yZ0lkPiAtLW91dHB1dCA8ZmlsZT5gLlxuICpcbiAqIEZldGNoZXMgdGhlIEdEUFIgcG9ydGFiaWxpdHkgZHVtcCBmcm9tIGBHRVQgL2FwaS9vcmdhbml6YXRpb24vOmlkL2V4cG9ydGBcbiAqIG9uIHRoZSBwbGF0Zm9ybSBzZXJ2aWNlIGFuZCB3cml0ZXMgaXQgdG8gZGlzayAob3Igc3Rkb3V0KS4gVGhlIGVuZHBvaW50XG4gKiBpcyBnYXRlZCBzZXJ2ZXItc2lkZSAqIOKAoiBTeXN0ZW0gYWRtaW5zIChhZG1pbi9vd25lciBpbiB0aGUgYHN5c3RlbWAgb3JnKSBtYXkgZXhwb3J0IGFueSBvcmcuXG4gKiDigKIgT3JnIGFkbWlucyAvIG93bmVycyBtYXkgZXhwb3J0IE9OTFkgdGhlaXIgb3duIG9yZy5cbiAqIOKAoiBFdmVyeXRoaW5nIGVsc2UgZ2V0cyA0MDMuXG4gKlxuICogVGhlIENMSSBpdHNlbGYgZG9lcyBubyByb2xlIGNoZWNraW5nICB0aGUgY2FsbGVyJ3MgUExBVEZPUk1fVE9LRU4gZHJpdmVzXG4gKiB3aGF0IHRoZSBzZXJ2ZXIgYWNjZXB0cy4gUnVuIGBwaXBlbGluZS1tYW5hZ2VyIHN0YXR1c2AgZmlyc3QgdG8gY29uZmlybVxuICogdGhlIHRva2VuJ3Mgcm9sZSArIG9yZy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgYmFzaFxuICogIyBTeXNhZG1pbjogYW55IG9yZ1xuICogcGlwZWxpbmUtbWFuYWdlciBvcmcgZXhwb3J0IC0taWQgb3JnLWFjbWUgLS1vdXRwdXQgYWNtZS5qc29uXG4gKlxuICogIyBPcmcgYWRtaW46IG93biBvcmcgb25seSAoc2VydmVyIHJlamVjdHMgb3RoZXIgaWRzIHdpdGggNDAzKVxuICogcGlwZWxpbmUtbWFuYWdlciBvcmcgZXhwb3J0IC0taWQgb3JnLWFjbWUgLS1vdXRwdXQgYWNtZS5qc29uXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9yZ0V4cG9ydChwcm9ncmFtOiBDb21tYW5kKTogdm9pZCB7XG4gIHdpdGhTc2xPcHRpb25zKHByb2dyYW1cbiAgICAuY29tbWFuZCgnZXhwb3J0JylcbiAgICAuZGVzY3JpcHRpb24oJ0V4cG9ydCBhbiBvcmdhbml6YXRpb25cXCdzIGRhdGEgYXMgSlNPTiAoR0RQUiBwb3J0YWJpbGl0eSwgKS4nKVxuICAgIC5yZXF1aXJlZE9wdGlvbignLWksIC0taWQgPGlkPicsICdPcmdhbml6YXRpb24gSUQgdG8gZXhwb3J0JylcbiAgICAub3B0aW9uKCctbywgLS1vdXRwdXQgPGZpbGU+JywgJ091dHB1dCBmaWxlIHBhdGggKGRlZmF1bHQ6IG9yZy08aWQ+LWV4cG9ydC5qc29uIGluIENXRCknKSlcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignT3JnIEV4cG9ydCcpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBwcmludFNzbFdhcm5pbmcob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICAgIGNvbnN0IG9yZ0lkID0gdmFsaWRhdGVFbnRpdHlJZChvcHRpb25zLmlkLCAnT3JnYW5pemF0aW9uJyk7XG4gICAgICAgIGNvbnN0IG91dHB1dFBhdGggPSBvcHRpb25zLm91dHB1dFxuICAgICAgICAgID8gcGF0aC5yZXNvbHZlKG9wdGlvbnMub3V0cHV0KVxuICAgICAgICAgIDogcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGBvcmctJHtvcmdJZH0tZXhwb3J0Lmpzb25gKTtcblxuICAgICAgICBwcmludEluZm8oJ1JlcXVlc3QgcGFyYW1ldGVycycsIHtcbiAgICAgICAgICBvcmdJZCxcbiAgICAgICAgICBvdXRwdXQ6IG91dHB1dFBhdGgsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnQob3B0aW9ucyk7XG5cbiAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICBwcmludFNlY3Rpb24oJ0ZldGNoaW5nIEV4cG9ydCcpO1xuXG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIC8vIFRoZSBlbmRwb2ludCBzdHJlYW1zIGEgbGFyZ2UgSlNPTiBhdHRhY2htZW50IGZvciBvcmdzIHdpdGggbG9uZ1xuICAgICAgICAvLyBoaXN0b3JpZXMuIFRoZSBBcGlDbGllbnQgcmV0dXJucyB0aGUgcGFyc2VkIGJvZHkgZGlyZWN0bHksIHdoaWNoXG4gICAgICAgIC8vIGZvciBgYXBwbGljYXRpb24vanNvbmAgaXMgYSBKUyBvYmplY3Qgd2UgcmUtc2VyaWFsaXplIHRvIGRpc2suXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmdldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oIGAke2NsaWVudC5nZXRDb25maWcoKS5hcGkuYmFzZVVybH0vYXBpL29yZ2FuaXphdGlvbi8ke2VuY29kZVVSSUNvbXBvbmVudChvcmdJZCl9L2V4cG9ydGAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcblxuICAgICAgICBpZiAoIXJlc3BvbnNlIHx8IHR5cGVvZiByZXNwb25zZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBwcmludEVycm9yKCdFbXB0eSAvIHVucGFyc2VhYmxlIGV4cG9ydCBwYXlsb2FkJyk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBvcnQgcmV0dXJuZWQgbm8gZGF0YSBmb3Igb3JnICR7b3JnSWR9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZS1zZXJpYWxpemUgc28gd2Uga2VlcCB0aGUgc2FtZSBwcmV0dHktcHJpbnRlZCBzaGFwZSB0aGUgc2VydmVyXG4gICAgICAgIC8vIHByb2R1Y2VkICgyLXNwYWNlIGluZGVudCBtYXRjaGVzIHRoZSBwbGF0Zm9ybSdzIGhhbmRsZXIpIGFuZCBzb1xuICAgICAgICAvLyB3ZSBkb24ndCBsb3NlIERhdGUgcHJlY2lzaW9uIG9uIGEgcm91bmQtdHJpcCB0aHJvdWdoIEpTT04ucGFyc2UuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEdVQVJEOiB0aGlzIHdyaXRlcyB0aGUgcmF3IHNlcnZlciBwYXlsb2FkIHN0cmFpZ2h0IHRvIGRpc2suIFRoZSBleHBvcnRcbiAgICAgICAgLy8gcGF5bG9hZCBtdXN0IE5FVkVSIGNvbnRhaW4gYW4gQVdTIGFjY291bnQgaWQg4oCUIG9yZ0lkIGlzIHRoZSBtYXJrZXRwbGFjZVxuICAgICAgICAvLyBjdXN0b21lcklkZW50aWZpZXIsIG5ldmVyIGFuIEFXUyBhY2NvdW50IGlkLiBJdCBpcyBhY2NvdW50LWlkLWZyZWUgdG9kYXk7XG4gICAgICAgIC8vIGlmIGEgZnV0dXJlIHNlcnZlciBjaGFuZ2UgZXZlciBhZGRzIG9uZSwgaXQgbXVzdCBiZSBzdHJpcHBlZC9yZWRhY3RlZFxuICAgICAgICAvLyBoZXJlIEJFRk9SRSB0aGlzIHdyaXRlLCBub3QgcGVyc2lzdGVkIHRocm91Z2ggdGhlIENMSS5cbiAgICAgICAgY29uc3QganNvbiA9IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLCBudWxsLCAyKTtcbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhvdXRwdXRQYXRoLCBqc29uLCAndXRmOCcpO1xuXG4gICAgICAgIGNvbnN0IHNpemVLYiA9IChqc29uLmxlbmd0aCAvIDEwMjQpLnRvRml4ZWQoMSk7XG4gICAgICAgIGNvbnN0IHBvc3RncmVzVGFibGVzID0gcmVzcG9uc2UucG9zdGdyZXMgJiYgdHlwZW9mIHJlc3BvbnNlLnBvc3RncmVzID09PSAnb2JqZWN0J1xuICAgICAgICAgID8gT2JqZWN0LmtleXMocmVzcG9uc2UucG9zdGdyZXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmxlbmd0aFxuICAgICAgICAgIDogMDtcblxuICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgIHByaW50U2VjdGlvbignRXhwb3J0IFNhdmVkJyk7XG4gICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICdPcmcgSUQnOiBncmVlbihib2xkKG9yZ0lkKSksXG4gICAgICAgICAgJ091dHB1dCc6IG91dHB1dFBhdGgsXG4gICAgICAgICAgJ1NpemUnOiBgJHtzaXplS2J9IEtCYCxcbiAgICAgICAgICAnUG9zdGdyZXMgdGFibGVzJzogU3RyaW5nKHBvc3RncmVzVGFibGVzKSxcbiAgICAgICAgICAnRXhwb3J0ZWQgYXQnOiB0eXBlb2YgcmVzcG9uc2UuZXhwb3J0ZWRBdCA9PT0gJ3N0cmluZycgPyByZXNwb25zZS5leHBvcnRlZEF0OiAnKG5vdCBzZXQpJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcHJpbnRFeGVjdXRpb25TdW1tYXJ5KGV4ZWN1dGlvbklkLCBkdXJhdGlvbik7XG4gICAgICAgIHByaW50U3VjY2VzcygnT3JnYW5pemF0aW9uIGV4cG9ydCBjb21wbGV0ZScsIHsgcGF0aDogb3V0cHV0UGF0aCB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHsgY29tbWFuZDogJ29yZy1leHBvcnQnLCBleGVjdXRpb25JZCwgb3JnSWQ6IG9wdGlvbnMuaWQgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG59XG4iXX0=