@fractary/faber 2.4.40 → 2.4.42

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 (353) hide show
  1. package/dist/__tests__/config.test.d.ts +0 -0
  2. package/dist/__tests__/config.test.d.ts.map +0 -0
  3. package/dist/__tests__/config.test.js +0 -0
  4. package/dist/__tests__/config.test.js.map +0 -0
  5. package/dist/__tests__/integration/forge-integration.test.d.ts +0 -0
  6. package/dist/__tests__/integration/forge-integration.test.d.ts.map +0 -0
  7. package/dist/__tests__/integration/forge-integration.test.js +2 -2
  8. package/dist/__tests__/integration/forge-integration.test.js.map +1 -1
  9. package/dist/__tests__/integration/init-workflow.test.d.ts +0 -0
  10. package/dist/__tests__/integration/init-workflow.test.d.ts.map +0 -0
  11. package/dist/__tests__/integration/init-workflow.test.js +0 -0
  12. package/dist/__tests__/integration/init-workflow.test.js.map +0 -0
  13. package/dist/agents/index.d.ts +0 -0
  14. package/dist/agents/index.d.ts.map +0 -0
  15. package/dist/agents/index.js +0 -0
  16. package/dist/agents/index.js.map +0 -0
  17. package/dist/agents/selector.d.ts +0 -0
  18. package/dist/agents/selector.d.ts.map +0 -0
  19. package/dist/agents/selector.js +0 -0
  20. package/dist/agents/selector.js.map +0 -0
  21. package/dist/agents/type-registry.d.ts +0 -0
  22. package/dist/agents/type-registry.d.ts.map +0 -0
  23. package/dist/agents/type-registry.js +0 -0
  24. package/dist/agents/type-registry.js.map +0 -0
  25. package/dist/agents/types.d.ts +0 -0
  26. package/dist/agents/types.d.ts.map +0 -0
  27. package/dist/agents/types.js +0 -0
  28. package/dist/agents/types.js.map +0 -0
  29. package/dist/auth/github-app.d.ts +0 -0
  30. package/dist/auth/github-app.d.ts.map +0 -0
  31. package/dist/auth/github-app.js +0 -0
  32. package/dist/auth/github-app.js.map +0 -0
  33. package/dist/auth/index.d.ts +0 -0
  34. package/dist/auth/index.d.ts.map +0 -0
  35. package/dist/auth/index.js +0 -0
  36. package/dist/auth/index.js.map +0 -0
  37. package/dist/changelog/index.d.ts +0 -0
  38. package/dist/changelog/index.d.ts.map +0 -0
  39. package/dist/changelog/index.js +0 -0
  40. package/dist/changelog/index.js.map +0 -0
  41. package/dist/changelog/manager.d.ts +0 -0
  42. package/dist/changelog/manager.d.ts.map +0 -0
  43. package/dist/changelog/manager.js +0 -0
  44. package/dist/changelog/manager.js.map +0 -0
  45. package/dist/changelog/types.d.ts +0 -0
  46. package/dist/changelog/types.d.ts.map +0 -0
  47. package/dist/changelog/types.js +0 -0
  48. package/dist/changelog/types.js.map +0 -0
  49. package/dist/cloud/__tests__/resource-manager.test.d.ts +7 -0
  50. package/dist/cloud/__tests__/resource-manager.test.d.ts.map +1 -0
  51. package/dist/cloud/__tests__/resource-manager.test.js +741 -0
  52. package/dist/cloud/__tests__/resource-manager.test.js.map +1 -0
  53. package/dist/cloud/__tests__/terraform-manager.test.d.ts +7 -0
  54. package/dist/cloud/__tests__/terraform-manager.test.d.ts.map +1 -0
  55. package/dist/cloud/__tests__/terraform-manager.test.js +493 -0
  56. package/dist/cloud/__tests__/terraform-manager.test.js.map +1 -0
  57. package/dist/cloud/index.d.ts +9 -0
  58. package/dist/cloud/index.d.ts.map +1 -0
  59. package/dist/cloud/index.js +11 -0
  60. package/dist/cloud/index.js.map +1 -0
  61. package/dist/cloud/resource-manager.d.ts +81 -0
  62. package/dist/cloud/resource-manager.d.ts.map +1 -0
  63. package/dist/cloud/resource-manager.js +288 -0
  64. package/dist/cloud/resource-manager.js.map +1 -0
  65. package/dist/cloud/terraform-manager.d.ts +108 -0
  66. package/dist/cloud/terraform-manager.d.ts.map +1 -0
  67. package/dist/cloud/terraform-manager.js +552 -0
  68. package/dist/cloud/terraform-manager.js.map +1 -0
  69. package/dist/cloud/types.d.ts +281 -0
  70. package/dist/cloud/types.d.ts.map +1 -0
  71. package/dist/cloud/types.js +7 -0
  72. package/dist/cloud/types.js.map +1 -0
  73. package/dist/config/__tests__/initializer.test.d.ts +0 -0
  74. package/dist/config/__tests__/initializer.test.d.ts.map +0 -0
  75. package/dist/config/__tests__/initializer.test.js +0 -0
  76. package/dist/config/__tests__/initializer.test.js.map +0 -0
  77. package/dist/config/initializer.d.ts +0 -0
  78. package/dist/config/initializer.d.ts.map +0 -0
  79. package/dist/config/initializer.js +0 -0
  80. package/dist/config/initializer.js.map +0 -0
  81. package/dist/config/updater.d.ts +0 -0
  82. package/dist/config/updater.d.ts.map +0 -0
  83. package/dist/config/updater.js +0 -0
  84. package/dist/config/updater.js.map +0 -0
  85. package/dist/config/validator.d.ts +0 -0
  86. package/dist/config/validator.d.ts.map +0 -0
  87. package/dist/config/validator.js +0 -0
  88. package/dist/config/validator.js.map +0 -0
  89. package/dist/config.d.ts +0 -0
  90. package/dist/config.d.ts.map +0 -0
  91. package/dist/config.js +0 -0
  92. package/dist/config.js.map +0 -0
  93. package/dist/defaults.d.ts +0 -0
  94. package/dist/defaults.d.ts.map +0 -0
  95. package/dist/defaults.js +0 -0
  96. package/dist/defaults.js.map +0 -0
  97. package/dist/errors.d.ts +0 -0
  98. package/dist/errors.d.ts.map +0 -0
  99. package/dist/errors.js +0 -0
  100. package/dist/errors.js.map +0 -0
  101. package/dist/executors/cli-entry.d.ts +0 -0
  102. package/dist/executors/cli-entry.d.ts.map +0 -0
  103. package/dist/executors/cli-entry.js +0 -0
  104. package/dist/executors/cli-entry.js.map +0 -0
  105. package/dist/executors/index.d.ts +0 -0
  106. package/dist/executors/index.d.ts.map +0 -0
  107. package/dist/executors/index.js +0 -0
  108. package/dist/executors/index.js.map +0 -0
  109. package/dist/executors/providers/claude.d.ts +0 -0
  110. package/dist/executors/providers/claude.d.ts.map +0 -0
  111. package/dist/executors/providers/claude.js +0 -0
  112. package/dist/executors/providers/claude.js.map +0 -0
  113. package/dist/executors/providers/http.d.ts +0 -0
  114. package/dist/executors/providers/http.d.ts.map +0 -0
  115. package/dist/executors/providers/http.js +0 -0
  116. package/dist/executors/providers/http.js.map +0 -0
  117. package/dist/executors/providers/index.d.ts +0 -0
  118. package/dist/executors/providers/index.d.ts.map +0 -0
  119. package/dist/executors/providers/index.js +0 -0
  120. package/dist/executors/providers/index.js.map +0 -0
  121. package/dist/executors/providers/openai-compatible.d.ts +0 -0
  122. package/dist/executors/providers/openai-compatible.d.ts.map +0 -0
  123. package/dist/executors/providers/openai-compatible.js +0 -0
  124. package/dist/executors/providers/openai-compatible.js.map +0 -0
  125. package/dist/executors/providers/openai.d.ts +0 -0
  126. package/dist/executors/providers/openai.d.ts.map +0 -0
  127. package/dist/executors/providers/openai.js +0 -0
  128. package/dist/executors/providers/openai.js.map +0 -0
  129. package/dist/executors/registry.d.ts +0 -0
  130. package/dist/executors/registry.d.ts.map +0 -0
  131. package/dist/executors/registry.js +0 -0
  132. package/dist/executors/registry.js.map +0 -0
  133. package/dist/executors/types.d.ts +0 -0
  134. package/dist/executors/types.d.ts.map +0 -0
  135. package/dist/executors/types.js +0 -0
  136. package/dist/executors/types.js.map +0 -0
  137. package/dist/executors/workflow-executor.d.ts +0 -0
  138. package/dist/executors/workflow-executor.d.ts.map +0 -0
  139. package/dist/executors/workflow-executor.js +0 -0
  140. package/dist/executors/workflow-executor.js.map +0 -0
  141. package/dist/faber/__tests__/config-manager.test.d.ts +7 -0
  142. package/dist/faber/__tests__/config-manager.test.d.ts.map +1 -0
  143. package/dist/faber/__tests__/config-manager.test.js +637 -0
  144. package/dist/faber/__tests__/config-manager.test.js.map +1 -0
  145. package/dist/faber/__tests__/state-manager.test.d.ts +7 -0
  146. package/dist/faber/__tests__/state-manager.test.d.ts.map +1 -0
  147. package/dist/faber/__tests__/state-manager.test.js +541 -0
  148. package/dist/faber/__tests__/state-manager.test.js.map +1 -0
  149. package/dist/faber/config-manager.d.ts +123 -0
  150. package/dist/faber/config-manager.d.ts.map +1 -0
  151. package/dist/faber/config-manager.js +449 -0
  152. package/dist/faber/config-manager.js.map +1 -0
  153. package/dist/faber/index.d.ts +17 -0
  154. package/dist/faber/index.d.ts.map +1 -0
  155. package/dist/faber/index.js +15 -0
  156. package/dist/faber/index.js.map +1 -0
  157. package/dist/faber/state-manager.d.ts +124 -0
  158. package/dist/faber/state-manager.d.ts.map +1 -0
  159. package/dist/faber/state-manager.js +558 -0
  160. package/dist/faber/state-manager.js.map +1 -0
  161. package/dist/faber/types.d.ts +383 -0
  162. package/dist/faber/types.d.ts.map +1 -0
  163. package/dist/faber/types.js +60 -0
  164. package/dist/faber/types.js.map +1 -0
  165. package/dist/index.d.ts +0 -0
  166. package/dist/index.d.ts.map +0 -0
  167. package/dist/index.js +0 -0
  168. package/dist/index.js.map +0 -0
  169. package/dist/logs/index.d.ts +0 -0
  170. package/dist/logs/index.d.ts.map +0 -0
  171. package/dist/logs/index.js +0 -0
  172. package/dist/logs/index.js.map +0 -0
  173. package/dist/logs/manager.d.ts +0 -0
  174. package/dist/logs/manager.d.ts.map +0 -0
  175. package/dist/logs/manager.js +0 -0
  176. package/dist/logs/manager.js.map +0 -0
  177. package/dist/logs/types.d.ts +0 -0
  178. package/dist/logs/types.d.ts.map +0 -0
  179. package/dist/logs/types.js +0 -0
  180. package/dist/logs/types.js.map +0 -0
  181. package/dist/paths.d.ts +0 -0
  182. package/dist/paths.d.ts.map +0 -0
  183. package/dist/paths.js +0 -0
  184. package/dist/paths.js.map +0 -0
  185. package/dist/repo/git.d.ts +0 -0
  186. package/dist/repo/git.d.ts.map +0 -0
  187. package/dist/repo/git.js +0 -0
  188. package/dist/repo/git.js.map +0 -0
  189. package/dist/repo/index.d.ts +0 -0
  190. package/dist/repo/index.d.ts.map +0 -0
  191. package/dist/repo/index.js +0 -0
  192. package/dist/repo/index.js.map +0 -0
  193. package/dist/repo/manager.d.ts +0 -0
  194. package/dist/repo/manager.d.ts.map +0 -0
  195. package/dist/repo/manager.js +0 -0
  196. package/dist/repo/manager.js.map +0 -0
  197. package/dist/repo/providers/bitbucket.d.ts +0 -0
  198. package/dist/repo/providers/bitbucket.d.ts.map +0 -0
  199. package/dist/repo/providers/bitbucket.js +0 -0
  200. package/dist/repo/providers/bitbucket.js.map +0 -0
  201. package/dist/repo/providers/github.d.ts +0 -0
  202. package/dist/repo/providers/github.d.ts.map +0 -0
  203. package/dist/repo/providers/github.js +0 -0
  204. package/dist/repo/providers/github.js.map +0 -0
  205. package/dist/repo/providers/gitlab.d.ts +0 -0
  206. package/dist/repo/providers/gitlab.d.ts.map +0 -0
  207. package/dist/repo/providers/gitlab.js +0 -0
  208. package/dist/repo/providers/gitlab.js.map +0 -0
  209. package/dist/repo/providers/index.d.ts +0 -0
  210. package/dist/repo/providers/index.d.ts.map +0 -0
  211. package/dist/repo/providers/index.js +0 -0
  212. package/dist/repo/providers/index.js.map +0 -0
  213. package/dist/repo/types.d.ts +0 -0
  214. package/dist/repo/types.d.ts.map +0 -0
  215. package/dist/repo/types.js +0 -0
  216. package/dist/repo/types.js.map +0 -0
  217. package/dist/spec/__tests__/manager.test.d.ts +0 -0
  218. package/dist/spec/__tests__/manager.test.d.ts.map +0 -0
  219. package/dist/spec/__tests__/manager.test.js +2 -2
  220. package/dist/spec/__tests__/manager.test.js.map +1 -1
  221. package/dist/spec/index.d.ts +3 -3
  222. package/dist/spec/index.d.ts.map +1 -1
  223. package/dist/spec/index.js +3 -3
  224. package/dist/spec/index.js.map +1 -1
  225. package/dist/spec/manager.d.ts +1 -1
  226. package/dist/spec/manager.d.ts.map +1 -1
  227. package/dist/spec/manager.js +3 -3
  228. package/dist/spec/manager.js.map +1 -1
  229. package/dist/spec/templates.d.ts +1 -1
  230. package/dist/spec/templates.d.ts.map +1 -1
  231. package/dist/spec/templates.js +0 -0
  232. package/dist/spec/templates.js.map +0 -0
  233. package/dist/spec/types.d.ts +2 -2
  234. package/dist/spec/types.d.ts.map +1 -1
  235. package/dist/spec/types.js +0 -0
  236. package/dist/spec/types.js.map +0 -0
  237. package/dist/state/index.d.ts +0 -0
  238. package/dist/state/index.d.ts.map +0 -0
  239. package/dist/state/index.js +0 -0
  240. package/dist/state/index.js.map +0 -0
  241. package/dist/state/manager.d.ts +0 -0
  242. package/dist/state/manager.d.ts.map +0 -0
  243. package/dist/state/manager.js +0 -0
  244. package/dist/state/manager.js.map +0 -0
  245. package/dist/state/session.d.ts +0 -0
  246. package/dist/state/session.d.ts.map +0 -0
  247. package/dist/state/session.js +0 -0
  248. package/dist/state/session.js.map +0 -0
  249. package/dist/state/types.d.ts +0 -0
  250. package/dist/state/types.d.ts.map +0 -0
  251. package/dist/state/types.js +0 -0
  252. package/dist/state/types.js.map +0 -0
  253. package/dist/storage/codex-adapter.d.ts +0 -0
  254. package/dist/storage/codex-adapter.d.ts.map +0 -0
  255. package/dist/storage/codex-adapter.js +0 -0
  256. package/dist/storage/codex-adapter.js.map +0 -0
  257. package/dist/storage/index.d.ts +0 -0
  258. package/dist/storage/index.d.ts.map +0 -0
  259. package/dist/storage/index.js +0 -0
  260. package/dist/storage/index.js.map +0 -0
  261. package/dist/storage/local.d.ts +0 -0
  262. package/dist/storage/local.d.ts.map +0 -0
  263. package/dist/storage/local.js +0 -0
  264. package/dist/storage/local.js.map +0 -0
  265. package/dist/types.d.ts +0 -0
  266. package/dist/types.d.ts.map +0 -0
  267. package/dist/types.js +0 -0
  268. package/dist/types.js.map +0 -0
  269. package/dist/work/index.d.ts +0 -0
  270. package/dist/work/index.d.ts.map +0 -0
  271. package/dist/work/index.js +0 -0
  272. package/dist/work/index.js.map +0 -0
  273. package/dist/work/manager.d.ts +0 -0
  274. package/dist/work/manager.d.ts.map +0 -0
  275. package/dist/work/manager.js +0 -0
  276. package/dist/work/manager.js.map +0 -0
  277. package/dist/work/providers/github.d.ts +0 -0
  278. package/dist/work/providers/github.d.ts.map +0 -0
  279. package/dist/work/providers/github.js +0 -0
  280. package/dist/work/providers/github.js.map +0 -0
  281. package/dist/work/providers/jira.d.ts +0 -0
  282. package/dist/work/providers/jira.d.ts.map +0 -0
  283. package/dist/work/providers/jira.js +0 -0
  284. package/dist/work/providers/jira.js.map +0 -0
  285. package/dist/work/providers/linear.d.ts +0 -0
  286. package/dist/work/providers/linear.d.ts.map +0 -0
  287. package/dist/work/providers/linear.js +0 -0
  288. package/dist/work/providers/linear.js.map +0 -0
  289. package/dist/work/types.d.ts +0 -0
  290. package/dist/work/types.d.ts.map +0 -0
  291. package/dist/work/types.js +0 -0
  292. package/dist/work/types.js.map +0 -0
  293. package/dist/workflow/__tests__/agent-executor.test.d.ts +0 -0
  294. package/dist/workflow/__tests__/agent-executor.test.d.ts.map +0 -0
  295. package/dist/workflow/__tests__/agent-executor.test.js +2 -2
  296. package/dist/workflow/__tests__/agent-executor.test.js.map +1 -1
  297. package/dist/workflow/__tests__/resolver.test.d.ts +0 -0
  298. package/dist/workflow/__tests__/resolver.test.d.ts.map +0 -0
  299. package/dist/workflow/__tests__/resolver.test.js +96 -0
  300. package/dist/workflow/__tests__/resolver.test.js.map +1 -1
  301. package/dist/workflow/agent-executor.d.ts +1 -1
  302. package/dist/workflow/agent-executor.d.ts.map +1 -1
  303. package/dist/workflow/agent-executor.js +3 -3
  304. package/dist/workflow/agent-executor.js.map +1 -1
  305. package/dist/workflow/faber.d.ts +0 -0
  306. package/dist/workflow/faber.d.ts.map +0 -0
  307. package/dist/workflow/faber.js +0 -0
  308. package/dist/workflow/faber.js.map +0 -0
  309. package/dist/workflow/index.d.ts +0 -0
  310. package/dist/workflow/index.d.ts.map +0 -0
  311. package/dist/workflow/index.js +0 -0
  312. package/dist/workflow/index.js.map +0 -0
  313. package/dist/workflow/resolver.d.ts +6 -0
  314. package/dist/workflow/resolver.d.ts.map +1 -1
  315. package/dist/workflow/resolver.js +16 -1
  316. package/dist/workflow/resolver.js.map +1 -1
  317. package/dist/workflow/types.d.ts +0 -0
  318. package/dist/workflow/types.d.ts.map +0 -0
  319. package/dist/workflow/types.js +0 -0
  320. package/dist/workflow/types.js.map +0 -0
  321. package/dist/workflows/__tests__/registry.test.d.ts +0 -0
  322. package/dist/workflows/__tests__/registry.test.d.ts.map +0 -0
  323. package/dist/workflows/__tests__/registry.test.js +0 -0
  324. package/dist/workflows/__tests__/registry.test.js.map +0 -0
  325. package/dist/workflows/registry.d.ts +0 -0
  326. package/dist/workflows/registry.d.ts.map +0 -0
  327. package/dist/workflows/registry.js +0 -0
  328. package/dist/workflows/registry.js.map +0 -0
  329. package/package.json +2 -2
  330. package/dist/cli/commands/logs.d.ts +0 -6
  331. package/dist/cli/commands/logs.d.ts.map +0 -1
  332. package/dist/cli/commands/logs.js +0 -215
  333. package/dist/cli/commands/logs.js.map +0 -1
  334. package/dist/cli/commands/repo.d.ts +0 -6
  335. package/dist/cli/commands/repo.d.ts.map +0 -1
  336. package/dist/cli/commands/repo.js +0 -260
  337. package/dist/cli/commands/repo.js.map +0 -1
  338. package/dist/cli/commands/spec.d.ts +0 -6
  339. package/dist/cli/commands/spec.d.ts.map +0 -1
  340. package/dist/cli/commands/spec.js +0 -184
  341. package/dist/cli/commands/spec.js.map +0 -1
  342. package/dist/cli/commands/work.d.ts +0 -6
  343. package/dist/cli/commands/work.d.ts.map +0 -1
  344. package/dist/cli/commands/work.js +0 -113
  345. package/dist/cli/commands/work.js.map +0 -1
  346. package/dist/cli/commands/workflow.d.ts +0 -6
  347. package/dist/cli/commands/workflow.d.ts.map +0 -1
  348. package/dist/cli/commands/workflow.js +0 -214
  349. package/dist/cli/commands/workflow.js.map +0 -1
  350. package/dist/cli/index.d.ts +0 -8
  351. package/dist/cli/index.d.ts.map +0 -1
  352. package/dist/cli/index.js +0 -27
  353. package/dist/cli/index.js.map +0 -1
