@peterhauge/apiops-cli 0.1.3-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +135 -0
  3. package/dist/cli/extract-command.d.ts +12 -0
  4. package/dist/cli/extract-command.d.ts.map +1 -0
  5. package/dist/cli/extract-command.js +157 -0
  6. package/dist/cli/extract-command.js.map +1 -0
  7. package/dist/cli/index.d.ts +7 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +74 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/init-command.d.ts +11 -0
  12. package/dist/cli/init-command.d.ts.map +1 -0
  13. package/dist/cli/init-command.js +87 -0
  14. package/dist/cli/init-command.js.map +1 -0
  15. package/dist/cli/publish-command.d.ts +12 -0
  16. package/dist/cli/publish-command.d.ts.map +1 -0
  17. package/dist/cli/publish-command.js +159 -0
  18. package/dist/cli/publish-command.js.map +1 -0
  19. package/dist/clients/apim-client.d.ts +110 -0
  20. package/dist/clients/apim-client.d.ts.map +1 -0
  21. package/dist/clients/apim-client.js +586 -0
  22. package/dist/clients/apim-client.js.map +1 -0
  23. package/dist/clients/artifact-store.d.ts +23 -0
  24. package/dist/clients/artifact-store.d.ts.map +1 -0
  25. package/dist/clients/artifact-store.js +188 -0
  26. package/dist/clients/artifact-store.js.map +1 -0
  27. package/dist/clients/iapim-client.d.ts +52 -0
  28. package/dist/clients/iapim-client.d.ts.map +1 -0
  29. package/dist/clients/iapim-client.js +6 -0
  30. package/dist/clients/iapim-client.js.map +1 -0
  31. package/dist/clients/iartifact-store.d.ts +50 -0
  32. package/dist/clients/iartifact-store.d.ts.map +1 -0
  33. package/dist/clients/iartifact-store.js +6 -0
  34. package/dist/clients/iartifact-store.js.map +1 -0
  35. package/dist/lib/auto-generated.d.ts +27 -0
  36. package/dist/lib/auto-generated.d.ts.map +1 -0
  37. package/dist/lib/auto-generated.js +34 -0
  38. package/dist/lib/auto-generated.js.map +1 -0
  39. package/dist/lib/cloud-config.d.ts +29 -0
  40. package/dist/lib/cloud-config.d.ts.map +1 -0
  41. package/dist/lib/cloud-config.js +60 -0
  42. package/dist/lib/cloud-config.js.map +1 -0
  43. package/dist/lib/config-loader.d.ts +21 -0
  44. package/dist/lib/config-loader.d.ts.map +1 -0
  45. package/dist/lib/config-loader.js +131 -0
  46. package/dist/lib/config-loader.js.map +1 -0
  47. package/dist/lib/dependency-graph.d.ts +43 -0
  48. package/dist/lib/dependency-graph.d.ts.map +1 -0
  49. package/dist/lib/dependency-graph.js +163 -0
  50. package/dist/lib/dependency-graph.js.map +1 -0
  51. package/dist/lib/exit-codes.d.ts +27 -0
  52. package/dist/lib/exit-codes.d.ts.map +1 -0
  53. package/dist/lib/exit-codes.js +33 -0
  54. package/dist/lib/exit-codes.js.map +1 -0
  55. package/dist/lib/logger.d.ts +39 -0
  56. package/dist/lib/logger.d.ts.map +1 -0
  57. package/dist/lib/logger.js +128 -0
  58. package/dist/lib/logger.js.map +1 -0
  59. package/dist/lib/parallel-runner.d.ts +38 -0
  60. package/dist/lib/parallel-runner.d.ts.map +1 -0
  61. package/dist/lib/parallel-runner.js +70 -0
  62. package/dist/lib/parallel-runner.js.map +1 -0
  63. package/dist/lib/resource-path.d.ts +205 -0
  64. package/dist/lib/resource-path.d.ts.map +1 -0
  65. package/dist/lib/resource-path.js +401 -0
  66. package/dist/lib/resource-path.js.map +1 -0
  67. package/dist/lib/resource-uri.d.ts +40 -0
  68. package/dist/lib/resource-uri.d.ts.map +1 -0
  69. package/dist/lib/resource-uri.js +86 -0
  70. package/dist/lib/resource-uri.js.map +1 -0
  71. package/dist/lib/user-agent.d.ts +2 -0
  72. package/dist/lib/user-agent.d.ts.map +1 -0
  73. package/dist/lib/user-agent.js +5 -0
  74. package/dist/lib/user-agent.js.map +1 -0
  75. package/dist/models/config.d.ts +83 -0
  76. package/dist/models/config.d.ts.map +1 -0
  77. package/dist/models/config.js +6 -0
  78. package/dist/models/config.js.map +1 -0
  79. package/dist/models/resource-types.d.ts +66 -0
  80. package/dist/models/resource-types.d.ts.map +1 -0
  81. package/dist/models/resource-types.js +243 -0
  82. package/dist/models/resource-types.js.map +1 -0
  83. package/dist/models/types.d.ts +47 -0
  84. package/dist/models/types.d.ts.map +1 -0
  85. package/dist/models/types.js +6 -0
  86. package/dist/models/types.js.map +1 -0
  87. package/dist/services/api-extractor.d.ts +36 -0
  88. package/dist/services/api-extractor.d.ts.map +1 -0
  89. package/dist/services/api-extractor.js +319 -0
  90. package/dist/services/api-extractor.js.map +1 -0
  91. package/dist/services/api-publisher.d.ts +18 -0
  92. package/dist/services/api-publisher.d.ts.map +1 -0
  93. package/dist/services/api-publisher.js +290 -0
  94. package/dist/services/api-publisher.js.map +1 -0
  95. package/dist/services/delete-unmatched-service.d.ts +17 -0
  96. package/dist/services/delete-unmatched-service.d.ts.map +1 -0
  97. package/dist/services/delete-unmatched-service.js +143 -0
  98. package/dist/services/delete-unmatched-service.js.map +1 -0
  99. package/dist/services/dry-run-reporter.d.ts +30 -0
  100. package/dist/services/dry-run-reporter.d.ts.map +1 -0
  101. package/dist/services/dry-run-reporter.js +111 -0
  102. package/dist/services/dry-run-reporter.js.map +1 -0
  103. package/dist/services/extract-service.d.ts +47 -0
  104. package/dist/services/extract-service.d.ts.map +1 -0
  105. package/dist/services/extract-service.js +374 -0
  106. package/dist/services/extract-service.js.map +1 -0
  107. package/dist/services/filter-service.d.ts +29 -0
  108. package/dist/services/filter-service.d.ts.map +1 -0
  109. package/dist/services/filter-service.js +143 -0
  110. package/dist/services/filter-service.js.map +1 -0
  111. package/dist/services/git-diff-service.d.ts +23 -0
  112. package/dist/services/git-diff-service.d.ts.map +1 -0
  113. package/dist/services/git-diff-service.js +135 -0
  114. package/dist/services/git-diff-service.js.map +1 -0
  115. package/dist/services/identity-guide-service.d.ts +11 -0
  116. package/dist/services/identity-guide-service.d.ts.map +1 -0
  117. package/dist/services/identity-guide-service.js +227 -0
  118. package/dist/services/identity-guide-service.js.map +1 -0
  119. package/dist/services/init-service.d.ts +16 -0
  120. package/dist/services/init-service.d.ts.map +1 -0
  121. package/dist/services/init-service.js +304 -0
  122. package/dist/services/init-service.js.map +1 -0
  123. package/dist/services/keyvault-checker.d.ts +58 -0
  124. package/dist/services/keyvault-checker.d.ts.map +1 -0
  125. package/dist/services/keyvault-checker.js +390 -0
  126. package/dist/services/keyvault-checker.js.map +1 -0
  127. package/dist/services/override-merger.d.ts +20 -0
  128. package/dist/services/override-merger.d.ts.map +1 -0
  129. package/dist/services/override-merger.js +102 -0
  130. package/dist/services/override-merger.js.map +1 -0
  131. package/dist/services/product-extractor.d.ts +26 -0
  132. package/dist/services/product-extractor.d.ts.map +1 -0
  133. package/dist/services/product-extractor.js +141 -0
  134. package/dist/services/product-extractor.js.map +1 -0
  135. package/dist/services/product-publisher.d.ts +15 -0
  136. package/dist/services/product-publisher.d.ts.map +1 -0
  137. package/dist/services/product-publisher.js +113 -0
  138. package/dist/services/product-publisher.js.map +1 -0
  139. package/dist/services/prompt-service.d.ts +13 -0
  140. package/dist/services/prompt-service.d.ts.map +1 -0
  141. package/dist/services/prompt-service.js +69 -0
  142. package/dist/services/prompt-service.js.map +1 -0
  143. package/dist/services/publish-service.d.ts +31 -0
  144. package/dist/services/publish-service.d.ts.map +1 -0
  145. package/dist/services/publish-service.js +445 -0
  146. package/dist/services/publish-service.js.map +1 -0
  147. package/dist/services/resource-extractor.d.ts +52 -0
  148. package/dist/services/resource-extractor.d.ts.map +1 -0
  149. package/dist/services/resource-extractor.js +168 -0
  150. package/dist/services/resource-extractor.js.map +1 -0
  151. package/dist/services/resource-publisher.d.ts +23 -0
  152. package/dist/services/resource-publisher.d.ts.map +1 -0
  153. package/dist/services/resource-publisher.js +349 -0
  154. package/dist/services/resource-publisher.js.map +1 -0
  155. package/dist/services/secret-redactor.d.ts +20 -0
  156. package/dist/services/secret-redactor.d.ts.map +1 -0
  157. package/dist/services/secret-redactor.js +45 -0
  158. package/dist/services/secret-redactor.js.map +1 -0
  159. package/dist/services/transitive-resolver.d.ts +45 -0
  160. package/dist/services/transitive-resolver.d.ts.map +1 -0
  161. package/dist/services/transitive-resolver.js +177 -0
  162. package/dist/services/transitive-resolver.js.map +1 -0
  163. package/dist/services/workspace-extractor.d.ts +34 -0
  164. package/dist/services/workspace-extractor.d.ts.map +1 -0
  165. package/dist/services/workspace-extractor.js +120 -0
  166. package/dist/services/workspace-extractor.js.map +1 -0
  167. package/dist/templates/azure-devops/extract-pipeline.d.ts +9 -0
  168. package/dist/templates/azure-devops/extract-pipeline.d.ts.map +1 -0
  169. package/dist/templates/azure-devops/extract-pipeline.js +95 -0
  170. package/dist/templates/azure-devops/extract-pipeline.js.map +1 -0
  171. package/dist/templates/azure-devops/publish-pipeline.d.ts +10 -0
  172. package/dist/templates/azure-devops/publish-pipeline.d.ts.map +1 -0
  173. package/dist/templates/azure-devops/publish-pipeline.js +100 -0
  174. package/dist/templates/azure-devops/publish-pipeline.js.map +1 -0
  175. package/dist/templates/configs/filter-config.d.ts +6 -0
  176. package/dist/templates/configs/filter-config.d.ts.map +1 -0
  177. package/dist/templates/configs/filter-config.js +51 -0
  178. package/dist/templates/configs/filter-config.js.map +1 -0
  179. package/dist/templates/configs/override-config.d.ts +6 -0
  180. package/dist/templates/configs/override-config.d.ts.map +1 -0
  181. package/dist/templates/configs/override-config.js +45 -0
  182. package/dist/templates/configs/override-config.js.map +1 -0
  183. package/dist/templates/configs/package-json.d.ts +10 -0
  184. package/dist/templates/configs/package-json.d.ts.map +1 -0
  185. package/dist/templates/configs/package-json.js +19 -0
  186. package/dist/templates/configs/package-json.js.map +1 -0
  187. package/dist/templates/copilot/identity-setup-prompt.d.ts +13 -0
  188. package/dist/templates/copilot/identity-setup-prompt.d.ts.map +1 -0
  189. package/dist/templates/copilot/identity-setup-prompt.js +279 -0
  190. package/dist/templates/copilot/identity-setup-prompt.js.map +1 -0
  191. package/dist/templates/github-actions/extract-workflow.d.ts +9 -0
  192. package/dist/templates/github-actions/extract-workflow.d.ts.map +1 -0
  193. package/dist/templates/github-actions/extract-workflow.js +126 -0
  194. package/dist/templates/github-actions/extract-workflow.js.map +1 -0
  195. package/dist/templates/github-actions/publish-workflow.d.ts +10 -0
  196. package/dist/templates/github-actions/publish-workflow.d.ts.map +1 -0
  197. package/dist/templates/github-actions/publish-workflow.js +105 -0
  198. package/dist/templates/github-actions/publish-workflow.js.map +1 -0
  199. package/package.json +65 -0
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Microsoft Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # apiops
2
+
3
+ `apiops` is a CLI tool for Azure API Management (APIM) configuration-as-code. Extract your APIM service configuration to local artifact files, publish those artifacts back to Azure, and scaffold CI/CD pipelines — all from the command line.
4
+
5
+ | | |
6
+ |---|---|
7
+ | **Source code** | [github.com/Azure/apiops-cli](https://github.com/Azure/apiops-cli) |
8
+ | **Issues** | [GitHub Issues](https://github.com/Azure/apiops-cli/issues) |
9
+
10
+ ## Getting started
11
+
12
+ **Prerequisites:** An Azure subscription with an existing APIM resource, and Node.js ≥ 22.
13
+
14
+ ```bash
15
+ npm install -g @peterhauge/apiops-cli
16
+ ```
17
+
18
+ ## Authentication
19
+
20
+ `apiops` uses [`@azure/identity`](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity) `DefaultAzureCredential` for authentication:
21
+
22
+ - To use environment variables, set the following variables: `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, and `AZURE_SUBSCRIPTION_ID`
23
+ - To specify authentication in command, use the following flags: `--client-id`, `--client-secret`, `--tenant-id`, and `--subscription-id`
24
+ - **CI/CD:** A service principal with the **API Management Service Contributor** role is recommended.
25
+ - **Azure-hosted environments:** Managed Identity and Workload Identity are also supported.
26
+
27
+ ## Commands
28
+
29
+ ### `apiops extract`
30
+
31
+ Extract APIM service configuration to local artifact files.
32
+
33
+ | Flag | Default | Description |
34
+ |------|---------|-------------|
35
+ | `--resource-group <rg>` | *(required)* | Azure resource group |
36
+ | `--service-name <name>` | *(required)* | APIM service name |
37
+ | `--output <dir>` | `./apim-artifacts` | Output directory |
38
+ | `--filter <path>` | | Extract only matching resources |
39
+ | `--no-transitive` | | Skip transitive dependencies |
40
+ | `--spec-format <format>` | | Override API spec format |
41
+
42
+ ```bash
43
+ apiops extract --help
44
+
45
+ # Basic extraction to the default output directory
46
+ apiops extract \
47
+ --resource-group <rg> \
48
+ --service-name <name> \
49
+ --output ./apim-artifacts
50
+
51
+ # Extract a filtered subset of resources and override the API spec format
52
+ apiops extract \
53
+ --resource-group <rg> \
54
+ --service-name <name> \
55
+ --filter ./filter.yaml \
56
+ --spec-format openapi-v3-yaml
57
+
58
+ # Authenticate explicitly with a service principal
59
+ apiops extract \
60
+ --resource-group <rg> \
61
+ --service-name <name> \
62
+ --client-id $AZURE_CLIENT_ID \
63
+ --client-secret $AZURE_CLIENT_SECRET \
64
+ --tenant-id $AZURE_TENANT_ID \
65
+ --subscription-id $AZURE_SUBSCRIPTION_ID
66
+ ```
67
+
68
+ ### `apiops publish`
69
+
70
+ Publish local artifact files to an Azure APIM service.
71
+
72
+ | Flag | Default | Description |
73
+ |------|---------|-------------|
74
+ | `--resource-group <rg>` | *(required)* | Azure resource group |
75
+ | `--service-name <name>` | *(required)* | APIM service name |
76
+ | `--source <dir>` | `./apim-artifacts` | Source artifacts directory |
77
+ | `--overrides <path>` | | Path to overrides file |
78
+ | `--dry-run` | | Preview changes without applying |
79
+ | `--delete-unmatched` | | Delete resources not in artifacts |
80
+
81
+ ```bash
82
+ apiops publish --help
83
+
84
+ # Preview changes without applying them
85
+ apiops publish \
86
+ --resource-group <rg> \
87
+ --service-name <name> \
88
+ --dry-run
89
+
90
+ # Publish and remove resources not present in the local artifacts
91
+ apiops publish \
92
+ --resource-group <rg> \
93
+ --service-name <name> \
94
+ --delete-unmatched
95
+ ```
96
+
97
+ ### `apiops init`
98
+
99
+ Scaffold a new APIM artifacts repository with CI/CD pipelines.
100
+
101
+ | Flag | Description |
102
+ |------|-------------|
103
+ | `--cli-package <path>` | Path to a local `.tgz` tarball |
104
+ | `--ci <platform>` | `github-actions` or `azure-devops` |
105
+ | `--environments <list>` | Comma-separated environments (e.g. `dev,prod`) |
106
+ | `--non-interactive` | Skip all prompts |
107
+ | `--force` | Overwrite existing files |
108
+
109
+ ```bash
110
+ apiops init --help
111
+
112
+ apiops init \
113
+ --ci github-actions \
114
+ --environments dev,prod
115
+ ```
116
+
117
+ ## Global options
118
+
119
+ | Option | Default | Description |
120
+ |--------|---------|-------------|
121
+ | `--subscription-id <id>` | `AZURE_SUBSCRIPTION_ID` env var | Azure subscription ID |
122
+ | `--cloud <name>` | `public` | `public`, `china`, `usgov`, `germany` |
123
+ | `--log-level <level>` | `info` | `debug`, `info`, `warn`, `error` |
124
+ | `--format <type>` | `text` | `text` or `json` |
125
+ | `--client-id <id>` | `AZURE_CLIENT_ID` env var | Service principal client ID |
126
+ | `--client-secret <secret>` | `AZURE_CLIENT_SECRET` env var | Service principal secret |
127
+ | `--tenant-id <id>` | `AZURE_TENANT_ID` env var | Azure AD tenant ID |
128
+
129
+ ## Contributing
130
+
131
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to build, test, debug, and submit changes.
132
+
133
+ ## License
134
+
135
+ [MIT](./LICENSE)
@@ -0,0 +1,12 @@
1
+ /**
2
+ * T028 & T029: Extract command CLI registration
3
+ * Commander subcommand with --resource-group, --service-name, --output,
4
+ * --filter, --no-transitive, --spec-format flags.
5
+ * Includes --format json: machine-readable JSON output mode.
6
+ */
7
+ import { Command } from 'commander';
8
+ /**
9
+ * Create and return the extract command for Commander.
10
+ */
11
+ export declare function createExtractCommand(): Command;
12
+ //# sourceMappingURL=extract-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-command.d.ts","sourceRoot":"","sources":["../../src/cli/extract-command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAsB9C"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * T028 & T029: Extract command CLI registration
3
+ * Commander subcommand with --resource-group, --service-name, --output,
4
+ * --filter, --no-transitive, --spec-format flags.
5
+ * Includes --format json: machine-readable JSON output mode.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { runExtraction } from '../services/extract-service.js';
9
+ import { loadFilterConfig } from '../lib/config-loader.js';
10
+ import { logger, parseLogLevel } from '../lib/logger.js';
11
+ import { ApimClient } from '../clients/apim-client.js';
12
+ import { ArtifactStore } from '../clients/artifact-store.js';
13
+ import { getCloudConfig, buildArmBaseUrl } from '../lib/cloud-config.js';
14
+ /**
15
+ * Create and return the extract command for Commander.
16
+ */
17
+ export function createExtractCommand() {
18
+ const extract = new Command('extract')
19
+ .description('Extract APIM configuration to local artifact files')
20
+ .requiredOption('--resource-group <rg>', 'Azure resource group name')
21
+ .requiredOption('--service-name <name>', 'APIM service instance name')
22
+ .option('--output <dir>', 'Output directory path', './apim-artifacts')
23
+ .option('--filter <path>', 'Filter configuration YAML file')
24
+ .option('--no-transitive', 'Disable transitive dependency inclusion')
25
+ .option('--spec-format <format>', 'API specification format (openapi-v2-json, openapi-v3-json, openapi-v3-yaml)')
26
+ .action(async (options, command) => {
27
+ const globalOpts = command.optsWithGlobals();
28
+ await executeExtract(options, globalOpts);
29
+ });
30
+ return extract;
31
+ }
32
+ /**
33
+ * Execute the extract command.
34
+ */
35
+ async function executeExtract(options, globalOpts) {
36
+ const subscriptionId = globalOpts.subscriptionId ?? process.env.AZURE_SUBSCRIPTION_ID;
37
+ if (!subscriptionId) {
38
+ logger.error('Subscription ID required: use --subscription-id or set AZURE_SUBSCRIPTION_ID');
39
+ process.exit(2);
40
+ }
41
+ // Build service context
42
+ const apiVersion = globalOpts.apiVersion ?? process.env.AZURE_API_VERSION ?? '2024-05-01';
43
+ const cloudName = globalOpts.cloud ?? 'public';
44
+ const cloudConfig = getCloudConfig(cloudName);
45
+ const baseUrl = buildArmBaseUrl(cloudName, subscriptionId, options.resourceGroup, options.serviceName);
46
+ const context = {
47
+ subscriptionId,
48
+ resourceGroup: options.resourceGroup,
49
+ serviceName: options.serviceName,
50
+ apiVersion,
51
+ baseUrl,
52
+ };
53
+ // Load filter config if specified
54
+ let filterConfig;
55
+ if (options.filter) {
56
+ filterConfig = await loadFilterConfig(options.filter);
57
+ if (!filterConfig) {
58
+ logger.error(`Filter file not found: ${options.filter}`);
59
+ process.exit(2);
60
+ }
61
+ }
62
+ // Build extract config
63
+ const extractConfig = {
64
+ service: context,
65
+ outputDir: options.output,
66
+ filter: filterConfig,
67
+ includeTransitive: options.transitive,
68
+ specFormat: options.specFormat,
69
+ logLevel: parseLogLevel(globalOpts.logLevel ?? 'info'),
70
+ };
71
+ // Create client and store
72
+ const client = new ApimClient(cloudConfig.authScope);
73
+ const store = new ArtifactStore();
74
+ // Run extraction
75
+ const result = await runExtraction(client, store, extractConfig);
76
+ // Output results
77
+ if (globalOpts.format === 'json') {
78
+ outputJson(result);
79
+ }
80
+ else {
81
+ outputText(result);
82
+ }
83
+ process.exit(result.exitCode);
84
+ }
85
+ /**
86
+ * T029: JSON output mode for extract.
87
+ * Machine-readable JSON to stdout with resource counts and file paths.
88
+ */
89
+ function outputJson(result) {
90
+ const output = {
91
+ status: result.exitCode === 0 ? 'success' : result.exitCode === 1 ? 'partial' : 'error',
92
+ exitCode: result.exitCode,
93
+ summary: {
94
+ totalExtracted: result.totalExtracted,
95
+ totalErrors: result.totalErrors,
96
+ typeBreakdown: result.typeResults.map((tr) => ({
97
+ type: tr.type,
98
+ extracted: tr.extracted.filter((r) => r.status === 'success').length,
99
+ errors: tr.errorCount,
100
+ })),
101
+ },
102
+ resources: result.extractedDescriptors.map((d) => ({
103
+ type: d.type,
104
+ nameParts: d.nameParts,
105
+ workspace: d.workspace,
106
+ })),
107
+ apis: result.apiResults.map((ar) => ({
108
+ name: ar.apiName,
109
+ revisions: ar.revisions.filter((r) => r.status === 'success').length,
110
+ specification: ar.specification,
111
+ operations: ar.operations.filter((r) => r.status === 'success').length,
112
+ tags: ar.tags.filter((r) => r.status === 'success').length,
113
+ })),
114
+ workspaces: result.workspaceResults.map((wr) => ({
115
+ name: wr.workspaceName,
116
+ resources: wr.resourceCount,
117
+ errors: wr.errorCount,
118
+ })),
119
+ };
120
+ // JSON output goes to stdout (not stderr)
121
+ process.stdout.write(JSON.stringify(output, null, 2) + '\n');
122
+ }
123
+ /**
124
+ * Text output mode (default) — per-resource status lines.
125
+ */
126
+ function outputText(result) {
127
+ // Per-type summary
128
+ for (const tr of result.typeResults) {
129
+ const successCount = tr.extracted.filter((r) => r.status === 'success').length;
130
+ if (successCount > 0) {
131
+ process.stdout.write(`Extracted ${successCount} ${tr.type}(s)\n`);
132
+ }
133
+ if (tr.errorCount > 0) {
134
+ process.stdout.write(`Failed ${tr.errorCount} ${tr.type}(s)\n`);
135
+ }
136
+ }
137
+ // API details
138
+ for (const ar of result.apiResults) {
139
+ const details = [];
140
+ if (ar.specification)
141
+ details.push('spec');
142
+ if (ar.operations.length > 0)
143
+ details.push(`${ar.operations.length} ops`);
144
+ if (ar.revisions.length > 0)
145
+ details.push(`${ar.revisions.length} revisions`);
146
+ if (details.length > 0) {
147
+ process.stdout.write(` API "${ar.apiName}": ${details.join(', ')}\n`);
148
+ }
149
+ }
150
+ // Workspace details
151
+ for (const wr of result.workspaceResults) {
152
+ process.stdout.write(`Workspace "${wr.workspaceName}": ${wr.resourceCount} resources\n`);
153
+ }
154
+ // Summary
155
+ process.stdout.write(`\nTotal: ${result.totalExtracted} resources extracted, ${result.totalErrors} errors\n`);
156
+ }
157
+ //# sourceMappingURL=extract-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-command.js","sourceRoot":"","sources":["../../src/cli/extract-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * T019: Commander program entry point
4
+ * Sets up global options and subcommand registration pattern
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * T019: Commander program entry point
4
+ * Sets up global options and subcommand registration pattern
5
+ */
6
+ import { Command, Option } from 'commander';
7
+ import { logger, parseLogLevel } from '../lib/logger.js';
8
+ import { createExtractCommand } from './extract-command.js';
9
+ import { createPublishCommand } from './publish-command.js';
10
+ import { createInitCommand } from './init-command.js';
11
+ const program = new Command();
12
+ // Configure program metadata
13
+ program
14
+ .name('apiops')
15
+ .version('0.1.0')
16
+ .description('CLI tool for Azure API Management configuration-as-code');
17
+ // Show global options in subcommand help (e.g. apiops extract --help)
18
+ program.configureHelp({ showGlobalOptions: true });
19
+ // Global options inherited by all subcommands
20
+ program
21
+ .addOption(new Option('--log-level <level>', 'Log level: debug, info, warn, or error')
22
+ .choices(['debug', 'info', 'warn', 'error'])
23
+ .default('info'))
24
+ .option('--otel <path>', 'Path to OpenTelemetry config YAML')
25
+ .option('--format <type>', 'Output format: text or json', 'text')
26
+ .option('--subscription-id <id>', 'Azure subscription ID')
27
+ .option('--cloud <name>', 'Sovereign cloud: public, china, usgov, germany', 'public')
28
+ .option('--client-id <id>', 'Service principal client ID')
29
+ .option('--client-secret <secret>', 'Service principal client secret')
30
+ .option('--tenant-id <id>', 'Azure AD tenant ID');
31
+ // Configure logger and set auth environment variables before each command
32
+ program.hook('preAction', (thisCommand) => {
33
+ const opts = thisCommand.optsWithGlobals();
34
+ logger.configure({ level: parseLogLevel(opts.logLevel ?? 'info') });
35
+ // T040: Set DefaultAzureCredential env vars from explicit auth flags.
36
+ // This ensures the ServicePrincipal credential is tried first,
37
+ // avoiding interactive browser prompts in CI/CD pipelines.
38
+ if (opts.clientId) {
39
+ process.env.AZURE_CLIENT_ID = opts.clientId;
40
+ }
41
+ if (opts.clientSecret) {
42
+ process.env.AZURE_CLIENT_SECRET = opts.clientSecret;
43
+ }
44
+ if (opts.tenantId) {
45
+ process.env.AZURE_TENANT_ID = opts.tenantId;
46
+ }
47
+ });
48
+ // Subcommand registration section
49
+ program.addCommand(createExtractCommand());
50
+ program.addCommand(createPublishCommand());
51
+ program.addCommand(createInitCommand());
52
+ // Apply help configuration to all subcommands so global options are visible
53
+ program.commands.forEach((cmd) => cmd.configureHelp({ showGlobalOptions: true }));
54
+ // Handle unknown commands gracefully
55
+ program.on('command:*', (operands) => {
56
+ const unknownCommand = operands[0] ?? 'unknown';
57
+ logger.error(`Unknown command: ${unknownCommand}`);
58
+ logger.info('Run "apiops --help" to see available commands');
59
+ process.exit(1);
60
+ });
61
+ // Parse arguments and handle errors
62
+ try {
63
+ await program.parseAsync(process.argv);
64
+ }
65
+ catch (error) {
66
+ if (error instanceof Error) {
67
+ logger.error('Command failed:', error.message);
68
+ }
69
+ else {
70
+ logger.error('Command failed with unknown error');
71
+ }
72
+ process.exit(1);
73
+ }
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * T050: Register init command
3
+ * Commander subcommand with --ci, --non-interactive, --artifact-dir, --environments flags
4
+ * Wire to init-service
5
+ */
6
+ import { Command } from 'commander';
7
+ /**
8
+ * Create and return the init command for Commander
9
+ */
10
+ export declare function createInitCommand(): Command;
11
+ //# sourceMappingURL=init-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-command.d.ts","sourceRoot":"","sources":["../../src/cli/init-command.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAiF3C"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * T050: Register init command
3
+ * Commander subcommand with --ci, --non-interactive, --artifact-dir, --environments flags
4
+ * Wire to init-service
5
+ */
6
+ import { Command } from 'commander';
7
+ import { initService } from '../services/init-service.js';
8
+ import { logger } from '../lib/logger.js';
9
+ /**
10
+ * Create and return the init command for Commander
11
+ */
12
+ export function createInitCommand() {
13
+ const init = new Command('init')
14
+ .description('Initialize APIM repository with CI/CD pipelines and configuration templates')
15
+ .option('--ci <provider>', 'CI/CD provider: github-actions or azure-devops')
16
+ .option('--non-interactive', 'Skip interactive prompts (requires --ci)', false)
17
+ .option('--artifact-dir <dir>', 'Artifact directory path', './apim-artifacts')
18
+ .option('--environments <list>', 'Comma-separated environment names', 'dev,prod')
19
+ .requiredOption('--cli-package <path>', 'Path to apiops npm tarball (from npm pack)')
20
+ .option('--force', 'Overwrite existing files without prompting', false)
21
+ .action(async (options) => {
22
+ try {
23
+ // Use pretty log format for init (human-facing command)
24
+ logger.setFormat('pretty');
25
+ // Validate CI provider if specified
26
+ if (options.ci && options.ci !== 'github-actions' && options.ci !== 'azure-devops') {
27
+ logger.error('Invalid CI provider. Must be "github-actions" or "azure-devops"');
28
+ process.exit(1);
29
+ }
30
+ // Parse environments
31
+ const environments = options.environments
32
+ .split(',')
33
+ .map((env) => env.trim())
34
+ .filter((env) => env.length > 0);
35
+ if (environments.length === 0) {
36
+ logger.error('At least one environment must be specified');
37
+ process.exit(1);
38
+ }
39
+ // Build config
40
+ const config = {
41
+ ciProvider: options.ci,
42
+ nonInteractive: options.nonInteractive,
43
+ artifactDir: options.artifactDir,
44
+ environments,
45
+ outputDir: process.cwd(),
46
+ cliPackage: options.cliPackage,
47
+ force: options.force,
48
+ };
49
+ // Run init service
50
+ const generatedFiles = await initService.run(config);
51
+ // Output file listing
52
+ const allFiles = [
53
+ ...generatedFiles.pipelines,
54
+ ...generatedFiles.configs,
55
+ ];
56
+ logger.info(`\nGenerated ${allFiles.length} file(s):`);
57
+ allFiles.forEach((file) => logger.info(` - ${file.startsWith('./') ? file : './' + file}`));
58
+ logger.info(`\nCreated ${generatedFiles.directories.length} directory/directories:`);
59
+ generatedFiles.directories.forEach((dir) => logger.info(` - ${dir.startsWith('./') ? dir : './' + dir}`));
60
+ // Determine which CI provider was actually used by checking generated files
61
+ const isGitHub = allFiles.some((f) => f.includes('IDENTITY-SETUP-GITHUB.md'));
62
+ logger.info('\nNext steps:');
63
+ logger.info(' 1. Review and customize the generated configuration files');
64
+ logger.info(' 2. Commit the generated files to your repository');
65
+ logger.info(' 3. Set up CI/CD identity authentication:');
66
+ if (isGitHub) {
67
+ logger.info(' - Follow ./IDENTITY-SETUP-GITHUB.md for manual setup, OR');
68
+ logger.info(' - Open ./.github/prompts/apiops-setup-identity.prompt.md with GitHub Copilot for guided setup');
69
+ }
70
+ else {
71
+ logger.info(' - Follow ./IDENTITY-SETUP-AZDO.md for manual setup');
72
+ }
73
+ logger.info('');
74
+ }
75
+ catch (error) {
76
+ if (error instanceof Error) {
77
+ logger.error('Init failed:', error.message);
78
+ }
79
+ else {
80
+ logger.error('Init failed with unknown error');
81
+ }
82
+ process.exit(1);
83
+ }
84
+ });
85
+ return init;
86
+ }
87
+ //# sourceMappingURL=init-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-command.js","sourceRoot":"","sources":["../../src/cli/init-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * T037 & T038: Publish command CLI registration
3
+ * Commander subcommand with --resource-group, --service-name, --source,
4
+ * --overrides, --dry-run, --delete-unmatched flags.
5
+ * Includes --format json: machine-readable JSON output mode (T038).
6
+ */
7
+ import { Command } from 'commander';
8
+ /**
9
+ * Create and return the publish command for Commander.
10
+ */
11
+ export declare function createPublishCommand(): Command;
12
+ //# sourceMappingURL=publish-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-command.d.ts","sourceRoot":"","sources":["../../src/cli/publish-command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA0B9C"}