@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
@@ -0,0 +1,586 @@
1
+ /**
2
+ * T016: Azure REST HTTP client implementing IApimClient
3
+ * Uses @azure/identity DefaultAzureCredential for auth
4
+ * Handles pagination, retry, rate limiting, and long-running operations
5
+ */
6
+ import { DefaultAzureCredential } from '@azure/identity';
7
+ import { RESOURCE_TYPE_METADATA, ResourceType } from '../models/resource-types.js';
8
+ import { buildArmUri, buildResourceLabel } from '../lib/resource-uri.js';
9
+ import { deriveListPaths } from '../lib/resource-path.js';
10
+ import { logger } from '../lib/logger.js';
11
+ import { USER_AGENT } from '../lib/user-agent.js';
12
+ /**
13
+ * Structured HTTP error that carries the response status code.
14
+ * Allows callers to branch on status without parsing the message string.
15
+ */
16
+ export class HttpError extends Error {
17
+ status;
18
+ code;
19
+ constructor(status, message, code // APIM error code, e.g. "MethodNotAllowedInPricingTier"
20
+ ) {
21
+ super(message);
22
+ this.status = status;
23
+ this.code = code;
24
+ this.name = 'HttpError';
25
+ }
26
+ }
27
+ export class ApimClient {
28
+ credential;
29
+ authScope;
30
+ tokenCache = null;
31
+ tokenPromise = null;
32
+ static TOKEN_CACHE_BUFFER_MS = 5 * 60 * 1000; // 5 minutes
33
+ static MAX_RETRIES = 3;
34
+ static BASE_DELAY_MS = 1000;
35
+ static MAX_DELAY_MS = 30000;
36
+ static MAX_POLLING_ATTEMPTS = 30;
37
+ static POLL_INTERVAL_MS = 2000;
38
+ /** Stable ARM API version for Resource Group existence checks */
39
+ static RESOURCE_GROUP_API_VERSION = '2021-04-01';
40
+ /**
41
+ * @param authScope OAuth2 scope for ARM token requests.
42
+ * Defaults to the Azure public cloud scope.
43
+ */
44
+ constructor(authScope = 'https://management.azure.com/.default') {
45
+ this.credential = new DefaultAzureCredential();
46
+ this.authScope = authScope;
47
+ }
48
+ /**
49
+ * Get bearer token for Azure Management API.
50
+ * Uses a promise cache to prevent duplicate token requests under concurrency.
51
+ */
52
+ async getToken() {
53
+ if (this.tokenCache && this.tokenCache.expiresOn > Date.now() + ApimClient.TOKEN_CACHE_BUFFER_MS) {
54
+ return this.tokenCache.token;
55
+ }
56
+ if (!this.tokenPromise) {
57
+ this.tokenPromise = this.fetchToken().finally(() => {
58
+ this.tokenPromise = null;
59
+ });
60
+ }
61
+ return this.tokenPromise;
62
+ }
63
+ async fetchToken() {
64
+ const tokenResponse = await this.credential.getToken(this.authScope);
65
+ this.tokenCache = {
66
+ token: tokenResponse.token,
67
+ expiresOn: tokenResponse.expiresOnTimestamp,
68
+ };
69
+ return tokenResponse.token;
70
+ }
71
+ /**
72
+ * Execute HTTP request with retry logic and rate limiting.
73
+ * @param noRetryOn5xx - When true, 5xx responses are returned immediately
74
+ * without retrying (e.g. wiki endpoints that return 500 for missing wikis).
75
+ * @param skipAuth - When true, skip adding Authorization/Content-Type headers
76
+ * (e.g. blob SAS URLs that are self-authenticating).
77
+ * @param allowedNonOkStatuses - Status codes the caller will handle itself
78
+ * (response returned instead of throwing). 404 is always allowed for GETs.
79
+ */
80
+ async request(url, options = {}, noRetryOn5xx = false, skipAuth = false, allowedNonOkStatuses = []) {
81
+ const headers = new Headers(options.headers);
82
+ if (!skipAuth) {
83
+ const token = await this.getToken();
84
+ headers.set('Authorization', `Bearer ${token}`);
85
+ headers.set('Content-Type', 'application/json');
86
+ }
87
+ else {
88
+ headers.delete('Authorization');
89
+ headers.delete('Proxy-Authorization');
90
+ headers.delete('x-ms-authorization-auxiliary');
91
+ }
92
+ headers.set('User-Agent', USER_AGENT);
93
+ let attempt = 0;
94
+ // For SAS blob URLs the query string contains the sig token — strip it before logging.
95
+ const logUrl = skipAuth ? url.split('?')[0] : url;
96
+ while (attempt <= ApimClient.MAX_RETRIES) {
97
+ try {
98
+ logger.debug(`HTTP ${options.method ?? 'GET'} ${logUrl}`);
99
+ const response = await fetch(url, { ...options, headers });
100
+ // Handle rate limiting (429)
101
+ if (response.status === 429) {
102
+ const retryAfter = response.headers.get('Retry-After');
103
+ const delaySeconds = retryAfter ? parseInt(retryAfter, 10) : Math.pow(2, attempt);
104
+ logger.warn(`Rate limited (429), retrying after ${delaySeconds}s`);
105
+ await this.delay(delaySeconds * 1000);
106
+ attempt++;
107
+ continue;
108
+ }
109
+ // Handle transient errors (5xx)
110
+ if (response.status >= 500 && response.status < 600) {
111
+ if (noRetryOn5xx) {
112
+ // Caller has opted out of 5xx retries — return the raw response so
113
+ // getResource can treat it as "not found" (e.g. wiki endpoints that
114
+ // return 500 when the API/product has no wiki).
115
+ return response;
116
+ }
117
+ if (attempt < ApimClient.MAX_RETRIES) {
118
+ const delayMs = this.exponentialBackoffWithJitter(attempt);
119
+ logger.warn(`Server error ${response.status}, retrying after ${delayMs}ms`);
120
+ await this.delay(delayMs);
121
+ attempt++;
122
+ continue;
123
+ }
124
+ }
125
+ // Handle 404 gracefully for GET operations (default method is GET when unspecified)
126
+ if (response.status === 404 && (options.method === 'GET' || !options.method)) {
127
+ return response;
128
+ }
129
+ // Caller-opt-in: return specific non-OK statuses instead of throwing
130
+ // (e.g. 406 from GraphQL `graphql-link` export when the API has no
131
+ // downloadable SDL — a valid "no spec available" signal, not an error).
132
+ if (!response.ok && allowedNonOkStatuses.includes(response.status)) {
133
+ return response;
134
+ }
135
+ // Check for error responses
136
+ if (!response.ok) {
137
+ const errorText = await response.text();
138
+ let errorCode;
139
+ try {
140
+ const errorBody = JSON.parse(errorText);
141
+ if (typeof errorBody === 'object' && errorBody !== null &&
142
+ 'error' in errorBody &&
143
+ typeof errorBody['error'] === 'object' &&
144
+ errorBody['error'] !== null &&
145
+ 'code' in errorBody['error'] &&
146
+ typeof errorBody['error']['code'] === 'string') {
147
+ errorCode = errorBody['error']['code'];
148
+ }
149
+ }
150
+ catch {
151
+ // Response body is not JSON — no error code available
152
+ }
153
+ throw new HttpError(response.status, `HTTP ${response.status}: ${errorText}`, errorCode);
154
+ }
155
+ return response;
156
+ }
157
+ catch (error) {
158
+ // Do not retry client errors (4xx) — they are deterministic, not transient.
159
+ // 429 rate-limiting is already handled above and never reaches here.
160
+ if (error instanceof HttpError && error.status >= 400 && error.status < 500) {
161
+ throw error;
162
+ }
163
+ if (attempt >= ApimClient.MAX_RETRIES) {
164
+ throw error;
165
+ }
166
+ const delayMs = this.exponentialBackoffWithJitter(attempt);
167
+ logger.warn(`Request failed: ${error.message}, retrying after ${delayMs}ms`);
168
+ await this.delay(delayMs);
169
+ attempt++;
170
+ }
171
+ }
172
+ throw new Error('Max retries exceeded');
173
+ }
174
+ exponentialBackoffWithJitter(attempt) {
175
+ const exponentialDelay = Math.min(ApimClient.BASE_DELAY_MS * Math.pow(2, attempt), ApimClient.MAX_DELAY_MS);
176
+ const jitter = Math.random() * 0.3 * exponentialDelay;
177
+ return exponentialDelay + jitter;
178
+ }
179
+ delay(ms) {
180
+ return new Promise((resolve) => setTimeout(resolve, ms));
181
+ }
182
+ async *listResources(context, type, parent) {
183
+ // Build list URL based on resource type and parent
184
+ let url;
185
+ const meta = RESOURCE_TYPE_METADATA[type];
186
+ const { listPath, childListPath } = deriveListPaths(meta.armPathSuffix);
187
+ if (parent) {
188
+ // For child resources, use parent's ARM URI as base.
189
+ // buildArmUri already appends ?api-version=..., so strip the query string
190
+ // before appending the child path to avoid a malformed double-query URL.
191
+ if (!childListPath) {
192
+ throw new Error(`Resource type ${type} is a singleton — listResources() cannot be called on it with a parent`);
193
+ }
194
+ const parentUri = buildArmUri(context, parent);
195
+ const parentUriBase = parentUri.split('?')[0];
196
+ url = `${parentUriBase}${childListPath}?api-version=${context.apiVersion}`;
197
+ }
198
+ else {
199
+ // For top-level resources
200
+ if (!listPath) {
201
+ throw new Error(`Resource type ${type} is a singleton — listResources() cannot be called on it`);
202
+ }
203
+ url = `${context.baseUrl}${listPath}?api-version=${context.apiVersion}`;
204
+ }
205
+ // Handle pagination with nextLink
206
+ while (url) {
207
+ let response;
208
+ try {
209
+ response = await this.request(url);
210
+ }
211
+ catch (error) {
212
+ // HTTP 400 with MethodNotAllowedInPricingTier means the resource type is not
213
+ // supported by this APIM pricing tier. Skip it — do not treat as a failure.
214
+ if (error instanceof HttpError && error.code === 'MethodNotAllowedInPricingTier') {
215
+ logger.debug(`Skipping resource type ${type} — not available in this pricing tier.`);
216
+ return;
217
+ }
218
+ throw error;
219
+ }
220
+ // request() returns 404 GET responses directly (non-throwing).
221
+ // A 404 on a list endpoint means the resource collection does not exist
222
+ // for this service instance — treat as empty.
223
+ if (!response.ok) {
224
+ if (response.status === 404) {
225
+ logger.debug(`Resource type ${type} returned HTTP 404, resource collection not found — returning empty list`);
226
+ return;
227
+ }
228
+ throw new HttpError(response.status, `Request failed with HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}`);
229
+ }
230
+ const data = await response.json();
231
+ if (data.value && Array.isArray(data.value)) {
232
+ for (const item of data.value) {
233
+ yield item;
234
+ }
235
+ }
236
+ url = data.nextLink ?? '';
237
+ }
238
+ }
239
+ async getResource(context, descriptor) {
240
+ const url = buildArmUri(context, descriptor);
241
+ // Azure APIM returns HTTP 500 (not 404) when an API or product has no wiki.
242
+ // Suppress retries for wiki types so the extractor silently skips them.
243
+ const isWiki = descriptor.type === ResourceType.ApiWiki ||
244
+ descriptor.type === ResourceType.ProductWiki;
245
+ try {
246
+ const response = await this.request(url, { method: 'GET' }, isWiki);
247
+ if (response.status === 404 || (isWiki && response.status >= 500 && response.status < 600)) {
248
+ return undefined;
249
+ }
250
+ const body = await response.text();
251
+ const contentType = response.headers.get('Content-Type') ?? '';
252
+ // Some APIM policy endpoints return raw XML instead of JSON-wrapped XML.
253
+ // Detect by Content-Type header or body sniffing, and wrap in the expected
254
+ // ARM envelope so callers can access properties.value as normal.
255
+ if (contentType.includes('xml') || body.trimStart().startsWith('<')) {
256
+ return { properties: { value: body, format: 'rawxml' } };
257
+ }
258
+ return JSON.parse(body);
259
+ }
260
+ catch (error) {
261
+ // Some APIM association endpoints (ProductGroup, ProductApi, GatewayApi) only
262
+ // support PUT/DELETE and return HTTP 405 on GET. Return undefined so callers
263
+ // (e.g. dry-run reporter) treat them as "not found" rather than an error.
264
+ if (error instanceof HttpError && error.status === 405) {
265
+ logger.debug(`Resource does not support GET (HTTP 405), treating as not found: ${url}`);
266
+ return undefined;
267
+ }
268
+ logger.error(`Failed to get resource: ${error.message}`);
269
+ throw error;
270
+ }
271
+ }
272
+ async putResource(context, descriptor, payload) {
273
+ const url = buildArmUri(context, descriptor);
274
+ const response = await this.request(url, {
275
+ method: 'PUT',
276
+ body: JSON.stringify(payload),
277
+ });
278
+ // Poll for long-running operations (201/202 responses).
279
+ // Skip polling for association resources that don't support GET (supportsGet: false in metadata).
280
+ // Check status BEFORE reading the body so the body stream is not consumed
281
+ // unnecessarily — and to avoid JSON-parsing failures when the 201/202 body
282
+ // is XML (e.g. policy endpoints that echo back raw XML on creation).
283
+ if (response.status === 201 || response.status === 202) {
284
+ const metadata = RESOURCE_TYPE_METADATA[descriptor.type];
285
+ if (!metadata.supportsGet) {
286
+ // Association resources don't support GET - return empty on success
287
+ logger.debug(`Skipping provisioning poll for association resource: ${buildResourceLabel(descriptor)}`);
288
+ return {};
289
+ }
290
+ return await this.pollProvisioningState(context, descriptor);
291
+ }
292
+ // Some APIM endpoints (e.g. policy) return raw XML in the response body
293
+ // instead of JSON. Parse safely and wrap XML in the standard ARM envelope
294
+ // so callers always receive a uniform object.
295
+ const responseText = await response.text();
296
+ if (!responseText.trim()) {
297
+ return {};
298
+ }
299
+ try {
300
+ return JSON.parse(responseText);
301
+ }
302
+ catch {
303
+ if (responseText.trimStart().startsWith('<')) {
304
+ // Policy endpoints may respond with raw XML — normalise to ARM envelope
305
+ return { properties: { value: responseText, format: 'rawxml' } };
306
+ }
307
+ throw new SyntaxError(`Non-JSON response from APIM PUT ${url}: ${responseText.substring(0, 200)}`);
308
+ }
309
+ }
310
+ async deleteResource(context, descriptor) {
311
+ const url = buildArmUri(context, descriptor);
312
+ try {
313
+ const response = await this.request(url, { method: 'DELETE' });
314
+ if (response.status === 404) {
315
+ return false; // Already deleted
316
+ }
317
+ // Poll for long-running operations
318
+ if (response.status === 202) {
319
+ await this.pollProvisioningState(context, descriptor);
320
+ }
321
+ return true;
322
+ }
323
+ catch (error) {
324
+ if (error.message.includes('404')) {
325
+ return false;
326
+ }
327
+ throw error;
328
+ }
329
+ }
330
+ async *listApiRevisions(context, apiName) {
331
+ const url = `${context.baseUrl}/apis/${encodeURIComponent(apiName)}/revisions?api-version=${context.apiVersion}`;
332
+ const response = await this.request(url);
333
+ const data = await response.json();
334
+ if (data.value && Array.isArray(data.value)) {
335
+ for (const item of data.value) {
336
+ yield item;
337
+ }
338
+ }
339
+ }
340
+ async getApiSpecification(context, apiName, apiType) {
341
+ const exportFormat = this.getExportFormat(apiType);
342
+ if (exportFormat === undefined) {
343
+ return undefined;
344
+ }
345
+ const buildExportUrl = (format) => `${context.baseUrl}/apis/${encodeURIComponent(apiName)}?export=true&format=${format}&api-version=${context.apiVersion}`;
346
+ // APIM's wsdl-link / wadl-link emitters frequently return HTTP 500 on
347
+ // real-world APIs. When the link variant fails, fall back to the inline
348
+ // (non-link) export which returns the raw XML in the response body. We
349
+ // must preserve WSDL/WADL fidelity so the spec can be re-imported on
350
+ // publish (the Azure/apiops reference tool skips on 500; we cannot —
351
+ // these APIs must round-trip).
352
+ const isXmlExport = exportFormat === 'wsdl-link' || exportFormat === 'wadl-link';
353
+ const inlineFormat = exportFormat === 'wsdl-link' ? 'wsdl' :
354
+ exportFormat === 'wadl-link' ? 'wadl' :
355
+ undefined;
356
+ // GraphQL APIs without a downloadable SDL link return HTTP 406 — handle it
357
+ // as a valid "no spec available" signal rather than an error.
358
+ const isGraphQLLink = exportFormat === 'graphql-link';
359
+ const allowedNonOkStatuses = isGraphQLLink ? [406] : [];
360
+ try {
361
+ // Suppress the default 5xx retry loop for XML exports so we can fall
362
+ // back to the inline export instead of burning retries on a broken path.
363
+ const response = await this.request(buildExportUrl(exportFormat), {}, isXmlExport, false, allowedNonOkStatuses);
364
+ if (response.status === 404) {
365
+ return undefined;
366
+ }
367
+ if (isGraphQLLink && response.status === 406) {
368
+ logger.debug(`No graphql-link specification available for ${apiName} (HTTP 406); ` +
369
+ `GraphQL schema will be sourced from /schemas instead.`);
370
+ return undefined;
371
+ }
372
+ if (isXmlExport && inlineFormat && response.status >= 500 && response.status < 600) {
373
+ logger.warn(`APIM returned HTTP ${response.status} exporting ${exportFormat} for ${apiName}; ` +
374
+ `falling back to inline ${inlineFormat} export.`);
375
+ return await this.getInlineXmlSpecification(buildExportUrl(inlineFormat), inlineFormat, apiName);
376
+ }
377
+ const data = await response.json();
378
+ // APIM returns the SAS link at `data.link` (top-level) in api-version 2024-05-01.
379
+ const blobLink = data.link ?? data.value?.link;
380
+ if (!blobLink) {
381
+ return undefined;
382
+ }
383
+ // Fetch the actual spec content from the blob SAS URL (no auth header needed — SAS token is self-authenticating)
384
+ const blobResponse = await this.request(blobLink, {}, false, true);
385
+ if (!blobResponse.ok) {
386
+ logger.warn(`Failed to fetch specification blob for ${apiName}: HTTP ${blobResponse.status}`);
387
+ return undefined;
388
+ }
389
+ const content = await blobResponse.text();
390
+ // Detect format from API metadata or content
391
+ const format = this.detectSpecificationFormat(data.format ?? '', content);
392
+ return {
393
+ content,
394
+ format,
395
+ };
396
+ }
397
+ catch (error) {
398
+ logger.warn(`Failed to get API specification for ${apiName}: ${error.message}`);
399
+ return undefined;
400
+ }
401
+ }
402
+ /**
403
+ * Fall back to the non-link (inline) WSDL/WADL export when wsdl-link / wadl-link
404
+ * returns HTTP 500. APIM returns the XML in `properties.value` as a JSON-escaped
405
+ * string. The extracted content is suitable for re-import via PUT ?import=true
406
+ * with the matching non-link format (e.g. format=wsdl for SOAP APIs), so SOAP
407
+ * round-tripping is preserved.
408
+ */
409
+ async getInlineXmlSpecification(url, inlineFormat, apiName) {
410
+ try {
411
+ const response = await this.request(url);
412
+ if (response.status === 404) {
413
+ return undefined;
414
+ }
415
+ if (!response.ok) {
416
+ logger.warn(`Inline ${inlineFormat} export for ${apiName} failed: HTTP ${response.status}. Specification will be skipped.`);
417
+ return undefined;
418
+ }
419
+ // APIM's inline export endpoint is inconsistent: depending on the
420
+ // api-version and the API's internal representation, the body may be
421
+ // (a) raw XML (e.g. `<?xml ...><wsdl:definitions ...>`), or
422
+ // (b) a JSON wrapper `{ properties: { value: "<wsdl...>" } }` / `{ value: "<wsdl...>" }`,
423
+ // or (c) a plain-text error like "Unable to export ...".
424
+ // We read as text first and sniff, which is robust to all three shapes.
425
+ const text = await response.text();
426
+ const trimmed = text.trimStart();
427
+ let content;
428
+ if (trimmed.startsWith('<')) {
429
+ // Raw XML response — use the body directly.
430
+ content = text;
431
+ }
432
+ else if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
433
+ try {
434
+ const body = JSON.parse(text);
435
+ const raw = body.properties?.value ?? body.value;
436
+ content = typeof raw === 'string' ? raw : undefined;
437
+ }
438
+ catch {
439
+ // Fall through to the "unexpected body" path below.
440
+ }
441
+ }
442
+ if (!content || content.length === 0) {
443
+ const preview = text.length > 120 ? `${text.slice(0, 120)}…` : text;
444
+ logger.warn(`Inline ${inlineFormat} export for ${apiName} returned an unexpected body; skipping. Preview: ${preview}`);
445
+ return undefined;
446
+ }
447
+ const format = inlineFormat;
448
+ return { content, format };
449
+ }
450
+ catch (error) {
451
+ logger.warn(`Inline ${inlineFormat} export for ${apiName} threw: ${error.message}. Specification will be skipped.`);
452
+ return undefined;
453
+ }
454
+ }
455
+ /**
456
+ * Map APIM API type to the appropriate export format query parameter.
457
+ * All APIM export formats return a SAS blob link (link-based, not inline content).
458
+ *
459
+ * APIM properties.type values and their export format mappings:
460
+ * graphql-link – GraphQL SDL blob (type=graphql)
461
+ * wsdl-link – WSDL blob (type=soap)
462
+ * openapi-link – OpenAPI 3.0 YAML (type=http, default)
463
+ * undefined – (type=websocket — no spec; callers should skip)
464
+ *
465
+ * SOAP APIs use wsdl-link so the exported specification can be re-imported
466
+ * faithfully on publish (matches the Azure/apiops reference tool). APIM's
467
+ * wsdl-link emitter occasionally returns HTTP 500 on real-world SOAP APIs;
468
+ * getApiSpecification handles that by falling back to the inline (non-link)
469
+ * `format=wsdl` export, which returns the raw WSDL in the response body.
470
+ * The inline WSDL is re-importable via PUT ?import=true&format=wsdl, so SOAP
471
+ * round-tripping is preserved even when the link variant is broken.
472
+ *
473
+ * Additional export formats supported by APIM for type=http REST APIs:
474
+ * swagger-link – Swagger 2.0 YAML
475
+ * openapi+json-link – OpenAPI 3.0 JSON
476
+ * wadl-link – WADL
477
+ * These cannot be auto-selected from properties.type alone because all REST APIs
478
+ * (whether originally imported as Swagger 2.0, OpenAPI 3.0, or WADL) share
479
+ * type=http in APIM. openapi-link is used as the preferred modern default.
480
+ *
481
+ * Returns undefined for WebSocket APIs — they have no traditional API specification.
482
+ * getApiSpecification will return undefined early when this method returns undefined.
483
+ */
484
+ getExportFormat(apiType) {
485
+ switch (apiType?.toLowerCase()) {
486
+ case 'graphql': return 'graphql-link';
487
+ case 'soap': return 'wsdl-link';
488
+ case 'websocket': return undefined;
489
+ default: return 'openapi-link';
490
+ }
491
+ }
492
+ async validatePreFlight(context) {
493
+ // Check resource group exists
494
+ const rgUrl = `https://management.azure.com/subscriptions/${encodeURIComponent(context.subscriptionId)}/resourceGroups/${encodeURIComponent(context.resourceGroup)}?api-version=${ApimClient.RESOURCE_GROUP_API_VERSION}`;
495
+ let rgResponse;
496
+ try {
497
+ rgResponse = await this.request(rgUrl, { method: 'GET' });
498
+ }
499
+ catch (error) {
500
+ this.throwPreFlightHttpError(error, `resource group '${context.resourceGroup}'`, `the subscription or resource group`);
501
+ }
502
+ if (rgResponse.status === 404) {
503
+ throw new Error(`Resource group '${context.resourceGroup}' not found in subscription '${context.subscriptionId}'. ` +
504
+ `Ensure the resource group exists before publishing.`);
505
+ }
506
+ // Check APIM service instance exists
507
+ const apimUrl = `${context.baseUrl}?api-version=${context.apiVersion}`;
508
+ let apimResponse;
509
+ try {
510
+ apimResponse = await this.request(apimUrl, { method: 'GET' });
511
+ }
512
+ catch (error) {
513
+ this.throwPreFlightHttpError(error, `APIM service '${context.serviceName}'`, `the APIM resource`);
514
+ }
515
+ if (apimResponse.status === 404) {
516
+ throw new Error(`APIM service '${context.serviceName}' not found in resource group '${context.resourceGroup}'. ` +
517
+ `Ensure the APIM instance exists before publishing.`);
518
+ }
519
+ }
520
+ /**
521
+ * Rethrows HttpError 401/403 responses from pre-flight checks as actionable errors.
522
+ * Non-HTTP errors and other status codes are re-thrown unchanged.
523
+ */
524
+ throwPreFlightHttpError(error, resourceLabel, roleTarget) {
525
+ if (error instanceof HttpError && error.status === 403) {
526
+ throw new Error(`Insufficient permissions to read ${resourceLabel}. ` +
527
+ `Ensure the service principal has at least Reader role on ${roleTarget}.`, { cause: error });
528
+ }
529
+ if (error instanceof HttpError && error.status === 401) {
530
+ throw new Error(`Authentication failed when checking ${resourceLabel}. ` +
531
+ `Verify that credentials are valid and the correct tenant/subscription is targeted.`, { cause: error });
532
+ }
533
+ throw error;
534
+ }
535
+ detectSpecificationFormat(formatHint, content) {
536
+ const lowerFormat = formatHint.toLowerCase();
537
+ if (lowerFormat.includes('graphql'))
538
+ return 'graphql';
539
+ if (lowerFormat.includes('wsdl'))
540
+ return 'wsdl';
541
+ if (lowerFormat.includes('wadl'))
542
+ return 'wadl';
543
+ if (lowerFormat.includes('json'))
544
+ return 'json';
545
+ // Try to detect from content
546
+ const trimmed = content.trim();
547
+ if (trimmed.startsWith('{') || trimmed.startsWith('['))
548
+ return 'json';
549
+ if (trimmed.startsWith('<?xml')) {
550
+ if (content.includes('wsdl:'))
551
+ return 'wsdl';
552
+ if (content.includes('wadl:'))
553
+ return 'wadl';
554
+ }
555
+ if (trimmed.includes('type Query') || trimmed.includes('type Mutation'))
556
+ return 'graphql';
557
+ // Default to YAML for OpenAPI
558
+ return 'yaml';
559
+ }
560
+ async pollProvisioningState(context, descriptor) {
561
+ for (let attempt = 0; attempt < ApimClient.MAX_POLLING_ATTEMPTS; attempt++) {
562
+ await this.delay(ApimClient.POLL_INTERVAL_MS);
563
+ const resource = await this.getResource(context, descriptor);
564
+ if (!resource) {
565
+ // APIM can transiently return 404 while asynchronously provisioning a
566
+ // resource (e.g. a Key Vault-backed named value). Treat a missing resource
567
+ // as "not yet visible" and continue polling rather than aborting — the
568
+ // resource will either appear on a subsequent poll or we time out after
569
+ // MAX_POLLING_ATTEMPTS.
570
+ logger.debug(`Resource not yet visible during provisioning poll (attempt ${attempt + 1}/${ApimClient.MAX_POLLING_ATTEMPTS}): ${buildResourceLabel(descriptor)}`);
571
+ continue;
572
+ }
573
+ const properties = resource.properties;
574
+ const provisioningState = properties?.provisioningState;
575
+ if (!provisioningState || provisioningState === 'Succeeded') {
576
+ return resource;
577
+ }
578
+ if (provisioningState === 'Failed') {
579
+ throw new Error(`Resource provisioning failed: ${JSON.stringify(properties)}`);
580
+ }
581
+ logger.debug(`Polling provisioning state: ${provisioningState} (attempt ${attempt + 1}/${ApimClient.MAX_POLLING_ATTEMPTS})`);
582
+ }
583
+ throw new Error('Provisioning state polling timed out');
584
+ }
585
+ }
586
+ //# sourceMappingURL=apim-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apim-client.js","sourceRoot":"","sources":["../../src/clients/apim-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * T017: Filesystem artifact store implementing IArtifactStore
3
+ * Read/write resource JSON files, policy XML, API specs, associations, wiki markdown
4
+ */
5
+ import { IArtifactStore } from './iartifact-store.js';
6
+ import { ResourceDescriptor } from '../models/types.js';
7
+ export declare class ArtifactStore implements IArtifactStore {
8
+ writeResource(baseDir: string, descriptor: ResourceDescriptor, json: Record<string, unknown>): Promise<void>;
9
+ writeContent(baseDir: string, descriptor: ResourceDescriptor, content: string, contentType: 'policy' | 'specification', format?: string): Promise<void>;
10
+ writeAssociation(baseDir: string, descriptor: ResourceDescriptor, associationType: 'apis' | 'groups' | 'tags', names: string[]): Promise<void>;
11
+ readResource(baseDir: string, descriptor: ResourceDescriptor): Promise<Record<string, unknown> | undefined>;
12
+ readContent(baseDir: string, descriptor: ResourceDescriptor, contentType: 'policy' | 'specification'): Promise<{
13
+ content: string;
14
+ format?: string;
15
+ } | undefined>;
16
+ readAssociation(baseDir: string, descriptor: ResourceDescriptor, associationType: 'apis' | 'groups' | 'tags'): Promise<string[]>;
17
+ listResources(baseDir: string): Promise<ResourceDescriptor[]>;
18
+ deleteResource(baseDir: string, descriptor: ResourceDescriptor): Promise<void>;
19
+ private ensureDirectory;
20
+ private walkDirectory;
21
+ private descriptorEquals;
22
+ }
23
+ //# sourceMappingURL=artifact-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/clients/artifact-store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAWxD,qBAAa,aAAc,YAAW,cAAc;IAC5C,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAgBV,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,QAAQ,GAAG,eAAe,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAsBV,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,EAC3C,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC;IAWV,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAoBzC,WAAW,CACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,QAAQ,GAAG,eAAe,GACtC,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IA6CtD,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,EAC9B,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAC1C,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBd,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAiB7D,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,kBAAkB,GAC7B,OAAO,CAAC,IAAI,CAAC;YAeF,eAAe;YAQf,aAAa;IAyB3B,OAAO,CAAC,gBAAgB;CAQzB"}