@quadnix/octo 0.0.30 → 0.2.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 (383) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +117 -8
  3. package/dist/app.type.d.ts +277 -19
  4. package/dist/app.type.js +80 -9
  5. package/dist/app.type.js.map +1 -1
  6. package/dist/decorators/action.decorator.d.ts +10 -6
  7. package/dist/decorators/action.decorator.js +19 -6
  8. package/dist/decorators/action.decorator.js.map +1 -1
  9. package/dist/decorators/anchor.decorator.d.ts +12 -5
  10. package/dist/decorators/anchor.decorator.js +12 -5
  11. package/dist/decorators/anchor.decorator.js.map +1 -1
  12. package/dist/decorators/enable-hook.decorator.d.ts +1 -1
  13. package/dist/decorators/enable-hook.decorator.js +1 -1
  14. package/dist/decorators/factory.decorator.d.ts +18 -34
  15. package/dist/decorators/factory.decorator.js +18 -34
  16. package/dist/decorators/factory.decorator.js.map +1 -1
  17. package/dist/decorators/model.decorator.d.ts +4 -6
  18. package/dist/decorators/model.decorator.js +2 -7
  19. package/dist/decorators/model.decorator.js.map +1 -1
  20. package/dist/decorators/module.decorator.d.ts +16 -10
  21. package/dist/decorators/module.decorator.js +16 -10
  22. package/dist/decorators/module.decorator.js.map +1 -1
  23. package/dist/decorators/on-event.decorator.d.ts +7 -2
  24. package/dist/decorators/on-event.decorator.js +5 -0
  25. package/dist/decorators/on-event.decorator.js.map +1 -1
  26. package/dist/decorators/resource.decorator.d.ts +50 -1
  27. package/dist/decorators/resource.decorator.js +38 -1
  28. package/dist/decorators/resource.decorator.js.map +1 -1
  29. package/dist/decorators/validate.decorator.d.ts +15 -1
  30. package/dist/decorators/validate.decorator.js +15 -1
  31. package/dist/decorators/validate.decorator.js.map +1 -1
  32. package/dist/errors/container.error.d.ts +18 -0
  33. package/dist/errors/container.error.js +18 -0
  34. package/dist/errors/container.error.js.map +1 -1
  35. package/dist/errors/index.d.ts +1 -0
  36. package/dist/errors/index.js +1 -0
  37. package/dist/errors/index.js.map +1 -1
  38. package/dist/errors/module.error.d.ts +6 -0
  39. package/dist/errors/module.error.js +6 -0
  40. package/dist/errors/module.error.js.map +1 -1
  41. package/dist/errors/node.error.d.ts +56 -0
  42. package/dist/errors/node.error.js +56 -0
  43. package/dist/errors/node.error.js.map +1 -1
  44. package/dist/errors/schema.error.d.ts +14 -1
  45. package/dist/errors/schema.error.js +11 -1
  46. package/dist/errors/schema.error.js.map +1 -1
  47. package/dist/errors/terraform.error.d.ts +20 -0
  48. package/dist/errors/terraform.error.js +24 -0
  49. package/dist/errors/terraform.error.js.map +1 -0
  50. package/dist/errors/transaction.error.d.ts +93 -2
  51. package/dist/errors/transaction.error.js +83 -0
  52. package/dist/errors/transaction.error.js.map +1 -1
  53. package/dist/events/action.event.d.ts +8 -4
  54. package/dist/events/action.event.js +2 -4
  55. package/dist/events/action.event.js.map +1 -1
  56. package/dist/events/command.event.d.ts +43 -0
  57. package/dist/events/command.event.js +33 -0
  58. package/dist/events/command.event.js.map +1 -0
  59. package/dist/events/event.model.d.ts +26 -8
  60. package/dist/events/event.model.js +15 -7
  61. package/dist/events/event.model.js.map +1 -1
  62. package/dist/events/hook/commit.hook.event.d.ts +1 -7
  63. package/dist/events/hook/commit.hook.event.js +0 -6
  64. package/dist/events/hook/commit.hook.event.js.map +1 -1
  65. package/dist/events/hook/hook.event.d.ts +1 -3
  66. package/dist/events/hook/hook.event.js +0 -2
  67. package/dist/events/hook/hook.event.js.map +1 -1
  68. package/dist/events/hook/model.hook.event.d.ts +1 -7
  69. package/dist/events/hook/model.hook.event.js +0 -6
  70. package/dist/events/hook/model.hook.event.js.map +1 -1
  71. package/dist/events/hook/resource.hook.event.d.ts +1 -7
  72. package/dist/events/hook/resource.hook.event.js +0 -6
  73. package/dist/events/hook/resource.hook.event.js.map +1 -1
  74. package/dist/events/index.d.ts +5 -0
  75. package/dist/events/index.js +5 -0
  76. package/dist/events/index.js.map +1 -1
  77. package/dist/events/mode-result.event.d.ts +57 -0
  78. package/dist/events/mode-result.event.js +24 -0
  79. package/dist/events/mode-result.event.js.map +1 -0
  80. package/dist/events/mode.event.d.ts +61 -0
  81. package/dist/events/mode.event.js +32 -0
  82. package/dist/events/mode.event.js.map +1 -0
  83. package/dist/events/module.event.d.ts +7 -5
  84. package/dist/events/module.event.js +3 -4
  85. package/dist/events/module.event.js.map +1 -1
  86. package/dist/events/registration.event.d.ts +19 -15
  87. package/dist/events/registration.event.js +18 -14
  88. package/dist/events/registration.event.js.map +1 -1
  89. package/dist/events/serialization.event.d.ts +16 -13
  90. package/dist/events/serialization.event.js +15 -12
  91. package/dist/events/serialization.event.js.map +1 -1
  92. package/dist/events/state.event.d.ts +102 -0
  93. package/dist/events/state.event.js +69 -0
  94. package/dist/events/state.event.js.map +1 -0
  95. package/dist/events/terraform.event.d.ts +78 -0
  96. package/dist/events/terraform.event.js +55 -0
  97. package/dist/events/terraform.event.js.map +1 -0
  98. package/dist/events/transaction.event.d.ts +3 -40
  99. package/dist/events/transaction.event.js +1 -29
  100. package/dist/events/transaction.event.js.map +1 -1
  101. package/dist/functions/container/container.d.ts +54 -13
  102. package/dist/functions/container/container.js +64 -19
  103. package/dist/functions/container/container.js.map +1 -1
  104. package/dist/functions/container/test-container.d.ts +43 -29
  105. package/dist/functions/container/test-container.js +71 -43
  106. package/dist/functions/container/test-container.js.map +1 -1
  107. package/dist/functions/dependency/dependency.d.ts +84 -23
  108. package/dist/functions/dependency/dependency.js +84 -14
  109. package/dist/functions/dependency/dependency.js.map +1 -1
  110. package/dist/functions/diff/aggregate-resource-actions.d.ts +19 -0
  111. package/dist/functions/diff/aggregate-resource-actions.js +41 -0
  112. package/dist/functions/diff/aggregate-resource-actions.js.map +1 -0
  113. package/dist/functions/diff/diff-metadata.d.ts +21 -3
  114. package/dist/functions/diff/diff-metadata.js +18 -0
  115. package/dist/functions/diff/diff-metadata.js.map +1 -1
  116. package/dist/functions/diff/diff.d.ts +68 -7
  117. package/dist/functions/diff/diff.js +44 -3
  118. package/dist/functions/diff/diff.js.map +1 -1
  119. package/dist/functions/hook/commit.hook.d.ts +16 -1
  120. package/dist/functions/hook/commit.hook.js +21 -6
  121. package/dist/functions/hook/commit.hook.js.map +1 -1
  122. package/dist/functions/hook/model-action.hook.d.ts +16 -1
  123. package/dist/functions/hook/model-action.hook.js +21 -6
  124. package/dist/functions/hook/model-action.hook.js.map +1 -1
  125. package/dist/functions/hook/resource-action.hook.d.ts +16 -1
  126. package/dist/functions/hook/resource-action.hook.js +21 -6
  127. package/dist/functions/hook/resource-action.hook.js.map +1 -1
  128. package/dist/functions/node/node-action.abstract.d.ts +23 -2
  129. package/dist/functions/node/node-action.abstract.js +22 -8
  130. package/dist/functions/node/node-action.abstract.js.map +1 -1
  131. package/dist/functions/node/node.abstract.d.ts +56 -5
  132. package/dist/functions/node/node.abstract.js +106 -22
  133. package/dist/functions/node/node.abstract.js.map +1 -1
  134. package/dist/functions/node/node.interface.d.ts +3 -1
  135. package/dist/functions/schema/schema.d.ts +7 -0
  136. package/dist/functions/schema/schema.js +10 -1
  137. package/dist/functions/schema/schema.js.map +1 -1
  138. package/dist/index.d.ts +12 -6
  139. package/dist/index.js +9 -4
  140. package/dist/index.js.map +1 -1
  141. package/dist/index.type.d.ts +5 -0
  142. package/dist/index.type.js +2 -0
  143. package/dist/index.type.js.map +1 -0
  144. package/dist/main.d.ts +245 -14
  145. package/dist/main.js +377 -72
  146. package/dist/main.js.map +1 -1
  147. package/dist/models/account/account.model.d.ts +43 -7
  148. package/dist/models/account/account.model.js +56 -8
  149. package/dist/models/account/account.model.js.map +1 -1
  150. package/dist/models/account/account.schema.d.ts +13 -1
  151. package/dist/models/account/account.schema.js +12 -0
  152. package/dist/models/account/account.schema.js.map +1 -1
  153. package/dist/models/app/app.model.d.ts +13 -8
  154. package/dist/models/app/app.model.js +17 -32
  155. package/dist/models/app/app.model.js.map +1 -1
  156. package/dist/models/app/app.schema.d.ts +6 -0
  157. package/dist/models/app/app.schema.js +6 -0
  158. package/dist/models/app/app.schema.js.map +1 -1
  159. package/dist/models/deployment/deployment.model.d.ts +13 -1
  160. package/dist/models/deployment/deployment.model.js +16 -4
  161. package/dist/models/deployment/deployment.model.js.map +1 -1
  162. package/dist/models/deployment/deployment.schema.d.ts +6 -0
  163. package/dist/models/deployment/deployment.schema.js +6 -0
  164. package/dist/models/deployment/deployment.schema.js.map +1 -1
  165. package/dist/models/environment/environment.model.d.ts +15 -3
  166. package/dist/models/environment/environment.model.js +22 -10
  167. package/dist/models/environment/environment.model.js.map +1 -1
  168. package/dist/models/environment/environment.schema.d.ts +2 -0
  169. package/dist/models/environment/environment.schema.js +2 -0
  170. package/dist/models/environment/environment.schema.js.map +1 -1
  171. package/dist/models/execution/execution.model.d.ts +21 -3
  172. package/dist/models/execution/execution.model.js +47 -29
  173. package/dist/models/execution/execution.model.js.map +1 -1
  174. package/dist/models/execution/execution.schema.d.ts +11 -0
  175. package/dist/models/execution/execution.schema.js +11 -0
  176. package/dist/models/execution/execution.schema.js.map +1 -1
  177. package/dist/models/filesystem/filesystem.model.d.ts +27 -1
  178. package/dist/models/filesystem/filesystem.model.js +30 -4
  179. package/dist/models/filesystem/filesystem.model.js.map +1 -1
  180. package/dist/models/filesystem/filesystem.schema.d.ts +5 -0
  181. package/dist/models/filesystem/filesystem.schema.js +5 -0
  182. package/dist/models/filesystem/filesystem.schema.js.map +1 -1
  183. package/dist/models/image/image.model.d.ts +19 -5
  184. package/dist/models/image/image.model.js +25 -11
  185. package/dist/models/image/image.model.js.map +1 -1
  186. package/dist/models/image/image.schema.d.ts +8 -0
  187. package/dist/models/image/image.schema.js +8 -0
  188. package/dist/models/image/image.schema.js.map +1 -1
  189. package/dist/models/model-action.interface.d.ts +17 -4
  190. package/dist/models/model.abstract.d.ts +96 -1
  191. package/dist/models/model.abstract.js +107 -8
  192. package/dist/models/model.abstract.js.map +1 -1
  193. package/dist/models/model.interface.d.ts +3 -0
  194. package/dist/models/pipeline/pipeline.model.d.ts +14 -2
  195. package/dist/models/pipeline/pipeline.model.js +19 -7
  196. package/dist/models/pipeline/pipeline.model.js.map +1 -1
  197. package/dist/models/pipeline/pipeline.schema.d.ts +8 -0
  198. package/dist/models/pipeline/pipeline.schema.js +8 -0
  199. package/dist/models/pipeline/pipeline.schema.js.map +1 -1
  200. package/dist/models/region/region.model.d.ts +16 -1
  201. package/dist/models/region/region.model.js +19 -4
  202. package/dist/models/region/region.model.js.map +1 -1
  203. package/dist/models/region/region.schema.d.ts +6 -0
  204. package/dist/models/region/region.schema.js +6 -0
  205. package/dist/models/region/region.schema.js.map +1 -1
  206. package/dist/models/server/server.model.d.ts +15 -3
  207. package/dist/models/server/server.model.js +18 -6
  208. package/dist/models/server/server.model.js.map +1 -1
  209. package/dist/models/server/server.schema.d.ts +3 -1
  210. package/dist/models/server/server.schema.js +3 -1
  211. package/dist/models/server/server.schema.js.map +1 -1
  212. package/dist/models/service/service.model.d.ts +37 -6
  213. package/dist/models/service/service.model.js +65 -11
  214. package/dist/models/service/service.model.js.map +1 -1
  215. package/dist/models/service/service.schema.d.ts +48 -1
  216. package/dist/models/service/service.schema.js +56 -1
  217. package/dist/models/service/service.schema.js.map +1 -1
  218. package/dist/models/subnet/subnet.model.d.ts +27 -3
  219. package/dist/models/subnet/subnet.model.js +40 -16
  220. package/dist/models/subnet/subnet.model.js.map +1 -1
  221. package/dist/models/subnet/subnet.schema.d.ts +9 -0
  222. package/dist/models/subnet/subnet.schema.js +9 -0
  223. package/dist/models/subnet/subnet.schema.js.map +1 -1
  224. package/dist/modes/apply-transaction.d.ts +23 -0
  225. package/dist/modes/apply-transaction.js +25 -0
  226. package/dist/modes/apply-transaction.js.map +1 -0
  227. package/dist/modes/commit.mode.d.ts +54 -0
  228. package/dist/modes/commit.mode.js +235 -0
  229. package/dist/modes/commit.mode.js.map +1 -0
  230. package/dist/modes/generate.mode.d.ts +30 -0
  231. package/dist/modes/generate.mode.js +50 -0
  232. package/dist/modes/generate.mode.js.map +1 -0
  233. package/dist/modes/run-action.mode.d.ts +30 -0
  234. package/dist/modes/run-action.mode.js +140 -0
  235. package/dist/modes/run-action.mode.js.map +1 -0
  236. package/dist/modes/validate.mode.d.ts +186 -0
  237. package/dist/modes/validate.mode.js +558 -0
  238. package/dist/modes/validate.mode.js.map +1 -0
  239. package/dist/modules/module.abstract.d.ts +51 -0
  240. package/dist/modules/module.abstract.js +36 -0
  241. package/dist/modules/module.abstract.js.map +1 -1
  242. package/dist/modules/module.container.d.ts +43 -1
  243. package/dist/modules/module.container.js +77 -5
  244. package/dist/modules/module.container.js.map +1 -1
  245. package/dist/modules/test-module.container.d.ts +139 -25
  246. package/dist/modules/test-module.container.js +383 -199
  247. package/dist/modules/test-module.container.js.map +1 -1
  248. package/dist/overlays/anchor.abstract.d.ts +32 -1
  249. package/dist/overlays/anchor.abstract.js +42 -11
  250. package/dist/overlays/anchor.abstract.js.map +1 -1
  251. package/dist/overlays/anchor.schema.d.ts +21 -0
  252. package/dist/overlays/anchor.schema.js +21 -0
  253. package/dist/overlays/anchor.schema.js.map +1 -1
  254. package/dist/overlays/overlay-data.repository.d.ts +18 -0
  255. package/dist/overlays/overlay-data.repository.js +18 -0
  256. package/dist/overlays/overlay-data.repository.js.map +1 -1
  257. package/dist/overlays/overlay.abstract.d.ts +56 -1
  258. package/dist/overlays/overlay.abstract.js +79 -20
  259. package/dist/overlays/overlay.abstract.js.map +1 -1
  260. package/dist/overlays/overlay.schema.d.ts +20 -0
  261. package/dist/overlays/overlay.schema.js +20 -0
  262. package/dist/overlays/overlay.schema.js.map +1 -1
  263. package/dist/resources/resource-action.interface.d.ts +29 -3
  264. package/dist/resources/resource-data.repository.d.ts +63 -1
  265. package/dist/resources/resource-data.repository.js +94 -4
  266. package/dist/resources/resource-data.repository.js.map +1 -1
  267. package/dist/resources/resource.abstract.d.ts +163 -6
  268. package/dist/resources/resource.abstract.js +223 -59
  269. package/dist/resources/resource.abstract.js.map +1 -1
  270. package/dist/resources/resource.interface.d.ts +0 -2
  271. package/dist/resources/resource.schema.d.ts +39 -1
  272. package/dist/resources/resource.schema.js +38 -0
  273. package/dist/resources/resource.schema.js.map +1 -1
  274. package/dist/resources/terraform-resource.abstract.d.ts +44 -0
  275. package/dist/resources/terraform-resource.abstract.js +45 -0
  276. package/dist/resources/terraform-resource.abstract.js.map +1 -0
  277. package/dist/services/event/event.service.d.ts +32 -5
  278. package/dist/services/event/event.service.js +58 -16
  279. package/dist/services/event/event.service.js.map +1 -1
  280. package/dist/services/input/input.service.d.ts +82 -5
  281. package/dist/services/input/input.service.js +143 -12
  282. package/dist/services/input/input.service.js.map +1 -1
  283. package/dist/services/schema-translation/schema-translation.service.d.ts +9 -0
  284. package/dist/services/schema-translation/schema-translation.service.js +9 -0
  285. package/dist/services/schema-translation/schema-translation.service.js.map +1 -1
  286. package/dist/services/serialization/model/model-serialization.service.d.ts +25 -3
  287. package/dist/services/serialization/model/model-serialization.service.js +113 -62
  288. package/dist/services/serialization/model/model-serialization.service.js.map +1 -1
  289. package/dist/services/serialization/resource/resource-serialization.service.d.ts +36 -6
  290. package/dist/services/serialization/resource/resource-serialization.service.js +77 -28
  291. package/dist/services/serialization/resource/resource-serialization.service.js.map +1 -1
  292. package/dist/services/state-management/local.state-provider.d.ts +67 -4
  293. package/dist/services/state-management/local.state-provider.js +168 -41
  294. package/dist/services/state-management/local.state-provider.js.map +1 -1
  295. package/dist/services/state-management/remote.state-provider.d.ts +216 -0
  296. package/dist/services/state-management/remote.state-provider.js +645 -0
  297. package/dist/services/state-management/remote.state-provider.js.map +1 -0
  298. package/dist/services/state-management/state-management.service.d.ts +195 -17
  299. package/dist/services/state-management/state-management.service.js +259 -10
  300. package/dist/services/state-management/state-management.service.js.map +1 -1
  301. package/dist/services/state-management/state-provider.interface.d.ts +98 -3
  302. package/dist/services/state-management/state-provider.interface.js +14 -1
  303. package/dist/services/state-management/state-provider.interface.js.map +1 -1
  304. package/dist/services/state-management/terraform-state.service.d.ts +99 -0
  305. package/dist/services/state-management/terraform-state.service.js +197 -0
  306. package/dist/services/state-management/terraform-state.service.js.map +1 -0
  307. package/dist/services/state-management/test.state-provider.d.ts +42 -4
  308. package/dist/services/state-management/test.state-provider.js +77 -25
  309. package/dist/services/state-management/test.state-provider.js.map +1 -1
  310. package/dist/services/terraform/terraform.service.d.ts +480 -0
  311. package/dist/services/terraform/terraform.service.js +1082 -0
  312. package/dist/services/terraform/terraform.service.js.map +1 -0
  313. package/dist/services/terraform/terraform.type.d.ts +387 -0
  314. package/dist/services/terraform/terraform.type.js +579 -0
  315. package/dist/services/terraform/terraform.type.js.map +1 -0
  316. package/dist/services/transaction/transaction.service.d.ts +110 -10
  317. package/dist/services/transaction/transaction.service.js +570 -251
  318. package/dist/services/transaction/transaction.service.js.map +1 -1
  319. package/dist/services/validation/validation.service.d.ts +15 -3
  320. package/dist/services/validation/validation.service.js +12 -0
  321. package/dist/services/validation/validation.service.js.map +1 -1
  322. package/dist/utilities/array/array.utility.d.ts +3 -0
  323. package/dist/utilities/array/array.utility.js +3 -0
  324. package/dist/utilities/array/array.utility.js.map +1 -1
  325. package/dist/{functions → utilities}/diff/diff.utility.d.ts +19 -3
  326. package/dist/{functions → utilities}/diff/diff.utility.js +57 -41
  327. package/dist/utilities/diff/diff.utility.js.map +1 -0
  328. package/dist/utilities/file/file.utility.d.ts +16 -2
  329. package/dist/utilities/file/file.utility.js +23 -61
  330. package/dist/utilities/file/file.utility.js.map +1 -1
  331. package/dist/utilities/hcl/hcl.utility.d.ts +128 -0
  332. package/dist/utilities/hcl/hcl.utility.js +402 -0
  333. package/dist/utilities/hcl/hcl.utility.js.map +1 -0
  334. package/dist/utilities/http/http.utility.d.ts +57 -0
  335. package/dist/utilities/http/http.utility.js +98 -0
  336. package/dist/utilities/http/http.utility.js.map +1 -0
  337. package/dist/utilities/node/node.utility.d.ts +3 -0
  338. package/dist/utilities/node/node.utility.js +3 -0
  339. package/dist/utilities/node/node.utility.js.map +1 -1
  340. package/dist/utilities/object/object.utility.d.ts +12 -0
  341. package/dist/utilities/object/object.utility.js +12 -0
  342. package/dist/utilities/object/object.utility.js.map +1 -1
  343. package/dist/utilities/project/project.utility.d.ts +28 -0
  344. package/dist/utilities/project/project.utility.js +35 -0
  345. package/dist/utilities/project/project.utility.js.map +1 -0
  346. package/dist/utilities/string/string.utility.d.ts +41 -0
  347. package/dist/utilities/string/string.utility.js +65 -0
  348. package/dist/utilities/string/string.utility.js.map +1 -0
  349. package/dist/utilities/terraform/terraform.utility.d.ts +276 -0
  350. package/dist/utilities/terraform/terraform.utility.js +623 -0
  351. package/dist/utilities/terraform/terraform.utility.js.map +1 -0
  352. package/dist/utilities/test-helpers/test-classes.d.ts +36 -30
  353. package/dist/utilities/test-helpers/test-classes.js +38 -39
  354. package/dist/utilities/test-helpers/test-classes.js.map +1 -1
  355. package/dist/utilities/test-helpers/test-models.d.ts +8 -1
  356. package/dist/utilities/test-helpers/test-models.js +37 -12
  357. package/dist/utilities/test-helpers/test-models.js.map +1 -1
  358. package/dist/utilities/test-helpers/test-modes.d.ts +315 -0
  359. package/dist/utilities/test-helpers/test-modes.js +486 -0
  360. package/dist/utilities/test-helpers/test-modes.js.map +1 -0
  361. package/dist/utilities/test-helpers/test-modules.d.ts +47 -0
  362. package/dist/utilities/test-helpers/test-modules.js +85 -0
  363. package/dist/utilities/test-helpers/test-modules.js.map +1 -0
  364. package/dist/utilities/test-helpers/test-overlays.d.ts +20 -2
  365. package/dist/utilities/test-helpers/test-overlays.js +56 -6
  366. package/dist/utilities/test-helpers/test-overlays.js.map +1 -1
  367. package/dist/utilities/test-helpers/test-resources.d.ts +23 -3
  368. package/dist/utilities/test-helpers/test-resources.js +83 -23
  369. package/dist/utilities/test-helpers/test-resources.js.map +1 -1
  370. package/dist/utilities/validation/validation.utility.d.ts +24 -0
  371. package/dist/utilities/validation/validation.utility.js +24 -0
  372. package/dist/utilities/validation/validation.utility.js.map +1 -1
  373. package/package.json +12 -6
  374. package/dist/functions/diff/diff.utility.js.map +0 -1
  375. package/dist/services/capture/capture.service.d.ts +0 -19
  376. package/dist/services/capture/capture.service.js +0 -43
  377. package/dist/services/capture/capture.service.js.map +0 -1
  378. package/dist/services/state-management/local-encryption.state-provider.d.ts +0 -20
  379. package/dist/services/state-management/local-encryption.state-provider.js +0 -90
  380. package/dist/services/state-management/local-encryption.state-provider.js.map +0 -1
  381. package/dist/utilities/cidr/cidr.utility.d.ts +0 -10
  382. package/dist/utilities/cidr/cidr.utility.js +0 -51
  383. package/dist/utilities/cidr/cidr.utility.js.map +0 -1
