@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,374 @@
1
+ /**
2
+ * T020: Extraction orchestrator
3
+ * Coordinates resource type extraction across dependency tiers
4
+ * using dependency-graph.ts and parallel-runner.ts.
5
+ * Per-resource status output per FR-023.
6
+ */
7
+ import { ResourceType } from '../models/resource-types.js';
8
+ import { TIER_1_RESOURCES, TIER_2_RESOURCES, TIER_3_RESOURCES, } from '../lib/dependency-graph.js';
9
+ import { runParallel } from '../lib/parallel-runner.js';
10
+ import { extractResourceType, } from './resource-extractor.js';
11
+ import { isSingletonType, isChildType } from '../lib/resource-path.js';
12
+ import { extractApiResources } from './api-extractor.js';
13
+ import { extractProductResources } from './product-extractor.js';
14
+ import { extractWorkspaces } from './workspace-extractor.js';
15
+ import { findTransitiveDependencies, } from './transitive-resolver.js';
16
+ import { logger } from '../lib/logger.js';
17
+ import { buildResourceLabel } from '../lib/resource-uri.js';
18
+ import { EXIT_SUCCESS, EXIT_PARTIAL, EXIT_FATAL } from '../lib/exit-codes.js';
19
+ import { getNamePart, getNameFromNameParts } from '../lib/resource-path.js';
20
+ /** Maximum concurrency for parallel extraction within a tier */
21
+ const DEFAULT_CONCURRENCY = 5;
22
+ /**
23
+ * Run the full extraction orchestration.
24
+ *
25
+ * Extraction proceeds in dependency tiers (1-4), with resources within
26
+ * each tier extracted in parallel. After tier 2, API-specific and
27
+ * product-specific sub-extractions run. Transitive dependency resolution
28
+ * happens after all tiers complete if enabled.
29
+ */
30
+ export async function runExtraction(client, store, config) {
31
+ const result = {
32
+ totalExtracted: 0,
33
+ totalErrors: 0,
34
+ typeResults: [],
35
+ apiResults: [],
36
+ productResults: [],
37
+ workspaceResults: [],
38
+ extractedDescriptors: [],
39
+ collectedPolicies: new Map(),
40
+ exitCode: EXIT_SUCCESS,
41
+ };
42
+ const { service, outputDir, filter } = config;
43
+ logger.info(`Starting extraction from ${service.serviceName}...`);
44
+ logger.debug(`Output directory: ${outputDir}`);
45
+ try {
46
+ // Phase 1: Extract Tier 1 resources (no dependencies)
47
+ logger.info('Extracting tier 1 resources (independent)...');
48
+ await extractTier(client, store, service, TIER_1_RESOURCES, outputDir, filter, result);
49
+ // Phase 2: Extract Tier 2 resources (depend on tier 1)
50
+ logger.info('Extracting tier 2 resources...');
51
+ await extractTier(client, store, service, TIER_2_RESOURCES, outputDir, filter, result);
52
+ // Phase 2.5: Extract API-specific and product-specific sub-resources
53
+ await extractApiSubResources(client, store, service, outputDir, filter, result);
54
+ await extractProductSubResources(client, store, service, outputDir, filter, result);
55
+ // Phase 3: Extract Tier 3 child resources
56
+ // Note: Many tier 3 types (ApiTag, ApiDiagnostic, etc.) are extracted as part
57
+ // of API-specific extraction above, so we only extract top-level listable types here.
58
+ // Child types (requiring a parent) are handled by api-extractor, product-extractor,
59
+ // or extractGatewayAssociations below.
60
+ logger.info('Extracting tier 3 resources...');
61
+ const tier3TopLevel = TIER_3_RESOURCES.filter((t) => !isSingletonType(t) && !isChildType(t));
62
+ await extractTier(client, store, service, tier3TopLevel, outputDir, filter, result);
63
+ // Extract gateway API associations
64
+ await extractGatewayAssociations(client, store, service, outputDir, filter, result);
65
+ // Phase 4: Tier 4 resources are extracted within API-specific extraction
66
+ // (ApiOperationPolicy, GraphQLResolverPolicy are handled in api-extractor)
67
+ // Phase 5: Extract service-level policy
68
+ await extractServicePolicy(client, store, service, outputDir, result);
69
+ // Phase 6: Transitive dependency resolution (if enabled)
70
+ if (config.includeTransitive && filter) {
71
+ await resolveAndExtractTransitive(client, store, service, outputDir, result);
72
+ }
73
+ // Phase 7: Extract workspace-scoped resources
74
+ await extractWorkspaceResources(client, store, service, outputDir, filter, result);
75
+ // Compute exit code
76
+ if (result.totalErrors > 0 && result.totalExtracted > 0) {
77
+ result.exitCode = EXIT_PARTIAL;
78
+ }
79
+ else if (result.totalErrors > 0 && result.totalExtracted === 0) {
80
+ result.exitCode = EXIT_FATAL;
81
+ }
82
+ logger.info(`Extraction complete: ${result.totalExtracted} resources extracted, ${result.totalErrors} errors`);
83
+ }
84
+ catch (error) {
85
+ const errorMessage = error instanceof Error ? error.message : String(error);
86
+ logger.error(`Fatal extraction error: ${errorMessage}`);
87
+ result.exitCode = EXIT_FATAL;
88
+ result.totalErrors++;
89
+ }
90
+ return result;
91
+ }
92
+ /**
93
+ * Extract all resources of given types in parallel within a tier.
94
+ * Collects results per-task and merges after all tasks complete to avoid
95
+ * concurrent mutations on the shared result object.
96
+ */
97
+ async function extractTier(client, store, context, types, outputDir, filter, result) {
98
+ const tasks = types.map((type) => async () => {
99
+ // Skip singleton types — they're handled separately
100
+ if (isSingletonType(type)) {
101
+ return undefined;
102
+ }
103
+ return extractResourceType(client, store, context, type, outputDir, filter);
104
+ });
105
+ const taskResults = await runParallel(tasks, DEFAULT_CONCURRENCY);
106
+ // Merge results sequentially after parallel execution completes
107
+ for (const taskResult of taskResults) {
108
+ if (taskResult.status === 'fulfilled' && taskResult.value) {
109
+ const typeResult = taskResult.value;
110
+ result.typeResults.push(typeResult);
111
+ result.totalExtracted += typeResult.extracted.filter((r) => r.status === 'success').length;
112
+ result.totalErrors += typeResult.errorCount;
113
+ for (const res of typeResult.extracted) {
114
+ if (res.status === 'success') {
115
+ result.extractedDescriptors.push(res.descriptor);
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ /**
122
+ * Extract API sub-resources (revisions, specs, operations, etc.) for all extracted APIs.
123
+ * Collects results per-task and merges after all tasks complete to avoid
124
+ * concurrent mutations on the shared result object.
125
+ */
126
+ async function extractApiSubResources(client, store, context, outputDir, filter, result) {
127
+ const apiResults = result.typeResults.filter((r) => r.type === ResourceType.Api);
128
+ for (const apiTypeResult of apiResults) {
129
+ const apiTasks = apiTypeResult.extracted
130
+ .filter((r) => r.status === 'success')
131
+ .map((api) => async () => {
132
+ const apiResult = await extractApiResources(client, store, context, api.descriptor, api.json, outputDir, filter);
133
+ return { apiName: getNameFromNameParts(api.descriptor.nameParts), apiResult };
134
+ });
135
+ const taskResults = await runParallel(apiTasks, DEFAULT_CONCURRENCY);
136
+ // Collect the per-API descriptors in the same order as tasks (for error attribution)
137
+ const apis = apiTypeResult.extracted.filter((r) => r.status === 'success');
138
+ // Merge results sequentially after parallel execution completes
139
+ for (let i = 0; i < taskResults.length; i++) {
140
+ const taskResult = taskResults[i];
141
+ if (!taskResult)
142
+ continue;
143
+ if (taskResult.status === 'rejected') {
144
+ const apiName = buildResourceLabel(apis[i].descriptor);
145
+ logger.error(`Failed to extract sub-resources for API "${apiName}": ${taskResult.reason?.message}`);
146
+ result.totalErrors++;
147
+ continue;
148
+ }
149
+ if (!taskResult.value)
150
+ continue;
151
+ const { apiName, apiResult } = taskResult.value;
152
+ result.apiResults.push(apiResult);
153
+ // Count sub-resources
154
+ const subCount = apiResult.revisions.filter((r) => r.status === 'success').length +
155
+ (apiResult.specification ? 1 : 0) +
156
+ apiResult.operations.filter((r) => r.status === 'success').length +
157
+ apiResult.operationPolicies.filter((r) => r.status === 'success').length +
158
+ apiResult.tags.filter((r) => r.status === 'success').length +
159
+ apiResult.diagnostics.filter((r) => r.status === 'success').length +
160
+ apiResult.schemas.filter((r) => r.status === 'success').length +
161
+ apiResult.releases.filter((r) => r.status === 'success').length +
162
+ apiResult.tagDescriptions.filter((r) => r.status === 'success').length +
163
+ (apiResult.wiki ? 1 : 0) +
164
+ apiResult.resolvers.filter((r) => r.status === 'success').length +
165
+ apiResult.resolverPolicies.filter((r) => r.status === 'success').length;
166
+ result.totalExtracted += subCount;
167
+ // Collect policies for transitive resolution
168
+ for (let pi = 0; pi < apiResult.policies.length; pi++) {
169
+ const policyContent = apiResult.policies[pi];
170
+ if (policyContent !== undefined) {
171
+ const key = `api:${apiName}:policy:${pi}`;
172
+ result.collectedPolicies.set(key, policyContent);
173
+ }
174
+ }
175
+ // Track sub-resource descriptors
176
+ for (const sub of [
177
+ ...apiResult.operations,
178
+ ...apiResult.operationPolicies,
179
+ ...apiResult.tags,
180
+ ...apiResult.diagnostics,
181
+ ...apiResult.schemas,
182
+ ...apiResult.releases,
183
+ ...apiResult.tagDescriptions,
184
+ ...apiResult.resolvers,
185
+ ...apiResult.resolverPolicies,
186
+ ]) {
187
+ if (sub.status === 'success') {
188
+ result.extractedDescriptors.push(sub.descriptor);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ /**
195
+ * Extract product sub-resources for all extracted products.
196
+ * Collects results per-task and merges after all tasks complete to avoid
197
+ * concurrent mutations on the shared result object.
198
+ */
199
+ async function extractProductSubResources(client, store, context, outputDir, filter, result) {
200
+ const productResults = result.typeResults.filter((r) => r.type === ResourceType.Product);
201
+ for (const productTypeResult of productResults) {
202
+ const productTasks = productTypeResult.extracted
203
+ .filter((r) => r.status === 'success')
204
+ .map((product) => async () => {
205
+ const prodResult = await extractProductResources(client, store, context, product.descriptor, outputDir, filter);
206
+ return { productName: getNameFromNameParts(product.descriptor.nameParts), prodResult };
207
+ });
208
+ const taskResults = await runParallel(productTasks, DEFAULT_CONCURRENCY);
209
+ // Collect the per-product descriptors in the same order as tasks (for error attribution)
210
+ const products = productTypeResult.extracted.filter((r) => r.status === 'success');
211
+ // Merge results sequentially after parallel execution completes
212
+ for (let i = 0; i < taskResults.length; i++) {
213
+ const taskResult = taskResults[i];
214
+ if (!taskResult)
215
+ continue;
216
+ if (taskResult.status === 'rejected') {
217
+ const productName = buildResourceLabel(products[i].descriptor);
218
+ logger.error(`Failed to extract sub-resources for product "${productName}": ${taskResult.reason?.message}`);
219
+ result.totalErrors++;
220
+ continue;
221
+ }
222
+ if (!taskResult.value)
223
+ continue;
224
+ const { productName, prodResult } = taskResult.value;
225
+ result.productResults.push(prodResult);
226
+ // Count sub-resources (associations + policy + wiki + tags)
227
+ const subCount = (prodResult.apis.length > 0 ? 1 : 0) +
228
+ (prodResult.groups.length > 0 ? 1 : 0) +
229
+ (prodResult.policy ? 1 : 0) +
230
+ (prodResult.wiki ? 1 : 0) +
231
+ (prodResult.tags.length > 0 ? 1 : 0);
232
+ result.totalExtracted += subCount;
233
+ // Collect policies for transitive resolution
234
+ for (let pi = 0; pi < prodResult.policies.length; pi++) {
235
+ const policyContent = prodResult.policies[pi];
236
+ if (policyContent !== undefined) {
237
+ const key = `product:${productName}:policy:${pi}`;
238
+ result.collectedPolicies.set(key, policyContent);
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ /**
245
+ * Extract service-level global policy.
246
+ */
247
+ async function extractServicePolicy(client, store, context, outputDir, result) {
248
+ const descriptor = {
249
+ type: ResourceType.ServicePolicy,
250
+ nameParts: [],
251
+ };
252
+ const policyJson = await client.getResource(context, descriptor);
253
+ if (!policyJson) {
254
+ return;
255
+ }
256
+ const properties = policyJson.properties;
257
+ const policyContent = properties?.value;
258
+ if (policyContent) {
259
+ await store.writeContent(outputDir, descriptor, policyContent, 'policy');
260
+ result.totalExtracted++;
261
+ result.extractedDescriptors.push(descriptor);
262
+ result.collectedPolicies.set('service-policy', policyContent);
263
+ logger.info('Extracted service-level policy');
264
+ }
265
+ }
266
+ /**
267
+ * Extract gateway API associations.
268
+ */
269
+ async function extractGatewayAssociations(client, store, context, outputDir, _filter, result) {
270
+ const gatewayResults = result.typeResults.filter((r) => r.type === ResourceType.Gateway);
271
+ for (const gwTypeResult of gatewayResults) {
272
+ for (const gw of gwTypeResult.extracted) {
273
+ if (gw.status !== 'success')
274
+ continue;
275
+ try {
276
+ const apiNames = [];
277
+ const gwApis = client.listResources(context, ResourceType.GatewayApi, gw.descriptor);
278
+ for await (const apiJson of gwApis) {
279
+ const name = apiJson.name;
280
+ if (name) {
281
+ apiNames.push(name);
282
+ }
283
+ }
284
+ if (apiNames.length > 0) {
285
+ await store.writeAssociation(outputDir, gw.descriptor, 'apis', apiNames);
286
+ result.totalExtracted++;
287
+ logger.info(`Extracted ${apiNames.length} API associations for gateway "${getNamePart(gw.descriptor.nameParts, 0)}"`);
288
+ }
289
+ }
290
+ catch (error) {
291
+ logger.warn(`Failed to extract API associations for gateway "${getNamePart(gw.descriptor.nameParts, 0)}": ${error.message}`);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ /**
297
+ * Resolve transitive dependencies and extract any additional resources.
298
+ * Collects results per-task and merges after all tasks complete to avoid
299
+ * concurrent mutations on the shared result object.
300
+ */
301
+ async function resolveAndExtractTransitive(client, store, context, outputDir, result) {
302
+ logger.info('Resolving transitive dependencies...');
303
+ // Build maps for transitive resolution
304
+ const apiJsonMap = new Map();
305
+ for (const apiResult of result.apiResults) {
306
+ // Find the API's JSON from type results
307
+ const apiTypeResults = result.typeResults.filter((r) => r.type === ResourceType.Api);
308
+ for (const atr of apiTypeResults) {
309
+ for (const extracted of atr.extracted) {
310
+ if (extracted.status === 'success' && getNamePart(extracted.descriptor.nameParts, 0) === apiResult.apiName) {
311
+ apiJsonMap.set(apiResult.apiName, extracted.json);
312
+ }
313
+ }
314
+ }
315
+ }
316
+ // Find transitive dependencies
317
+ const transitiveDeps = findTransitiveDependencies(result.collectedPolicies, apiJsonMap);
318
+ // Filter out already-extracted resources
319
+ // Use buildResourceLabel for the key — it handles singleton types (e.g.
320
+ // ServicePolicy) whose nameParts are empty, avoiding a getNamePart crash.
321
+ const alreadyExtracted = new Set(result.extractedDescriptors.map((d) => `${d.type}:${buildResourceLabel(d).toLowerCase()}`));
322
+ const newDeps = transitiveDeps.filter((dep) => !alreadyExtracted.has(`${dep.type}:${buildResourceLabel(dep).toLowerCase()}`));
323
+ if (newDeps.length === 0) {
324
+ logger.debug('No additional transitive dependencies found');
325
+ return;
326
+ }
327
+ logger.info(`Found ${newDeps.length} transitive dependencies to extract`);
328
+ // Extract each transitive dependency
329
+ const tasks = newDeps.map((dep) => async () => {
330
+ try {
331
+ const json = await client.getResource(context, dep);
332
+ if (json) {
333
+ await store.writeResource(outputDir, dep, json);
334
+ logger.info(`Extracted transitive dependency ${buildResourceLabel(dep)}`);
335
+ return { dep, success: true };
336
+ }
337
+ }
338
+ catch (error) {
339
+ const errorMessage = error instanceof Error ? error.message : String(error);
340
+ logger.warn(`Failed to extract transitive dependency ${buildResourceLabel(dep)}: ${errorMessage}`);
341
+ }
342
+ return { dep, success: false };
343
+ });
344
+ const taskResults = await runParallel(tasks, DEFAULT_CONCURRENCY);
345
+ // Merge results sequentially after parallel execution completes
346
+ for (const taskResult of taskResults) {
347
+ if (taskResult.status === 'fulfilled' && taskResult.value) {
348
+ if (taskResult.value.success) {
349
+ result.totalExtracted++;
350
+ result.extractedDescriptors.push(taskResult.value.dep);
351
+ }
352
+ else {
353
+ result.totalErrors++;
354
+ }
355
+ }
356
+ }
357
+ }
358
+ /**
359
+ * Extract workspace-scoped resources.
360
+ */
361
+ async function extractWorkspaceResources(client, store, context, outputDir, filter, result) {
362
+ try {
363
+ const wsResults = await extractWorkspaces(client, store, context, outputDir, filter);
364
+ result.workspaceResults = wsResults;
365
+ for (const ws of wsResults) {
366
+ result.totalExtracted += ws.resourceCount;
367
+ result.totalErrors += ws.errorCount;
368
+ }
369
+ }
370
+ catch (error) {
371
+ logger.warn(`Workspace extraction failed: ${error.message}`);
372
+ }
373
+ }
374
+ //# sourceMappingURL=extract-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-service.js","sourceRoot":"","sources":["../../src/services/extract-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * T024: Filter service
3
+ * Load FilterConfig, apply inclusive allowlist per resource type,
4
+ * case-insensitive matching, API root-name matching for revisions.
5
+ */
6
+ import { FilterConfig } from '../models/config.js';
7
+ import { ResourceDescriptor } from '../models/types.js';
8
+ /**
9
+ * Determines if a resource should be included based on the filter config.
10
+ *
11
+ * Rules:
12
+ * - If no filter config is provided, all resources are included.
13
+ * - If the filter field is undefined/absent for a resource type, all resources of that type are included.
14
+ * - If the filter field is an empty array, NO resources of that type are included.
15
+ * - Matching is case-insensitive.
16
+ * - API filter matches root name; all revisions of matching root are included.
17
+ * - Child resources inherit filter from their parent type.
18
+ */
19
+ export declare function shouldIncludeResource(descriptor: ResourceDescriptor, filter?: FilterConfig): boolean;
20
+ /**
21
+ * Extract root API name from a potentially revision-qualified name.
22
+ * E.g., "my-api;rev=2" → "my-api"
23
+ */
24
+ export declare function extractRootApiName(name: string): string;
25
+ /**
26
+ * Filter a list of resource descriptors based on filter config.
27
+ */
28
+ export declare function filterResources(descriptors: ResourceDescriptor[], filter?: FilterConfig): ResourceDescriptor[];
29
+ //# sourceMappingURL=filter-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-service.d.ts","sourceRoot":"","sources":["../../src/services/filter-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAiDxD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,kBAAkB,EAC9B,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CA2BT;AAeD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AA4BD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,kBAAkB,EAAE,EACjC,MAAM,CAAC,EAAE,YAAY,GACpB,kBAAkB,EAAE,CAatB"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * T024: Filter service
3
+ * Load FilterConfig, apply inclusive allowlist per resource type,
4
+ * case-insensitive matching, API root-name matching for revisions.
5
+ */
6
+ import { ResourceType } from '../models/resource-types.js';
7
+ import { logger } from '../lib/logger.js';
8
+ import { getNamePart } from '../lib/resource-path.js';
9
+ /**
10
+ * Map resource types to their corresponding FilterConfig field names.
11
+ */
12
+ const FILTER_FIELD_MAP = {
13
+ [ResourceType.Api]: 'apiNames',
14
+ [ResourceType.Backend]: 'backendNames',
15
+ [ResourceType.Product]: 'productNames',
16
+ [ResourceType.NamedValue]: 'namedValueNames',
17
+ [ResourceType.Logger]: 'loggerNames',
18
+ [ResourceType.Diagnostic]: 'diagnosticNames',
19
+ [ResourceType.Tag]: 'tagNames',
20
+ [ResourceType.PolicyFragment]: 'policyFragmentNames',
21
+ [ResourceType.Gateway]: 'gatewayNames',
22
+ [ResourceType.VersionSet]: 'versionSetNames',
23
+ [ResourceType.Group]: 'groupNames',
24
+ [ResourceType.Subscription]: 'subscriptionNames',
25
+ [ResourceType.GlobalSchema]: 'schemaNames',
26
+ [ResourceType.PolicyRestriction]: 'policyRestrictionNames',
27
+ [ResourceType.Documentation]: 'documentationNames',
28
+ };
29
+ /**
30
+ * Child resource types that inherit filter status from their parent.
31
+ * If the parent (e.g., Api or Product) passes the filter, all children are included.
32
+ */
33
+ const PARENT_FILTER_MAP = {
34
+ [ResourceType.ApiPolicy]: 'apiNames',
35
+ [ResourceType.ApiTag]: 'apiNames',
36
+ [ResourceType.ApiDiagnostic]: 'apiNames',
37
+ [ResourceType.ApiOperation]: 'apiNames',
38
+ [ResourceType.ApiOperationPolicy]: 'apiNames',
39
+ [ResourceType.ApiSchema]: 'apiNames',
40
+ [ResourceType.ApiRelease]: 'apiNames',
41
+ [ResourceType.ApiTagDescription]: 'apiNames',
42
+ [ResourceType.ApiWiki]: 'apiNames',
43
+ [ResourceType.GraphQLResolver]: 'apiNames',
44
+ [ResourceType.GraphQLResolverPolicy]: 'apiNames',
45
+ [ResourceType.ProductPolicy]: 'productNames',
46
+ [ResourceType.ProductApi]: 'productNames',
47
+ [ResourceType.ProductGroup]: 'productNames',
48
+ [ResourceType.ProductTag]: 'productNames',
49
+ [ResourceType.ProductWiki]: 'productNames',
50
+ [ResourceType.GatewayApi]: 'gatewayNames',
51
+ };
52
+ /**
53
+ * Determines if a resource should be included based on the filter config.
54
+ *
55
+ * Rules:
56
+ * - If no filter config is provided, all resources are included.
57
+ * - If the filter field is undefined/absent for a resource type, all resources of that type are included.
58
+ * - If the filter field is an empty array, NO resources of that type are included.
59
+ * - Matching is case-insensitive.
60
+ * - API filter matches root name; all revisions of matching root are included.
61
+ * - Child resources inherit filter from their parent type.
62
+ */
63
+ export function shouldIncludeResource(descriptor, filter) {
64
+ if (!filter) {
65
+ return true;
66
+ }
67
+ // Check direct filter field for this resource type
68
+ const directField = FILTER_FIELD_MAP[descriptor.type];
69
+ if (directField) {
70
+ return matchesFilter(getNamePart(descriptor.nameParts, 0), filter[directField]);
71
+ }
72
+ // Check parent-based filter for child resource types
73
+ const parentField = PARENT_FILTER_MAP[descriptor.type];
74
+ if (parentField) {
75
+ const parentName = getParentNameForFilter(descriptor);
76
+ if (parentName) {
77
+ return matchesFilter(parentName, filter[parentField]);
78
+ }
79
+ }
80
+ // ServicePolicy has no filter — always included
81
+ if (descriptor.type === ResourceType.ServicePolicy) {
82
+ return true;
83
+ }
84
+ // Unknown types are included by default
85
+ return true;
86
+ }
87
+ /**
88
+ * Get the parent name to use for filter matching.
89
+ * Uses PARENT_FILTER_MAP to determine which name-part is the parent, and
90
+ * applies revision-suffix stripping for API children.
91
+ */
92
+ function getParentNameForFilter(descriptor) {
93
+ const parentName = getNamePart(descriptor.nameParts, 0);
94
+ // API children need revision suffix stripped (e.g. "my-api;rev=2" → "my-api")
95
+ return PARENT_FILTER_MAP[descriptor.type] === 'apiNames'
96
+ ? extractRootApiName(parentName)
97
+ : parentName;
98
+ }
99
+ /**
100
+ * Extract root API name from a potentially revision-qualified name.
101
+ * E.g., "my-api;rev=2" → "my-api"
102
+ */
103
+ export function extractRootApiName(name) {
104
+ const semiIndex = name.indexOf(';');
105
+ return semiIndex >= 0 ? name.substring(0, semiIndex) : name;
106
+ }
107
+ /**
108
+ * Match a resource name against a filter allowlist.
109
+ *
110
+ * - undefined allowlist → include all (no filter for this type)
111
+ * - empty array → include none
112
+ * - non-empty array → case-insensitive match
113
+ */
114
+ function matchesFilter(name, allowlist) {
115
+ if (allowlist === undefined) {
116
+ return true;
117
+ }
118
+ if (allowlist.length === 0) {
119
+ return false;
120
+ }
121
+ const lowerName = name.toLowerCase();
122
+ // For APIs, also match by root name (strip revision suffix)
123
+ const lowerRoot = extractRootApiName(lowerName);
124
+ return allowlist.some((allowed) => {
125
+ const lowerAllowed = allowed.toLowerCase();
126
+ return lowerName === lowerAllowed || lowerRoot === lowerAllowed;
127
+ });
128
+ }
129
+ /**
130
+ * Filter a list of resource descriptors based on filter config.
131
+ */
132
+ export function filterResources(descriptors, filter) {
133
+ if (!filter) {
134
+ return descriptors;
135
+ }
136
+ const filtered = descriptors.filter((d) => shouldIncludeResource(d, filter));
137
+ const excluded = descriptors.length - filtered.length;
138
+ if (excluded > 0) {
139
+ logger.debug(`Filter excluded ${excluded} of ${descriptors.length} resources`);
140
+ }
141
+ return filtered;
142
+ }
143
+ //# sourceMappingURL=filter-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-service.js","sourceRoot":"","sources":["../../src/services/filter-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * T036: Git diff service
3
+ * Compute changed resource artifacts between commits using simple-git.
4
+ * Maps file paths to ResourceDescriptors for incremental publish.
5
+ */
6
+ import { ResourceDescriptor } from '../models/types.js';
7
+ export interface GitDiffResult {
8
+ /** Resources modified or added in this commit */
9
+ changedDescriptors: ResourceDescriptor[];
10
+ /** Resources deleted in this commit */
11
+ deletedDescriptors: ResourceDescriptor[];
12
+ }
13
+ /**
14
+ * Compute which resource artifacts changed between commitId~1 and commitId.
15
+ * Uses simple-git. Maps file paths to ResourceDescriptors.
16
+ * Returns empty arrays if git is unavailable or path not in a repo.
17
+ *
18
+ * @param sourceDir - Root artifact directory
19
+ * @param commitId - Commit SHA to diff against its parent
20
+ * @returns Changed and deleted resource descriptors
21
+ */
22
+ export declare function computeGitDiff(sourceDir: string, commitId: string): Promise<GitDiffResult>;
23
+ //# sourceMappingURL=git-diff-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-diff-service.d.ts","sourceRoot":"","sources":["../../src/services/git-diff-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC,uCAAuC;IACvC,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAuCxB"}