@@ -0,0 +1,741 @@
1
+ /**
2
+ * @fractary/faber - ResourceManager Tests
3
+ *
4
+ * Unit tests for ResourceManager with mocked TerraformManager
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { ResourceManager } from '../resource-manager';
9
+ import { TerraformManager } from '../terraform-manager';
10
+ // Mock TerraformManager
11
+ jest.mock('../terraform-manager');
12
+ const MockedTerraformManager = TerraformManager;
13
+ describe('ResourceManager', () => {
14
+ const testDir = path.join(__dirname, '__test-resource-manager__');
15
+ const tfDir = path.join(testDir, 'terraform');
16
+ let manager;
17
+ let mockTerraformManager;
18
+ beforeEach(() => {
19
+ // Clean up test directory before each test
20
+ if (fs.existsSync(testDir)) {
21
+ fs.rmSync(testDir, { recursive: true, force: true });
22
+ }
23
+ fs.mkdirSync(tfDir, { recursive: true });
24
+ // Reset mocks
25
+ jest.clearAllMocks();
26
+ // Create mock instance
27
+ mockTerraformManager = {
28
+ isInitialized: jest.fn(),
29
+ show: jest.fn(),
30
+ output: jest.fn(),
31
+ };
32
+ // Mock constructor to return our mock instance
33
+ MockedTerraformManager.mockImplementation(() => mockTerraformManager);
34
+ // Create manager
35
+ manager = new ResourceManager({
36
+ environment: 'production',
37
+ terraformDir: tfDir,
38
+ awsProfile: 'prod',
39
+ });
40
+ });
41
+ afterEach(() => {
42
+ // Clean up test directory after each test
43
+ if (fs.existsSync(testDir)) {
44
+ fs.rmSync(testDir, { recursive: true, force: true });
45
+ }
46
+ });
47
+ describe('Constructor', () => {
48
+ it('should construct with required config', () => {
49
+ const mgr = new ResourceManager({
50
+ environment: 'dev',
51
+ });
52
+ expect(mgr).toBeDefined();
53
+ });
54
+ it('should construct with terraform directory', () => {
55
+ const mgr = new ResourceManager({
56
+ environment: 'staging',
57
+ terraformDir: tfDir,
58
+ });
59
+ expect(mgr).toBeDefined();
60
+ });
61
+ it('should construct with AWS profile', () => {
62
+ const mgr = new ResourceManager({
63
+ environment: 'prod',
64
+ awsProfile: 'production',
65
+ });
66
+ expect(mgr).toBeDefined();
67
+ });
68
+ });
69
+ describe('getEnvironment', () => {
70
+ it('should return configured environment', () => {
71
+ expect(manager.getEnvironment()).toBe('production');
72
+ });
73
+ });
74
+ describe('list', () => {
75
+ const mockTerraformState = {
76
+ format_version: '1.0',
77
+ terraform_version: '1.5.0',
78
+ resources: [
79
+ {
80
+ type: 'aws_instance',
81
+ name: 'web',
82
+ mode: 'managed',
83
+ provider: 'registry.terraform.io/hashicorp/aws',
84
+ instances: [{
85
+ schema_version: 1,
86
+ attributes: {
87
+ id: 'i-12345',
88
+ arn: 'arn:aws:ec2:us-west-2:123456789012:instance/i-12345',
89
+ instance_type: 't3.micro',
90
+ instance_state: 'running',
91
+ availability_zone: 'us-west-2a',
92
+ tags: { Name: 'web-server', Environment: 'production' },
93
+ },
94
+ }],
95
+ },
96
+ {
97
+ type: 'aws_s3_bucket',
98
+ name: 'assets',
99
+ mode: 'managed',
100
+ provider: 'registry.terraform.io/hashicorp/aws',
101
+ instances: [{
102
+ schema_version: 0,
103
+ attributes: {
104
+ id: 'my-assets-bucket',
105
+ arn: 'arn:aws:s3:::my-assets-bucket',
106
+ region: 'us-west-2',
107
+ tags: { Name: 'assets', Environment: 'production' },
108
+ },
109
+ }],
110
+ },
111
+ {
112
+ type: 'aws_lambda_function',
113
+ name: 'api',
114
+ mode: 'managed',
115
+ provider: 'registry.terraform.io/hashicorp/aws',
116
+ instances: [{
117
+ schema_version: 0,
118
+ attributes: {
119
+ id: 'my-api-function',
120
+ arn: 'arn:aws:lambda:us-west-2:123456789012:function:my-api',
121
+ function_name: 'my-api',
122
+ region: 'us-west-2',
123
+ },
124
+ }],
125
+ },
126
+ ],
127
+ outputs: {},
128
+ };
129
+ beforeEach(() => {
130
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
131
+ mockTerraformManager.show.mockResolvedValue(mockTerraformState);
132
+ });
133
+ it('should list all resources from terraform state', async () => {
134
+ const resources = await manager.list();
135
+ expect(resources).toHaveLength(3);
136
+ expect(resources.map(r => r.type)).toContain('aws_instance');
137
+ expect(resources.map(r => r.type)).toContain('aws_s3_bucket');
138
+ expect(resources.map(r => r.type)).toContain('aws_lambda_function');
139
+ });
140
+ it('should map AWS provider correctly', async () => {
141
+ const resources = await manager.list();
142
+ resources.forEach(r => {
143
+ expect(r.provider).toBe('aws');
144
+ });
145
+ });
146
+ it('should extract resource name from tags', async () => {
147
+ const resources = await manager.list();
148
+ const webInstance = resources.find(r => r.type === 'aws_instance');
149
+ expect(webInstance?.name).toBe('web-server');
150
+ });
151
+ it('should use terraform resource name as fallback', async () => {
152
+ const resources = await manager.list();
153
+ // Lambda function doesn't have attrs.name, so falls back to resource.name
154
+ const lambda = resources.find(r => r.type === 'aws_lambda_function');
155
+ expect(lambda?.name).toBe('api'); // Uses terraform resource name as fallback
156
+ });
157
+ it('should extract region from availability zone', async () => {
158
+ const resources = await manager.list();
159
+ const webInstance = resources.find(r => r.type === 'aws_instance');
160
+ expect(webInstance?.region).toBe('us-west-2');
161
+ });
162
+ it('should include terraform_address in metadata', async () => {
163
+ const resources = await manager.list();
164
+ const webInstance = resources.find(r => r.type === 'aws_instance');
165
+ expect(webInstance?.metadata?.terraform_address).toBe('aws_instance.web');
166
+ });
167
+ it('should filter by type', async () => {
168
+ const resources = await manager.list({ type: 'aws_instance' });
169
+ expect(resources).toHaveLength(1);
170
+ expect(resources[0].type).toBe('aws_instance');
171
+ });
172
+ it('should filter by status', async () => {
173
+ const resources = await manager.list({ status: 'running' });
174
+ // All resources in our mock are running
175
+ expect(resources.length).toBeGreaterThan(0);
176
+ resources.forEach(r => {
177
+ expect(r.status).toBe('running');
178
+ });
179
+ });
180
+ it('should filter by region', async () => {
181
+ const resources = await manager.list({ region: 'us-west-2' });
182
+ expect(resources.length).toBeGreaterThan(0);
183
+ resources.forEach(r => {
184
+ expect(r.region).toBe('us-west-2');
185
+ });
186
+ });
187
+ it('should filter by tag', async () => {
188
+ const resources = await manager.list({
189
+ tag: { key: 'Environment', value: 'production' },
190
+ });
191
+ expect(resources).toHaveLength(2); // web instance and s3 bucket have Environment tag
192
+ });
193
+ it('should return empty array when terraform not initialized', async () => {
194
+ mockTerraformManager.isInitialized.mockResolvedValue(false);
195
+ const resources = await manager.list();
196
+ expect(resources).toEqual([]);
197
+ });
198
+ it('should return empty array when no terraform directory', async () => {
199
+ const mgr = new ResourceManager({
200
+ environment: 'dev',
201
+ // No terraformDir
202
+ });
203
+ const resources = await mgr.list();
204
+ expect(resources).toEqual([]);
205
+ });
206
+ it('should handle terraform show error gracefully', async () => {
207
+ mockTerraformManager.show.mockRejectedValue(new Error('State not found'));
208
+ const resources = await manager.list();
209
+ expect(resources).toEqual([]);
210
+ });
211
+ });
212
+ describe('Resource Status Mapping', () => {
213
+ beforeEach(() => {
214
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
215
+ });
216
+ it('should map EC2 running state', async () => {
217
+ mockTerraformManager.show.mockResolvedValue({
218
+ format_version: '1.0',
219
+ terraform_version: '1.5.0',
220
+ resources: [{
221
+ type: 'aws_instance',
222
+ name: 'web',
223
+ mode: 'managed',
224
+ provider: 'registry.terraform.io/hashicorp/aws',
225
+ instances: [{
226
+ attributes: {
227
+ id: 'i-12345',
228
+ instance_state: 'running',
229
+ },
230
+ }],
231
+ }],
232
+ outputs: {},
233
+ });
234
+ const resources = await manager.list();
235
+ expect(resources[0].status).toBe('running');
236
+ });
237
+ it('should map EC2 stopped state', async () => {
238
+ mockTerraformManager.show.mockResolvedValue({
239
+ format_version: '1.0',
240
+ terraform_version: '1.5.0',
241
+ resources: [{
242
+ type: 'aws_instance',
243
+ name: 'web',
244
+ mode: 'managed',
245
+ provider: 'registry.terraform.io/hashicorp/aws',
246
+ instances: [{
247
+ attributes: {
248
+ id: 'i-12345',
249
+ instance_state: 'stopped',
250
+ },
251
+ }],
252
+ }],
253
+ outputs: {},
254
+ });
255
+ const resources = await manager.list();
256
+ expect(resources[0].status).toBe('stopped');
257
+ });
258
+ it('should map EC2 pending state', async () => {
259
+ mockTerraformManager.show.mockResolvedValue({
260
+ format_version: '1.0',
261
+ terraform_version: '1.5.0',
262
+ resources: [{
263
+ type: 'aws_instance',
264
+ name: 'web',
265
+ mode: 'managed',
266
+ provider: 'registry.terraform.io/hashicorp/aws',
267
+ instances: [{
268
+ attributes: {
269
+ id: 'i-12345',
270
+ instance_state: 'pending',
271
+ },
272
+ }],
273
+ }],
274
+ outputs: {},
275
+ });
276
+ const resources = await manager.list();
277
+ expect(resources[0].status).toBe('pending');
278
+ });
279
+ it('should map RDS available state to running', async () => {
280
+ mockTerraformManager.show.mockResolvedValue({
281
+ format_version: '1.0',
282
+ terraform_version: '1.5.0',
283
+ resources: [{
284
+ type: 'aws_db_instance',
285
+ name: 'db',
286
+ mode: 'managed',
287
+ provider: 'registry.terraform.io/hashicorp/aws',
288
+ instances: [{
289
+ attributes: {
290
+ id: 'mydb',
291
+ status: 'available',
292
+ },
293
+ }],
294
+ }],
295
+ outputs: {},
296
+ });
297
+ const resources = await manager.list();
298
+ expect(resources[0].status).toBe('running');
299
+ });
300
+ it('should map Lambda function to running', async () => {
301
+ mockTerraformManager.show.mockResolvedValue({
302
+ format_version: '1.0',
303
+ terraform_version: '1.5.0',
304
+ resources: [{
305
+ type: 'aws_lambda_function',
306
+ name: 'api',
307
+ mode: 'managed',
308
+ provider: 'registry.terraform.io/hashicorp/aws',
309
+ instances: [{
310
+ attributes: {
311
+ id: 'my-function',
312
+ },
313
+ }],
314
+ }],
315
+ outputs: {},
316
+ });
317
+ const resources = await manager.list();
318
+ expect(resources[0].status).toBe('running');
319
+ });
320
+ it('should map ECS service with desired_count > 0 to running', async () => {
321
+ mockTerraformManager.show.mockResolvedValue({
322
+ format_version: '1.0',
323
+ terraform_version: '1.5.0',
324
+ resources: [{
325
+ type: 'aws_ecs_service',
326
+ name: 'api',
327
+ mode: 'managed',
328
+ provider: 'registry.terraform.io/hashicorp/aws',
329
+ instances: [{
330
+ attributes: {
331
+ id: 'my-service',
332
+ desired_count: 2,
333
+ },
334
+ }],
335
+ }],
336
+ outputs: {},
337
+ });
338
+ const resources = await manager.list();
339
+ expect(resources[0].status).toBe('running');
340
+ });
341
+ it('should map ECS service with desired_count = 0 to stopped', async () => {
342
+ mockTerraformManager.show.mockResolvedValue({
343
+ format_version: '1.0',
344
+ terraform_version: '1.5.0',
345
+ resources: [{
346
+ type: 'aws_ecs_service',
347
+ name: 'api',
348
+ mode: 'managed',
349
+ provider: 'registry.terraform.io/hashicorp/aws',
350
+ instances: [{
351
+ attributes: {
352
+ id: 'my-service',
353
+ desired_count: 0,
354
+ },
355
+ }],
356
+ }],
357
+ outputs: {},
358
+ });
359
+ const resources = await manager.list();
360
+ expect(resources[0].status).toBe('stopped');
361
+ });
362
+ });
363
+ describe('status', () => {
364
+ beforeEach(() => {
365
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
366
+ mockTerraformManager.show.mockResolvedValue({
367
+ format_version: '1.0',
368
+ terraform_version: '1.5.0',
369
+ resources: [
370
+ {
371
+ type: 'aws_instance',
372
+ name: 'web1',
373
+ mode: 'managed',
374
+ provider: 'registry.terraform.io/hashicorp/aws',
375
+ instances: [{
376
+ attributes: { id: 'i-1', instance_state: 'running', region: 'us-west-2' },
377
+ }],
378
+ },
379
+ {
380
+ type: 'aws_instance',
381
+ name: 'web2',
382
+ mode: 'managed',
383
+ provider: 'registry.terraform.io/hashicorp/aws',
384
+ instances: [{
385
+ attributes: { id: 'i-2', instance_state: 'stopped', region: 'us-west-2' },
386
+ }],
387
+ },
388
+ {
389
+ type: 'aws_s3_bucket',
390
+ name: 'assets',
391
+ mode: 'managed',
392
+ provider: 'registry.terraform.io/hashicorp/aws',
393
+ instances: [{
394
+ attributes: { id: 'bucket', region: 'us-east-1' },
395
+ }],
396
+ },
397
+ ],
398
+ outputs: {},
399
+ });
400
+ });
401
+ it('should return total resource count', async () => {
402
+ const summary = await manager.status();
403
+ expect(summary.total).toBe(3);
404
+ });
405
+ it('should count resources by type', async () => {
406
+ const summary = await manager.status();
407
+ expect(summary.by_type['aws_instance']).toBe(2);
408
+ expect(summary.by_type['aws_s3_bucket']).toBe(1);
409
+ });
410
+ it('should count resources by status', async () => {
411
+ const summary = await manager.status();
412
+ expect(summary.by_status.running).toBe(2); // 1 running EC2 + 1 S3 (always running)
413
+ expect(summary.by_status.stopped).toBe(1);
414
+ });
415
+ it('should count resources by region', async () => {
416
+ const summary = await manager.status();
417
+ expect(summary.by_region['us-west-2']).toBe(2);
418
+ expect(summary.by_region['us-east-1']).toBe(1);
419
+ });
420
+ });
421
+ describe('get', () => {
422
+ beforeEach(() => {
423
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
424
+ mockTerraformManager.show.mockResolvedValue({
425
+ format_version: '1.0',
426
+ terraform_version: '1.5.0',
427
+ resources: [{
428
+ type: 'aws_instance',
429
+ name: 'web',
430
+ mode: 'managed',
431
+ provider: 'registry.terraform.io/hashicorp/aws',
432
+ instances: [{
433
+ attributes: { id: 'i-12345', instance_state: 'running' },
434
+ }],
435
+ }],
436
+ outputs: {},
437
+ });
438
+ });
439
+ it('should return resource by ID', async () => {
440
+ const resource = await manager.get('i-12345');
441
+ expect(resource).not.toBeNull();
442
+ expect(resource?.id).toBe('i-12345');
443
+ });
444
+ it('should return null for unknown ID', async () => {
445
+ const resource = await manager.get('i-unknown');
446
+ expect(resource).toBeNull();
447
+ });
448
+ });
449
+ describe('getByType', () => {
450
+ beforeEach(() => {
451
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
452
+ mockTerraformManager.show.mockResolvedValue({
453
+ format_version: '1.0',
454
+ terraform_version: '1.5.0',
455
+ resources: [
456
+ {
457
+ type: 'aws_instance',
458
+ name: 'web',
459
+ mode: 'managed',
460
+ provider: 'registry.terraform.io/hashicorp/aws',
461
+ instances: [{ attributes: { id: 'i-1' } }],
462
+ },
463
+ {
464
+ type: 'aws_s3_bucket',
465
+ name: 'assets',
466
+ mode: 'managed',
467
+ provider: 'registry.terraform.io/hashicorp/aws',
468
+ instances: [{ attributes: { id: 'bucket' } }],
469
+ },
470
+ ],
471
+ outputs: {},
472
+ });
473
+ });
474
+ it('should return resources of specified type', async () => {
475
+ const resources = await manager.getByType('aws_instance');
476
+ expect(resources).toHaveLength(1);
477
+ expect(resources[0].type).toBe('aws_instance');
478
+ });
479
+ });
480
+ describe('getByTag', () => {
481
+ beforeEach(() => {
482
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
483
+ mockTerraformManager.show.mockResolvedValue({
484
+ format_version: '1.0',
485
+ terraform_version: '1.5.0',
486
+ resources: [
487
+ {
488
+ type: 'aws_instance',
489
+ name: 'web',
490
+ mode: 'managed',
491
+ provider: 'registry.terraform.io/hashicorp/aws',
492
+ instances: [{
493
+ attributes: {
494
+ id: 'i-1',
495
+ tags: { Environment: 'production', Team: 'engineering' },
496
+ },
497
+ }],
498
+ },
499
+ {
500
+ type: 'aws_instance',
501
+ name: 'dev',
502
+ mode: 'managed',
503
+ provider: 'registry.terraform.io/hashicorp/aws',
504
+ instances: [{
505
+ attributes: {
506
+ id: 'i-2',
507
+ tags: { Environment: 'development', Team: 'engineering' },
508
+ },
509
+ }],
510
+ },
511
+ ],
512
+ outputs: {},
513
+ });
514
+ });
515
+ it('should return resources with matching tag', async () => {
516
+ const resources = await manager.getByTag('Environment', 'production');
517
+ expect(resources).toHaveLength(1);
518
+ expect(resources[0].id).toBe('i-1');
519
+ });
520
+ });
521
+ describe('hasResources', () => {
522
+ beforeEach(() => {
523
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
524
+ });
525
+ it('should return true when resources exist', async () => {
526
+ mockTerraformManager.show.mockResolvedValue({
527
+ format_version: '1.0',
528
+ terraform_version: '1.5.0',
529
+ resources: [{
530
+ type: 'aws_instance',
531
+ name: 'web',
532
+ mode: 'managed',
533
+ provider: 'registry.terraform.io/hashicorp/aws',
534
+ instances: [{ attributes: { id: 'i-1' } }],
535
+ }],
536
+ outputs: {},
537
+ });
538
+ expect(await manager.hasResources()).toBe(true);
539
+ });
540
+ it('should return false when no resources', async () => {
541
+ mockTerraformManager.show.mockResolvedValue({
542
+ format_version: '1.0',
543
+ terraform_version: '1.5.0',
544
+ resources: [],
545
+ outputs: {},
546
+ });
547
+ expect(await manager.hasResources()).toBe(false);
548
+ });
549
+ });
550
+ describe('count', () => {
551
+ beforeEach(() => {
552
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
553
+ mockTerraformManager.show.mockResolvedValue({
554
+ format_version: '1.0',
555
+ terraform_version: '1.5.0',
556
+ resources: [
557
+ {
558
+ type: 'aws_instance',
559
+ name: 'web1',
560
+ mode: 'managed',
561
+ provider: 'registry.terraform.io/hashicorp/aws',
562
+ instances: [{ attributes: { id: 'i-1' } }],
563
+ },
564
+ {
565
+ type: 'aws_instance',
566
+ name: 'web2',
567
+ mode: 'managed',
568
+ provider: 'registry.terraform.io/hashicorp/aws',
569
+ instances: [{ attributes: { id: 'i-2' } }],
570
+ },
571
+ {
572
+ type: 'aws_s3_bucket',
573
+ name: 'assets',
574
+ mode: 'managed',
575
+ provider: 'registry.terraform.io/hashicorp/aws',
576
+ instances: [{ attributes: { id: 'bucket' } }],
577
+ },
578
+ ],
579
+ outputs: {},
580
+ });
581
+ });
582
+ it('should return total count', async () => {
583
+ const count = await manager.count();
584
+ expect(count).toBe(3);
585
+ });
586
+ it('should return filtered count', async () => {
587
+ const count = await manager.count({ type: 'aws_instance' });
588
+ expect(count).toBe(2);
589
+ });
590
+ });
591
+ describe('getOutputs', () => {
592
+ beforeEach(() => {
593
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
594
+ });
595
+ it('should return terraform outputs', async () => {
596
+ mockTerraformManager.output.mockResolvedValue({
597
+ instance_id: { value: 'i-12345', type: 'string', sensitive: false },
598
+ public_ip: { value: '1.2.3.4', type: 'string', sensitive: false },
599
+ });
600
+ const outputs = await manager.getOutputs();
601
+ expect(outputs['instance_id']).toBe('i-12345');
602
+ expect(outputs['public_ip']).toBe('1.2.3.4');
603
+ });
604
+ it('should return empty object when not initialized', async () => {
605
+ mockTerraformManager.isInitialized.mockResolvedValue(false);
606
+ const outputs = await manager.getOutputs();
607
+ expect(outputs).toEqual({});
608
+ });
609
+ it('should return empty object on error', async () => {
610
+ mockTerraformManager.output.mockRejectedValue(new Error('No outputs'));
611
+ const outputs = await manager.getOutputs();
612
+ expect(outputs).toEqual({});
613
+ });
614
+ });
615
+ describe('healthCheck', () => {
616
+ beforeEach(() => {
617
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
618
+ });
619
+ it('should return healthy when all resources are healthy', async () => {
620
+ mockTerraformManager.show.mockResolvedValue({
621
+ format_version: '1.0',
622
+ terraform_version: '1.5.0',
623
+ resources: [
624
+ {
625
+ type: 'aws_instance',
626
+ name: 'web',
627
+ mode: 'managed',
628
+ provider: 'registry.terraform.io/hashicorp/aws',
629
+ instances: [{
630
+ attributes: { id: 'i-1', instance_state: 'running' },
631
+ }],
632
+ },
633
+ {
634
+ type: 'aws_s3_bucket',
635
+ name: 'assets',
636
+ mode: 'managed',
637
+ provider: 'registry.terraform.io/hashicorp/aws',
638
+ instances: [{ attributes: { id: 'bucket' } }],
639
+ },
640
+ ],
641
+ outputs: {},
642
+ });
643
+ const health = await manager.healthCheck();
644
+ expect(health.healthy).toBe(true);
645
+ expect(health.issues).toHaveLength(0);
646
+ expect(health.checked).toBe(2);
647
+ });
648
+ it('should report stopped EC2 instances', async () => {
649
+ mockTerraformManager.show.mockResolvedValue({
650
+ format_version: '1.0',
651
+ terraform_version: '1.5.0',
652
+ resources: [{
653
+ type: 'aws_instance',
654
+ name: 'web',
655
+ mode: 'managed',
656
+ provider: 'registry.terraform.io/hashicorp/aws',
657
+ instances: [{
658
+ attributes: { id: 'i-1', instance_state: 'stopped' },
659
+ }],
660
+ }],
661
+ outputs: {},
662
+ });
663
+ const health = await manager.healthCheck();
664
+ expect(health.healthy).toBe(false);
665
+ expect(health.issues).toContain('1 EC2 instance(s) are stopped');
666
+ });
667
+ it('should report terminated resources', async () => {
668
+ mockTerraformManager.show.mockResolvedValue({
669
+ format_version: '1.0',
670
+ terraform_version: '1.5.0',
671
+ resources: [{
672
+ type: 'aws_instance',
673
+ name: 'web',
674
+ mode: 'managed',
675
+ provider: 'registry.terraform.io/hashicorp/aws',
676
+ instances: [{
677
+ attributes: { id: 'i-1', instance_state: 'terminated' },
678
+ }],
679
+ }],
680
+ outputs: {},
681
+ });
682
+ const health = await manager.healthCheck();
683
+ expect(health.healthy).toBe(false);
684
+ expect(health.issues.some(i => i.includes('terminated'))).toBe(true);
685
+ });
686
+ });
687
+ describe('Provider Detection', () => {
688
+ beforeEach(() => {
689
+ mockTerraformManager.isInitialized.mockResolvedValue(true);
690
+ });
691
+ it('should detect GCP provider', async () => {
692
+ mockTerraformManager.show.mockResolvedValue({
693
+ format_version: '1.0',
694
+ terraform_version: '1.5.0',
695
+ resources: [{
696
+ type: 'google_compute_instance',
697
+ name: 'web',
698
+ mode: 'managed',
699
+ provider: 'registry.terraform.io/hashicorp/google',
700
+ instances: [{ attributes: { id: 'vm-1' } }],
701
+ }],
702
+ outputs: {},
703
+ });
704
+ const resources = await manager.list();
705
+ expect(resources[0].provider).toBe('gcp');
706
+ });
707
+ it('should detect Azure provider', async () => {
708
+ mockTerraformManager.show.mockResolvedValue({
709
+ format_version: '1.0',
710
+ terraform_version: '1.5.0',
711
+ resources: [{
712
+ type: 'azurerm_virtual_machine',
713
+ name: 'web',
714
+ mode: 'managed',
715
+ provider: 'registry.terraform.io/hashicorp/azurerm',
716
+ instances: [{ attributes: { id: 'vm-1' } }],
717
+ }],
718
+ outputs: {},
719
+ });
720
+ const resources = await manager.list();
721
+ expect(resources[0].provider).toBe('azure');
722
+ });
723
+ it('should fallback to other for unknown provider', async () => {
724
+ mockTerraformManager.show.mockResolvedValue({
725
+ format_version: '1.0',
726
+ terraform_version: '1.5.0',
727
+ resources: [{
728
+ type: 'kubernetes_deployment',
729
+ name: 'web',
730
+ mode: 'managed',
731
+ provider: 'registry.terraform.io/hashicorp/kubernetes',
732
+ instances: [{ attributes: { id: 'deploy-1' } }],
733
+ }],
734
+ outputs: {},
735
+ });
736
+ const resources = await manager.list();
737
+ expect(resources[0].provider).toBe('other');
738
+ });
739
+ });
740
+ });
741
+ //# sourceMappingURL=resource-manager.test.js.map