@@ -1,35 +1,42 @@
1
- import { readFile, writeFile } from 'fs/promises';
2
- import { join, resolve } from 'path';
3
- import { TransactionError } from '../../errors/index.js';
1
+ import { randomUUID } from 'crypto';
2
+ import { copyFile, readFile, readdir, rm, writeFile } from 'fs/promises';
3
+ import { dirname, join, resolve } from 'path';
4
+ import { AppLockError, TransactionError } from '../../errors/index.js';
5
+ import { FileUtility } from '../../utilities/file/file.utility.js';
4
6
  /**
7
+ * Keeps state in a directory on the local filesystem.
8
+ *
9
+ * Good for experimenting on your own machine. It is not shared, so a team running Octo against the
10
+ * same infrastructure needs a provider that persists somewhere they all reach.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * await octo.initialize(new LocalStateProvider('./infrastructure'));
15
+ * ```
16
+ *
5
17
  * @group Services/State Management
18
+ *
19
+ * @see Techniques for [State Providers](/docs/techniques/state-providers).
6
20
  */
7
21
  export class LocalStateProvider {
22
+ /**
23
+ * @param localStateDirectoryPath The directory state files are written into.
24
+ */
8
25
  constructor(localStateDirectoryPath) {
9
26
  this.localStateDirectoryPath = resolve(localStateDirectoryPath);
10
- this.lockFilePath = resolve(join(localStateDirectoryPath, 'local-state.lock'));
11
- }
12
- async addOrUpdateAppLock(lockId) {
13
- await writeFile(this.lockFilePath, lockId);
27
+ this.lockFilePath = join(this.localStateDirectoryPath, 'local-state.lock');
14
28
  }
29
+ /**
30
+ * The id of the lock currently held, or `undefined` when the app is unlocked.
31
+ */
15
32
  async getAppLock() {
16
- try {
17
- const contents = await readFile(this.lockFilePath, 'utf-8');
18
- const appLock = contents.replace(/\s/g, '');
19
- if (!appLock) {
20
- return undefined;
21
- }
22
- return appLock;
23
- }
24
- catch (error) {
25
- if (error.code === 'ENOENT') {
26
- return undefined;
27
- }
28
- else {
29
- throw error;
30
- }
31
- }
33
+ return (await this.readLock())?.lockId;
32
34
  }
35
+ /**
36
+ * Reads a state file.
37
+ *
38
+ * @throws {@link TransactionError} With the message `No state found!` when the file does not exist.
39
+ */
33
40
  async getState(stateFileName) {
34
41
  try {
35
42
  return await readFile(join(this.localStateDirectoryPath, stateFileName));
@@ -41,44 +48,164 @@ export class LocalStateProvider {
41
48
  throw error;
42
49
  }
43
50
  }
51
+ /**
52
+ * Whether `lockId` is the lock currently held.
53
+ *
54
+ * @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held.
55
+ */
44
56
  async isAppLocked(lockId) {
45
57
  const existingLockId = await this.getAppLock();
46
58
  if (!existingLockId) {
47
59
  return false;
48
60
  }
49
- if (lockId !== existingLockId) {
61
+ if (existingLockId !== lockId) {
50
62
  throw new TransactionError('Invalid lock ID!');
51
63
  }
52
- else {
53
- return true;
64
+ return true;
65
+ }
66
+ /**
67
+ * The names of the state files whose name starts with `prefix`.
68
+ */
69
+ async listStates(prefix) {
70
+ let entries;
71
+ try {
72
+ entries = await readdir(this.localStateDirectoryPath);
73
+ }
74
+ catch (error) {
75
+ if (error.code === 'ENOENT') {
76
+ return [];
77
+ }
78
+ throw error;
54
79
  }
80
+ return entries.filter((entry) => entry.startsWith(prefix));
55
81
  }
56
- async lockApp() {
57
- const existingLockId = await this.getAppLock();
58
- if (existingLockId) {
59
- throw new TransactionError('App already locked!');
82
+ /**
83
+ * Takes the app lock, writing its id and the time it was taken into `local-state.lock` beside the
84
+ * state files. With `lockId`, resumes the run already holding it. The lock never expires.
85
+ *
86
+ * @throws {@link AppLockError} When a lock is held, naming the id that holds it and how long it has
87
+ * been held. When `lockId` is given and is not the lock held.
88
+ */
89
+ async lockApp(lockId) {
90
+ await FileUtility.ensureDirectory(this.localStateDirectoryPath);
91
+ // Resume the run holding the lock, which on one machine holds nothing more to read.
92
+ if (lockId) {
93
+ if ((await this.getAppLock()) !== lockId) {
94
+ throw new AppLockError(`App is not locked with lock ID "${lockId}"!`, { reason: 'not-held' });
95
+ }
96
+ return { lockId };
97
+ }
98
+ // Take the lock with an exclusive create, so of two runs racing for it exactly one wins.
99
+ const newLockId = randomUUID();
100
+ const record = { lockId: newLockId, startedAt: Date.now() };
101
+ try {
102
+ await writeFile(this.lockFilePath, JSON.stringify(record), { flag: 'wx' });
60
103
  }
61
- const lockId = crypto.randomUUID();
62
- await this.addOrUpdateAppLock(lockId);
63
- return { lockId };
104
+ catch (error) {
105
+ if (error.code === 'EEXIST') {
106
+ const holder = await this.readLock();
107
+ const heldFor = holder?.startedAt === undefined ? undefined : this.describeAge(holder.startedAt);
108
+ throw new AppLockError(`App already locked with lock ID "${holder?.lockId}"${heldFor ? `, held for ${heldFor}` : ''}!`, {
109
+ holder: holder ? { lockId: holder.lockId, takenAt: holder.startedAt } : undefined,
110
+ reason: 'held',
111
+ });
112
+ }
113
+ throw error;
114
+ }
115
+ return { lockId: newLockId };
116
+ }
117
+ /**
118
+ * Does nothing: the directory is the only copy of the state, so it is always the newest.
119
+ */
120
+ async refreshState() {
121
+ return { replaced: false };
64
122
  }
65
- async saveState(stateFileName, data) {
66
- await writeFile(join(this.localStateDirectoryPath, stateFileName), data);
123
+ /**
124
+ * Writes state files, overwriting whatever was there, copying each one given a `filePath`, and
125
+ * deleting each one given no `data`. A name holding `/` is written into a directory beneath the state
126
+ * directory.
127
+ */
128
+ async saveStates(stateFiles) {
129
+ for (const stateFile of stateFiles) {
130
+ const stateFilePath = join(this.localStateDirectoryPath, stateFile.stateFileName);
131
+ if ('filePath' in stateFile) {
132
+ await FileUtility.ensureDirectory(dirname(stateFilePath));
133
+ await copyFile(stateFile.filePath, stateFilePath);
134
+ }
135
+ else if (stateFile.data === undefined) {
136
+ await rm(stateFilePath, { force: true });
137
+ }
138
+ else {
139
+ await FileUtility.ensureDirectory(dirname(stateFilePath));
140
+ await writeFile(stateFilePath, stateFile.data);
141
+ }
142
+ }
67
143
  }
144
+ /**
145
+ * Releases the app lock by deleting the lock file.
146
+ *
147
+ * @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held.
148
+ */
68
149
  async unlockApp(lockId) {
69
150
  const existingLockId = await this.getAppLock();
70
151
  if (!existingLockId) {
71
152
  return;
72
153
  }
73
- if (lockId !== existingLockId) {
154
+ if (existingLockId !== lockId) {
74
155
  throw new TransactionError('Invalid lock ID!');
75
156
  }
76
- await this.addOrUpdateAppLock('');
157
+ await rm(this.lockFilePath, { force: true });
77
158
  }
78
- async updateAppLockTransaction(lockId) {
79
- const isAppLocked = await this.isAppLocked(lockId);
80
- if (!isAppLocked) {
81
- throw new TransactionError('App is unlocked!');
159
+ /**
160
+ * How long the lock has been held, as a short readable span. Undefined when the recorded time
161
+ * cannot be read as one, so a broken value is left out rather than reported as a negative age.
162
+ */
163
+ describeAge(startedAt) {
164
+ const heldForMs = Date.now() - startedAt;
165
+ if (!Number.isFinite(heldForMs) || heldForMs < 0) {
166
+ return undefined;
167
+ }
168
+ const seconds = Math.floor(heldForMs / 1000);
169
+ if (seconds < 60) {
170
+ return `${seconds}s`;
171
+ }
172
+ const minutes = Math.floor(seconds / 60);
173
+ if (minutes < 60) {
174
+ return `${minutes}m`;
175
+ }
176
+ const hours = Math.floor(minutes / 60);
177
+ if (hours < 24) {
178
+ return `${hours}h ${minutes % 60}m`;
179
+ }
180
+ return `${Math.floor(hours / 24)}d ${hours % 24}h`;
181
+ }
182
+ /**
183
+ * The lock file's record, or undefined when no lock is held. A file holding an id and nothing else
184
+ * is a lock taken before the record carried a time, and reads as that id with no age.
185
+ */
186
+ async readLock() {
187
+ let contents;
188
+ try {
189
+ contents = (await readFile(this.lockFilePath, 'utf-8')).trim();
190
+ }
191
+ catch (error) {
192
+ if (error.code === 'ENOENT') {
193
+ return undefined;
194
+ }
195
+ throw error;
196
+ }
197
+ if (!contents) {
198
+ return undefined;
199
+ }
200
+ if (!contents.startsWith('{')) {
201
+ return { lockId: contents };
202
+ }
203
+ try {
204
+ const record = JSON.parse(contents);
205
+ return typeof record.lockId === 'string' ? record : { lockId: contents };
206
+ }
207
+ catch (error) {
208
+ return { lockId: contents };
82
209
  }
83
210
  }
84
211
  }
@@ -1 +1 @@
1
- {"version":3,"file":"local.state-provider.js","sourceRoot":"","sources":["../../../src/services/state-management/local.state-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local.state-provider.js","sourceRoot":"","sources":["../../../src/services/state-management/local.state-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ import { type IStateProvider } from './state-provider.interface.js';
2
+ /**
3
+ * Keeps state in Octo's managed backend, so a team shares one store and no machine holds the only copy.
4
+ *
5
+ * A run reads and writes a state directory on disk, exactly as {@link LocalStateProvider} does, and
6
+ * the backend is kept in step with it:
7
+ *
8
+ * - {@link RemoteStateProvider.refreshState} brings the directory up to the newest sealed state, and
9
+ * is what `octo generate` plans against.
10
+ * - {@link RemoteStateProvider.lockApp} opens a new record for the run, refusing when the newest
11
+ * sealed state has moved since the directory was refreshed.
12
+ * - Every write under the lock lands in the directory and in the run's record before it returns, so
13
+ * a run that dies leaves a record somebody can finish from another machine.
14
+ * - {@link RemoteStateProvider.unlockApp} seals the record and releases the lock.
15
+ *
16
+ * Two files of the provider's own sit beside the state files and are never uploaded:
17
+ * `remote-state.lock` records the run the directory belongs to and is deleted when the lock is
18
+ * released, and `remote-state-upload.lock` makes the octo processes of one machine write to the
19
+ * backend one at a time and is deleted after every write.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * await octo.initialize(
24
+ * new RemoteStateProvider({
25
+ * appId: 'my-app',
26
+ * localStateDirectoryPath: './.octo',
27
+ * organizationId: 'my-organization',
28
+ * sessionId: process.env.OCTO_SESSION!,
29
+ * stateManagementServiceUrl: 'http://localhost:3619/state',
30
+ * }),
31
+ * );
32
+ * ```
33
+ *
34
+ * @group Services/State Management
35
+ *
36
+ * @see Techniques for [State Providers](/docs/techniques/state-providers).
37
+ */
38
+ export declare class RemoteStateProvider implements IStateProvider {
39
+ private readonly appId;
40
+ private readonly localStateDirectoryPath;
41
+ private readonly localStateProvider;
42
+ private readonly lockContext;
43
+ private readonly organizationId;
44
+ private readonly sessionId;
45
+ private readonly stateManagementServiceUrl;
46
+ /**
47
+ * @param options `organizationId` and `appId` name the app whose state this is, and `sessionId`
48
+ * is the session the run acts as. `stateManagementServiceUrl` is the backend service, including
49
+ * the prefix its routes sit behind. `localStateDirectoryPath` is the directory state files are
50
+ * written into. `lockContext` is what a blocked run is shown about the holder.
51
+ */
52
+ constructor(options: {
53
+ appId: string;
54
+ localStateDirectoryPath: string;
55
+ lockContext?: string;
56
+ organizationId: string;
57
+ sessionId: string;
58
+ stateManagementServiceUrl: string;
59
+ });
60
+ /**
61
+ * The id of the lock currently held, or `undefined` when the app is unlocked.
62
+ */
63
+ getAppLock(): Promise<string | undefined>;
64
+ /**
65
+ * Reads a state file.
66
+ *
67
+ * @throws {@link TransactionError} With the message `No state found!` when the file does not exist.
68
+ */
69
+ getState(stateFileName: string): Promise<Buffer>;
70
+ /**
71
+ * Whether `lockId` is the lock currently held.
72
+ *
73
+ * @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held,
74
+ * and when `lockId` is held but was neither taken nor resumed in this state directory.
75
+ */
76
+ isAppLocked(lockId: string): Promise<boolean>;
77
+ /**
78
+ * The names of the state files whose name starts with `prefix`.
79
+ */
80
+ listStates(prefix: string): Promise<string[]>;
81
+ /**
82
+ * Takes the app lock and opens the run's record with everything the state directory holds.
83
+ *
84
+ * With `lockId`, resumes the run already holding that lock instead - from any machine, as the
85
+ * account that took it or an organization administrator. The state directory is replaced with
86
+ * what that run wrote so far, its journal included, keeping this machine's journal files, which join
87
+ * the record, and every write after lands in its record. A run that wrote nothing is resumed from the
88
+ * newest sealed state, without that state's journal.
89
+ *
90
+ * @throws {@link AppLockError} When a lock is held, naming the id that holds it. When the newest
91
+ * sealed state moved since {@link RemoteStateProvider.refreshState} last ran. When `lockId` is
92
+ * given and is not held.
93
+ */
94
+ lockApp(lockId?: string): ReturnType<IStateProvider['lockApp']>;
95
+ /**
96
+ * Brings the state directory up to the newest sealed state, which is what a run plans against.
97
+ *
98
+ * A directory an open run is still writing is left alone. A directory the backend holds nothing
99
+ * for is left alone too: that is a first run, or a project arriving from another provider, and the
100
+ * files on disk are the only copy there is. Journal files are neither replaced nor taken.
101
+ */
102
+ refreshState(): Promise<{
103
+ commitId?: string;
104
+ previousCommitId?: string;
105
+ replaced: boolean;
106
+ }>;
107
+ /**
108
+ * Writes state files, deleting each one given no `data`, and then writes the run's record once for
109
+ * all of them when a run is open. A name holding `/` is the machine's own: it is written beneath
110
+ * the state directory and never reaches the record.
111
+ *
112
+ * @throws {@link TransactionError} When the backend would refuse a file's name, before anything is
113
+ * written. When the backend refuses the write, which is where the limits it holds the app to apply.
114
+ */
115
+ saveStates(stateFiles: Parameters<IStateProvider['saveStates']>[0]): Promise<void>;
116
+ /**
117
+ * Writes the directory into the run's record, seals it, and releases the app lock. Unlocking an app
118
+ * that is not locked is not an error.
119
+ *
120
+ * A write that failed earlier left the directory ahead of the record, so the record is written once
121
+ * more before it is sealed: a sealed record is what every machine plans against next.
122
+ *
123
+ * @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held.
124
+ * When the directory cannot be written into the record, keeping the lock held.
125
+ */
126
+ unlockApp(lockId: string): Promise<void>;
127
+ /**
128
+ * The route this app's state and locks are read and written at.
129
+ */
130
+ private appStateUrl;
131
+ /**
132
+ * The session this run acts as. Every route but the health check is behind it.
133
+ */
134
+ private authorizationHeader;
135
+ /**
136
+ * Deletes the lock file. Deleting one that is not there is not an error.
137
+ */
138
+ private deleteLockFile;
139
+ /**
140
+ * How long the lock has been held, as a short readable span. Undefined when the recorded time
141
+ * cannot be read as one, so a broken value is left out rather than reported as a negative age.
142
+ */
143
+ private describeAge;
144
+ /**
145
+ * Writes the directory into the run's record, when this directory belongs to an open run.
146
+ */
147
+ private pushRun;
148
+ /**
149
+ * Every lock the backend holds on this app, oldest first.
150
+ */
151
+ private readAppLocks;
152
+ /**
153
+ * The lock file. Empty when there is none.
154
+ */
155
+ private readLockFile;
156
+ /**
157
+ * The newest record the app holds, sealed or not, or `undefined` when it holds none.
158
+ *
159
+ * One run holds the whole app at a time, so records are opened in the order they are sealed.
160
+ */
161
+ private readNewestState;
162
+ /**
163
+ * Releases a lock, sealing the record its commit names. False when the lock is not held.
164
+ */
165
+ private releaseAppLock;
166
+ /**
167
+ * Replaces every state file in the directory with the ones a state body names, downloading each
168
+ * from its URL and checking it against its SHA-256, and returns the body. The directory's journal
169
+ * files are kept; with `takeJournal`, the body's are written beside them.
170
+ *
171
+ * Each file is streamed to a temporary file beside it, so a state is not bounded by memory.
172
+ */
173
+ private replaceStateFiles;
174
+ /**
175
+ * Resumes the run holding `lockId` in this state directory.
176
+ */
177
+ private resumeAppLock;
178
+ /**
179
+ * Every state file the directory holds, which is every file in it but the provider's two lock
180
+ * files and a write still in progress, and none of the directories a run writes beside them, such
181
+ * as a generated terragrunt folder.
182
+ */
183
+ private stateFileNames;
184
+ /**
185
+ * Runs `body` while holding `remote-state-upload.lock`, so one write to the backend is in flight at
186
+ * a time across every octo process on this machine. The file is deleted when `body` returns, and
187
+ * one left by a process that is gone is taken over.
188
+ */
189
+ private withUploadLock;
190
+ /**
191
+ * Writes the lock file.
192
+ */
193
+ private writeLockFile;
194
+ /**
195
+ * Writes the directory into the run's record as it stands, and returns the SHA-256 of every file the
196
+ * record holds afterwards.
197
+ *
198
+ * A write is three requests: the upload is asked for naming every file and its digest, the files
199
+ * the backend does not already hold are PUT to the URLs it answered with, and the upload is
200
+ * claimed. A file that fails to upload stops the write before the claim, and a claim with a file
201
+ * missing is refused, so a write lands whole or not at all. An upload left unclaimed is thrown away by
202
+ * the backend at the next write or when the lock is released. A directory holding nothing writes
203
+ * nothing, since the backend holds no empty state.
204
+ *
205
+ * The files are hard linked into a snapshot directory first and streamed from there, so a state is
206
+ * not bounded by memory, and a file another process replaces meanwhile is uploaded as it was
207
+ * hashed: a write replaces a file by renaming over it, which leaves the linked one as it was.
208
+ */
209
+ private writeRunState;
210
+ /**
211
+ * Writes one file into the state directory whole, from `data` or copied from `filePath`, so a process
212
+ * reading it never reads half of it. Replacing the file rather than writing into it is also what lets
213
+ * an upload freeze it with a hard link.
214
+ */
215
+ private writeStateFile;
216
+ }