@highstate/backend 0.9.18 → 0.9.20

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 (331) hide show
  1. package/dist/{chunk-OU5OQBLB.js → chunk-I7BWSAN6.js} +3 -28
  2. package/dist/{chunk-OU5OQBLB.js.map → chunk-I7BWSAN6.js.map} +1 -1
  3. package/dist/chunk-RC6Q3XQQ.js +1547 -0
  4. package/dist/chunk-RC6Q3XQQ.js.map +1 -0
  5. package/dist/chunk-VB4YL327.js +139 -0
  6. package/dist/chunk-VB4YL327.js.map +1 -0
  7. package/dist/database/local/prisma.config.js +26 -0
  8. package/dist/database/local/prisma.config.js.map +1 -0
  9. package/dist/highstate.manifest.json +2 -1
  10. package/dist/index.js +7590 -7289
  11. package/dist/index.js.map +1 -1
  12. package/dist/library/package-resolution-worker.js +1 -1
  13. package/dist/library/package-resolution-worker.js.map +1 -1
  14. package/dist/library/worker/main.js +35 -29
  15. package/dist/library/worker/main.js.map +1 -1
  16. package/dist/shared/index.js +2 -2
  17. package/package.json +18 -9
  18. package/prisma/backend/_schema/layout.prisma +7 -0
  19. package/prisma/backend/_schema/library.prisma +17 -0
  20. package/prisma/backend/_schema/project.prisma +101 -0
  21. package/prisma/backend/_schema/pulumi.prisma +17 -0
  22. package/prisma/backend/postgresql/main.prisma +17 -0
  23. package/prisma/backend/sqlite/main.prisma +17 -0
  24. package/prisma/backend/sqlite/migrations/20250817070609_initiial/migration.sql +34 -0
  25. package/prisma/backend/sqlite/migrations/20250817104948_add_fields/migration.sql +59 -0
  26. package/prisma/backend/sqlite/migrations/20250818082732_add_models/migration.sql +41 -0
  27. package/prisma/backend/sqlite/migrations/20250818083106_a/migration.sql +19 -0
  28. package/prisma/backend/sqlite/migrations/20250818101945_hi/migration.sql +1 -0
  29. package/prisma/backend/sqlite/migrations/20250819082315_a/migration.sql +5 -0
  30. package/prisma/backend/sqlite/migrations/migration_lock.toml +3 -0
  31. package/prisma/project/api-key.prisma +32 -0
  32. package/prisma/project/artifact.prisma +52 -0
  33. package/prisma/project/custom-status.prisma +46 -0
  34. package/prisma/project/evaluation.prisma +45 -0
  35. package/prisma/project/instance.prisma +157 -0
  36. package/prisma/project/layout.prisma +23 -0
  37. package/prisma/project/lock.prisma +18 -0
  38. package/prisma/project/main.prisma +17 -0
  39. package/prisma/project/migrations/20250816081310_initial/migration.sql +300 -0
  40. package/prisma/project/migrations/20250816082523_test/migration.sql +72 -0
  41. package/prisma/project/migrations/20250818065643_update/migration.sql +42 -0
  42. package/prisma/project/migrations/20250818070758_a/migration.sql +8 -0
  43. package/prisma/project/migrations/20250818070913_a/migration.sql +8 -0
  44. package/prisma/project/migrations/20250818082720_add_motels/migration.sql +11 -0
  45. package/prisma/project/migrations/20250818112523_hello/migration.sql +35 -0
  46. package/prisma/project/migrations/20250819082305_a/migration.sql +14 -0
  47. package/prisma/project/migrations/20250819165004_add_missing_fields/migration.sql +216 -0
  48. package/prisma/project/migrations/20250819171309_a/migration.sql +22 -0
  49. package/prisma/project/migrations/20250820113949_a/migration.sql +66 -0
  50. package/prisma/project/migrations/20250820144256_b/migration.sql +31 -0
  51. package/prisma/project/migrations/20250820145547_a/migration.sql +24 -0
  52. package/prisma/project/migrations/20250820182517_b/migration.sql +2 -0
  53. package/prisma/project/migrations/20250821172324_a/migration.sql +2 -0
  54. package/prisma/project/migrations/20250822081339_a/migration.sql +219 -0
  55. package/prisma/project/migrations/20250822083742_b/migration.sql +1 -0
  56. package/prisma/project/migrations/20250822105134_boom/migration.sql +1 -0
  57. package/prisma/project/migrations/20250822141028_b/migration.sql +1 -0
  58. package/prisma/project/migrations/20250822142342_b/migration.sql +16 -0
  59. package/prisma/project/migrations/20250824072720_a/migration.sql +1 -0
  60. package/prisma/project/migrations/20250824093656_b/migration.sql +21 -0
  61. package/prisma/project/migrations/20250825082518_a/migration.sql +1 -0
  62. package/prisma/project/migrations/20250825085343_b/migration.sql +1 -0
  63. package/prisma/project/migrations/20250825091312_a/migration.sql +1 -0
  64. package/prisma/project/migrations/20250903095431_hi/migration.sql +44 -0
  65. package/prisma/project/migrations/20250903174255_a/migration.sql +24 -0
  66. package/prisma/project/migrations/20250908095205_hi/migration.sql +18 -0
  67. package/prisma/project/migrations/20250909155857_hi/migration.sql +15 -0
  68. package/prisma/project/migrations/migration_lock.toml +3 -0
  69. package/prisma/project/model.prisma +37 -0
  70. package/prisma/project/operation.prisma +148 -0
  71. package/prisma/project/page.prisma +49 -0
  72. package/prisma/project/secret.prisma +54 -0
  73. package/prisma/project/service-account.prisma +42 -0
  74. package/prisma/project/terminal.prisma +107 -0
  75. package/prisma/project/trigger.prisma +37 -0
  76. package/prisma/project/unlock-method.prisma +46 -0
  77. package/prisma/project/worker.prisma +169 -0
  78. package/src/artifact/abstractions.ts +13 -13
  79. package/src/artifact/encryption.ts +30 -54
  80. package/src/artifact/factory.ts +6 -9
  81. package/src/artifact/local.ts +33 -46
  82. package/src/business/api-key.ts +24 -36
  83. package/src/business/artifact.test.ts +978 -0
  84. package/src/business/artifact.ts +136 -216
  85. package/src/business/evaluation.ts +328 -0
  86. package/src/business/index.ts +5 -2
  87. package/src/business/instance-lock.test.ts +1060 -0
  88. package/src/business/instance-lock.ts +387 -78
  89. package/src/business/instance-state.test.ts +735 -0
  90. package/src/business/instance-state.ts +582 -337
  91. package/src/business/operation.test.ts +439 -0
  92. package/src/business/operation.ts +174 -208
  93. package/src/business/project-model.ts +258 -0
  94. package/src/business/project-unlock.ts +168 -126
  95. package/src/business/project.ts +287 -179
  96. package/src/business/secret.test.ts +469 -130
  97. package/src/business/secret.ts +177 -217
  98. package/src/business/settings.test.ts +695 -0
  99. package/src/business/settings.ts +855 -0
  100. package/src/business/terminal-session.ts +90 -0
  101. package/src/business/unit-extra.test.ts +539 -0
  102. package/src/business/unit-extra.ts +160 -0
  103. package/src/business/worker.test.ts +356 -579
  104. package/src/business/worker.ts +238 -339
  105. package/src/common/codebase.ts +65 -0
  106. package/src/common/index.ts +3 -5
  107. package/src/common/logger.ts +5 -0
  108. package/src/common/utils.ts +4 -3
  109. package/src/config.ts +10 -11
  110. package/src/database/_generated/backend/postgresql/client.ts +72 -0
  111. package/src/database/_generated/backend/postgresql/commonInputTypes.ts +350 -0
  112. package/src/database/_generated/backend/postgresql/enums.ts +13 -0
  113. package/src/database/_generated/backend/postgresql/internal/class.ts +320 -0
  114. package/src/database/_generated/backend/postgresql/internal/prismaNamespace.ts +1238 -0
  115. package/src/database/_generated/backend/postgresql/models/Library.ts +1263 -0
  116. package/src/database/_generated/backend/postgresql/models/Project.ts +2175 -0
  117. package/src/database/_generated/backend/postgresql/models/ProjectModelStorage.ts +1263 -0
  118. package/src/database/_generated/backend/postgresql/models/ProjectSpace.ts +1602 -0
  119. package/src/database/_generated/backend/postgresql/models/PulumiBackend.ts +1263 -0
  120. package/src/database/_generated/backend/postgresql/models/UserWorkspaseLayout.ts +1065 -0
  121. package/src/database/_generated/backend/postgresql/models.ts +16 -0
  122. package/src/database/_generated/backend/postgresql/pjtg.ts +182 -0
  123. package/src/database/_generated/backend/sqlite/client.ts +72 -0
  124. package/src/database/_generated/backend/sqlite/commonInputTypes.ts +331 -0
  125. package/src/database/_generated/backend/sqlite/enums.ts +13 -0
  126. package/src/database/_generated/backend/sqlite/internal/class.ts +318 -0
  127. package/src/database/_generated/backend/sqlite/internal/prismaNamespace.ts +1207 -0
  128. package/src/database/_generated/backend/sqlite/models/Library.ts +1261 -0
  129. package/src/database/_generated/backend/sqlite/models/Project.ts +2169 -0
  130. package/src/database/_generated/backend/sqlite/models/ProjectModelStorage.ts +1261 -0
  131. package/src/database/_generated/backend/sqlite/models/ProjectSpace.ts +1599 -0
  132. package/src/database/_generated/backend/sqlite/models/PulumiBackend.ts +1261 -0
  133. package/src/database/_generated/backend/sqlite/models/UserWorkspaseLayout.ts +1063 -0
  134. package/src/database/_generated/backend/sqlite/models.ts +16 -0
  135. package/src/database/_generated/backend/sqlite/pjtg.ts +182 -0
  136. package/src/database/_generated/project/client.ts +204 -0
  137. package/src/database/_generated/project/commonInputTypes.ts +827 -0
  138. package/src/database/_generated/project/enums.ts +104 -0
  139. package/src/database/_generated/project/internal/class.ts +479 -0
  140. package/src/database/_generated/project/internal/prismaNamespace.ts +2974 -0
  141. package/src/database/_generated/project/models/ApiKey.ts +1506 -0
  142. package/src/database/_generated/project/models/Artifact.ts +2051 -0
  143. package/src/database/_generated/project/models/HubModel.ts +1125 -0
  144. package/src/database/_generated/project/models/InstanceCustomStatus.ts +1713 -0
  145. package/src/database/_generated/project/models/InstanceEvaluationState.ts +1312 -0
  146. package/src/database/_generated/project/models/InstanceLock.ts +1268 -0
  147. package/src/database/_generated/project/models/InstanceModel.ts +1125 -0
  148. package/src/database/_generated/project/models/InstanceOperationState.ts +1707 -0
  149. package/src/database/_generated/project/models/InstanceState.ts +4613 -0
  150. package/src/database/_generated/project/models/Operation.ts +1647 -0
  151. package/src/database/_generated/project/models/OperationLog.ts +1455 -0
  152. package/src/database/_generated/project/models/Page.ts +1838 -0
  153. package/src/database/_generated/project/models/Secret.ts +1692 -0
  154. package/src/database/_generated/project/models/ServiceAccount.ts +2165 -0
  155. package/src/database/_generated/project/models/Terminal.ts +2038 -0
  156. package/src/database/_generated/project/models/TerminalSession.ts +1454 -0
  157. package/src/database/_generated/project/models/TerminalSessionLog.ts +1280 -0
  158. package/src/database/_generated/project/models/Trigger.ts +1430 -0
  159. package/src/database/_generated/project/models/UnlockMethod.ts +1220 -0
  160. package/src/database/_generated/project/models/UserCompositeViewport.ts +1280 -0
  161. package/src/database/_generated/project/models/UserProjectViewport.ts +1059 -0
  162. package/src/database/_generated/project/models/Worker.ts +1459 -0
  163. package/src/database/_generated/project/models/WorkerUnitRegistration.ts +1524 -0
  164. package/src/database/_generated/project/models/WorkerVersion.ts +1974 -0
  165. package/src/database/_generated/project/models/WorkerVersionLog.ts +1318 -0
  166. package/src/database/_generated/project/models.ts +35 -0
  167. package/src/database/_generated/project/pjtg.ts +182 -0
  168. package/src/database/abstractions.ts +19 -0
  169. package/src/database/factory.ts +37 -0
  170. package/src/database/index.ts +6 -0
  171. package/src/database/local/backend.ts +134 -0
  172. package/src/database/local/index.ts +3 -0
  173. package/src/database/local/meta.ts +46 -0
  174. package/src/database/local/prisma.config.ts +25 -0
  175. package/src/database/local/project.ts +39 -0
  176. package/src/database/manager.ts +181 -0
  177. package/src/database/migrate.ts +35 -0
  178. package/src/database/prisma.ts +56 -0
  179. package/src/database/well-known.ts +38 -0
  180. package/src/index.ts +4 -4
  181. package/src/library/abstractions.ts +3 -5
  182. package/src/library/factory.ts +1 -1
  183. package/src/library/local.ts +81 -26
  184. package/src/library/package-resolution-worker.ts +1 -1
  185. package/src/library/worker/evaluator.ts +40 -23
  186. package/src/library/worker/loader.lite.ts +1 -1
  187. package/src/library/worker/main.ts +3 -10
  188. package/src/library/worker/protocol.ts +0 -1
  189. package/src/lock/index.ts +0 -1
  190. package/src/lock/manager.ts +0 -10
  191. package/src/orchestrator/manager.ts +190 -104
  192. package/src/orchestrator/operation-context.ts +357 -0
  193. package/src/orchestrator/operation-plan.destroy.test.md +357 -0
  194. package/src/orchestrator/operation-plan.destroy.test.ts +775 -0
  195. package/src/orchestrator/operation-plan.fixtures.ts +213 -0
  196. package/src/orchestrator/operation-plan.md +198 -0
  197. package/src/orchestrator/operation-plan.refresh.test.md +199 -0
  198. package/src/orchestrator/operation-plan.refresh.test.ts +367 -0
  199. package/src/orchestrator/operation-plan.ts +709 -0
  200. package/src/orchestrator/operation-plan.update.test.md +485 -0
  201. package/src/orchestrator/operation-plan.update.test.ts +1066 -0
  202. package/src/orchestrator/operation-workset.ts +233 -578
  203. package/src/orchestrator/operation.ts +440 -948
  204. package/src/orchestrator/plan-test-builder.ts +267 -0
  205. package/src/project-model/abstractions.ts +118 -0
  206. package/src/project-model/backends/codebase.ts +365 -0
  207. package/src/project-model/backends/database.ts +440 -0
  208. package/src/project-model/errors.ts +81 -0
  209. package/src/project-model/factory.ts +24 -0
  210. package/src/project-model/index.ts +4 -0
  211. package/src/project-model/utils.test.ts +544 -0
  212. package/src/project-model/utils.ts +242 -0
  213. package/src/pubsub/abstractions.ts +10 -1
  214. package/src/pubsub/factory.ts +4 -4
  215. package/src/pubsub/index.ts +1 -0
  216. package/src/pubsub/manager.ts +29 -13
  217. package/src/pubsub/memory.ts +31 -0
  218. package/src/runner/abstractions.ts +40 -41
  219. package/src/runner/artifact-env.ts +19 -8
  220. package/src/runner/factory.ts +6 -6
  221. package/src/runner/force-abort.ts +3 -6
  222. package/src/runner/local.ts +74 -67
  223. package/src/runner/pulumi.ts +23 -63
  224. package/src/services.ts +181 -123
  225. package/src/shared/models/backend/index.ts +3 -1
  226. package/src/shared/models/backend/library.ts +9 -1
  227. package/src/shared/models/backend/project.ts +43 -42
  228. package/src/shared/models/backend/pulumi.ts +14 -0
  229. package/src/shared/models/backend/unlock-method.ts +1 -1
  230. package/src/shared/models/backend/well-known.ts +58 -0
  231. package/src/shared/models/base.ts +40 -26
  232. package/src/shared/models/errors.ts +82 -1
  233. package/src/shared/models/index.ts +3 -2
  234. package/src/shared/models/prisma.ts +36 -0
  235. package/src/shared/models/project/api-key.ts +37 -59
  236. package/src/shared/models/project/artifact.ts +16 -76
  237. package/src/shared/models/project/custom-status.ts +12 -0
  238. package/src/shared/models/project/index.ts +8 -7
  239. package/src/shared/models/project/lock.ts +10 -78
  240. package/src/shared/models/project/model.ts +19 -1
  241. package/src/shared/models/project/operation.ts +235 -99
  242. package/src/shared/models/project/page.ts +37 -48
  243. package/src/shared/models/project/secret.ts +29 -89
  244. package/src/shared/models/project/service-account.ts +12 -17
  245. package/src/shared/models/project/state.ts +100 -407
  246. package/src/shared/models/project/terminal.ts +75 -88
  247. package/src/shared/models/project/trigger.ts +13 -49
  248. package/src/shared/models/project/unlock-method.ts +20 -26
  249. package/src/shared/models/project/worker.ts +89 -90
  250. package/src/shared/resolvers/graph-resolver.ts +21 -0
  251. package/src/shared/resolvers/index.ts +1 -1
  252. package/src/shared/resolvers/input-hash.ts +24 -14
  253. package/src/shared/resolvers/input.ts +9 -2
  254. package/src/shared/resolvers/registry.ts +5 -4
  255. package/src/shared/resolvers/state.ts +12 -1
  256. package/src/shared/resolvers/validation.ts +7 -3
  257. package/src/shared/utils/index.ts +1 -2
  258. package/src/shared/utils/promise-tracker.ts +30 -3
  259. package/src/terminal/abstractions.ts +1 -1
  260. package/src/terminal/docker.ts +3 -3
  261. package/src/terminal/manager.ts +102 -118
  262. package/src/test-utils/database.ts +119 -0
  263. package/src/test-utils/index.ts +2 -0
  264. package/src/test-utils/services.ts +134 -0
  265. package/src/unlock/abstractions.ts +5 -23
  266. package/src/unlock/memory.ts +9 -14
  267. package/src/worker/abstractions.ts +7 -4
  268. package/src/worker/docker.ts +14 -19
  269. package/src/worker/manager.ts +366 -97
  270. package/dist/chunk-NAAIDR4U.js +0 -8499
  271. package/dist/chunk-NAAIDR4U.js.map +0 -1
  272. package/dist/chunk-Y7DXREVO.js +0 -1745
  273. package/dist/chunk-Y7DXREVO.js.map +0 -1
  274. package/dist/magic-string.es-5ABAC4JN.js +0 -1292
  275. package/dist/magic-string.es-5ABAC4JN.js.map +0 -1
  276. package/src/business/__traces__/secret/update-instance-secrets/create-and-delete-secrets-simultaneously.md +0 -356
  277. package/src/business/__traces__/secret/update-instance-secrets/create-new-secrets-for-instance.md +0 -274
  278. package/src/business/__traces__/secret/update-instance-secrets/delete-existing-secrets.md +0 -223
  279. package/src/business/__traces__/secret/update-instance-secrets/no-op-when-no-changes.md +0 -147
  280. package/src/business/__traces__/secret/update-instance-secrets/update-existing-secrets.md +0 -280
  281. package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration-when-other-exists.md +0 -360
  282. package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration.md +0 -215
  283. package/src/business/__traces__/worker/update-unit-registrations/create-multiple-workers-with-different-identities.md +0 -427
  284. package/src/business/__traces__/worker/update-unit-registrations/handle-nonexistent-registration-id-gracefully.md +0 -217
  285. package/src/business/__traces__/worker/update-unit-registrations/no-op-when-no-changes.md +0 -132
  286. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-changes.md +0 -454
  287. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-version-changes.md +0 -426
  288. package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-with-same-identity-reuses-service-account.md +0 -372
  289. package/src/business/__traces__/worker/update-unit-registrations/remove-one-of-multiple-unit-registrations.md +0 -383
  290. package/src/business/__traces__/worker/update-unit-registrations/remove-unit-registration.md +0 -245
  291. package/src/business/__traces__/worker/update-unit-registrations/update-existing-unit-registration-when-params-change.md +0 -174
  292. package/src/business/__traces__/worker/update-unit-registrations/update-params-and-image-simultaneously.md +0 -432
  293. package/src/business/__traces__/worker/update-unit-registrations/worker-with-multiple-registrations-not-deleted-when-one-removed.md +0 -220
  294. package/src/business/backend-unlock.ts +0 -10
  295. package/src/common/clock.ts +0 -18
  296. package/src/common/performance.ts +0 -44
  297. package/src/common/random.ts +0 -68
  298. package/src/common/test/index.ts +0 -2
  299. package/src/common/test/render.ts +0 -98
  300. package/src/common/test/tracer.ts +0 -359
  301. package/src/hotstate/abstractions.ts +0 -48
  302. package/src/hotstate/factory.ts +0 -17
  303. package/src/hotstate/index.ts +0 -3
  304. package/src/hotstate/manager.ts +0 -192
  305. package/src/hotstate/memory.ts +0 -100
  306. package/src/hotstate/validation.ts +0 -100
  307. package/src/lock/test.ts +0 -108
  308. package/src/project/abstractions.ts +0 -78
  309. package/src/project/evaluation.ts +0 -248
  310. package/src/project/factory.ts +0 -11
  311. package/src/project/index.ts +0 -3
  312. package/src/project/local.ts +0 -417
  313. package/src/pubsub/local.ts +0 -36
  314. package/src/pubsub/validation.ts +0 -33
  315. package/src/shared/utils/args.ts +0 -25
  316. package/src/state/abstractions.ts +0 -289
  317. package/src/state/encryption.ts +0 -98
  318. package/src/state/factory.ts +0 -20
  319. package/src/state/index.ts +0 -7
  320. package/src/state/local/backend.ts +0 -106
  321. package/src/state/local/collection.ts +0 -361
  322. package/src/state/local/index.ts +0 -2
  323. package/src/state/manager.ts +0 -890
  324. package/src/state/memory/backend.ts +0 -70
  325. package/src/state/memory/collection.ts +0 -270
  326. package/src/state/memory/index.ts +0 -2
  327. package/src/state/repository/index.ts +0 -2
  328. package/src/state/repository/repository.index.ts +0 -193
  329. package/src/state/repository/repository.ts +0 -507
  330. package/src/state/test.ts +0 -457
  331. /package/src/{state → database/local}/keyring.ts +0 -0
@@ -0,0 +1,544 @@
1
+ import type {
2
+ HubModel,
3
+ HubModelPatch,
4
+ InstanceInput,
5
+ InstanceModel,
6
+ InstanceModelPatch,
7
+ } from "@highstate/contract"
8
+ import { describe, expect, test } from "vitest"
9
+ import {
10
+ applyHubPatch,
11
+ applyInstancePatch,
12
+ cleanupHubReferences,
13
+ cleanupInstanceReferences,
14
+ deleteHubReferences,
15
+ deleteInstanceReferences,
16
+ renameInstanceReferences,
17
+ updateInstanceReferences,
18
+ } from "./utils"
19
+
20
+ describe("deleteInstanceReferences", () => {
21
+ test.concurrent("removes references to deleted instance from inputs", () => {
22
+ const inputs: Record<string, InstanceInput[]> = {
23
+ server: [
24
+ { instanceId: "server.v1:target", output: "endpoint" },
25
+ { instanceId: "server.v1:other", output: "endpoint" },
26
+ ],
27
+ database: [
28
+ { instanceId: "database.v1:main", output: "connectionString" },
29
+ { instanceId: "server.v1:target", output: "host" },
30
+ ],
31
+ }
32
+
33
+ deleteInstanceReferences(inputs, "server.v1:target")
34
+
35
+ expect(inputs).toEqual({
36
+ server: [{ instanceId: "server.v1:other", output: "endpoint" }],
37
+ database: [{ instanceId: "database.v1:main", output: "connectionString" }],
38
+ })
39
+ })
40
+
41
+ test.concurrent("removes empty input arrays", () => {
42
+ const inputs: Record<string, InstanceInput[]> = {
43
+ server: [{ instanceId: "server.v1:target", output: "endpoint" }],
44
+ database: [{ instanceId: "database.v1:main", output: "connectionString" }],
45
+ }
46
+
47
+ deleteInstanceReferences(inputs, "server.v1:target")
48
+
49
+ expect(inputs).toEqual({
50
+ database: [{ instanceId: "database.v1:main", output: "connectionString" }],
51
+ })
52
+ expect(inputs).not.toHaveProperty("server")
53
+ })
54
+ })
55
+
56
+ describe("deleteHubReferences", () => {
57
+ test.concurrent("removes references to deleted hub from hub inputs", () => {
58
+ const inputs = {
59
+ config: [{ hubId: "hub999" }, { hubId: "hub888" }],
60
+ secrets: [{ hubId: "hub456" }, { hubId: "hub999" }],
61
+ }
62
+
63
+ deleteHubReferences(inputs, "hub999")
64
+
65
+ expect(inputs).toEqual({
66
+ config: [{ hubId: "hub888" }],
67
+ secrets: [{ hubId: "hub456" }],
68
+ })
69
+ })
70
+
71
+ test.concurrent("removes empty input arrays", () => {
72
+ const inputs = {
73
+ config: [{ hubId: "hub999" }],
74
+ secrets: [{ hubId: "hub456" }],
75
+ }
76
+
77
+ deleteHubReferences(inputs, "hub999")
78
+
79
+ expect(inputs).toEqual({
80
+ secrets: [{ hubId: "hub456" }],
81
+ })
82
+ expect(inputs).not.toHaveProperty("config")
83
+ })
84
+ })
85
+
86
+ describe("renameInstanceReferences", () => {
87
+ test.concurrent("updates instance references to new ID", () => {
88
+ const inputs: InstanceInput[] = [
89
+ { instanceId: "server.v1:old", output: "endpoint" },
90
+ { instanceId: "server.v1:other", output: "endpoint" },
91
+ { instanceId: "server.v1:old", output: "host" },
92
+ ]
93
+
94
+ renameInstanceReferences(inputs, "server.v1:old", "server.v1:new")
95
+
96
+ expect(inputs).toEqual([
97
+ { instanceId: "server.v1:new", output: "endpoint" },
98
+ { instanceId: "server.v1:other", output: "endpoint" },
99
+ { instanceId: "server.v1:new", output: "host" },
100
+ ])
101
+ })
102
+
103
+ test.concurrent("does not modify unrelated references", () => {
104
+ const inputs: InstanceInput[] = [
105
+ { instanceId: "server.v1:other", output: "endpoint" },
106
+ { instanceId: "database.v1:main", output: "connection" },
107
+ ]
108
+
109
+ renameInstanceReferences(inputs, "server.v1:old", "server.v1:new")
110
+
111
+ expect(inputs).toEqual([
112
+ { instanceId: "server.v1:other", output: "endpoint" },
113
+ { instanceId: "database.v1:main", output: "connection" },
114
+ ])
115
+ })
116
+ })
117
+
118
+ describe("cleanupInstanceReferences", () => {
119
+ test.concurrent("removes instance references from instances and hubs", () => {
120
+ const instances: InstanceModel[] = [
121
+ {
122
+ id: "server.v1:web",
123
+ name: "web",
124
+ type: "server.v1",
125
+ kind: "unit",
126
+ inputs: {
127
+ database: [{ instanceId: "database.v1:target", output: "connection" }],
128
+ cache: [{ instanceId: "cache.v1:redis", output: "url" }],
129
+ },
130
+ },
131
+ {
132
+ id: "server.v1:api",
133
+ name: "api",
134
+ type: "server.v1",
135
+ kind: "unit",
136
+ inputs: {
137
+ database: [{ instanceId: "database.v1:target", output: "connection" }],
138
+ },
139
+ },
140
+ ]
141
+
142
+ const hubs: HubModel[] = [
143
+ {
144
+ id: "hub123",
145
+ inputs: [{ instanceId: "database.v1:target", output: "host" }],
146
+ },
147
+ ]
148
+
149
+ cleanupInstanceReferences(instances, hubs, "database.v1:target")
150
+
151
+ expect(instances[0].inputs).toEqual({
152
+ cache: [{ instanceId: "cache.v1:redis", output: "url" }],
153
+ })
154
+ expect(instances[1]).not.toHaveProperty("inputs")
155
+ expect(hubs[0]).not.toHaveProperty("inputs")
156
+ })
157
+
158
+ test.concurrent("handles instances with no inputs", () => {
159
+ const instances: InstanceModel[] = [
160
+ {
161
+ id: "server.v1:web",
162
+ name: "web",
163
+ type: "server.v1",
164
+ kind: "unit",
165
+ },
166
+ ]
167
+
168
+ const hubs: HubModel[] = []
169
+
170
+ expect(() => cleanupInstanceReferences(instances, hubs, "database.v1:target")).not.toThrow()
171
+ })
172
+ })
173
+
174
+ describe("cleanupHubReferences", () => {
175
+ test.concurrent("removes hub references from instances and hubs", () => {
176
+ const instances: InstanceModel[] = [
177
+ {
178
+ id: "server.v1:web",
179
+ name: "web",
180
+ type: "server.v1",
181
+ kind: "unit",
182
+ hubInputs: {
183
+ config: [{ hubId: "hub999" }],
184
+ secrets: [{ hubId: "hub456" }],
185
+ },
186
+ injectionInputs: [{ hubId: "hub999" }, { hubId: "hub789" }],
187
+ },
188
+ ]
189
+
190
+ const hubs: HubModel[] = [
191
+ {
192
+ id: "hub123",
193
+ injectionInputs: [{ hubId: "hub999" }, { hubId: "hub456" }],
194
+ },
195
+ ]
196
+
197
+ cleanupHubReferences(instances, hubs, "hub999")
198
+
199
+ expect(instances[0].hubInputs).toEqual({
200
+ secrets: [{ hubId: "hub456" }],
201
+ })
202
+ expect(instances[0].injectionInputs).toEqual([{ hubId: "hub789" }])
203
+ expect(hubs[0].injectionInputs).toEqual([{ hubId: "hub456" }])
204
+ })
205
+
206
+ test.concurrent("removes empty arrays and objects", () => {
207
+ const instances: InstanceModel[] = [
208
+ {
209
+ id: "server.v1:web",
210
+ name: "web",
211
+ type: "server.v1",
212
+ kind: "unit",
213
+ hubInputs: {
214
+ config: [{ hubId: "hub999" }],
215
+ },
216
+ injectionInputs: [{ hubId: "hub999" }],
217
+ },
218
+ ]
219
+
220
+ const hubs: HubModel[] = []
221
+
222
+ cleanupHubReferences(instances, hubs, "hub999")
223
+
224
+ expect(instances[0]).not.toHaveProperty("hubInputs")
225
+ expect(instances[0]).not.toHaveProperty("injectionInputs")
226
+ })
227
+ })
228
+
229
+ describe("updateInstanceReferences", () => {
230
+ test.concurrent("updates instance references across instances and hubs", () => {
231
+ const instances: InstanceModel[] = [
232
+ {
233
+ id: "server.v1:web",
234
+ name: "web",
235
+ type: "server.v1",
236
+ kind: "unit",
237
+ inputs: {
238
+ database: [{ instanceId: "database.v1:old", output: "connection" }],
239
+ },
240
+ },
241
+ ]
242
+
243
+ const hubs: HubModel[] = [
244
+ {
245
+ id: "hub123",
246
+ inputs: [{ instanceId: "database.v1:old", output: "host" }],
247
+ },
248
+ ]
249
+
250
+ updateInstanceReferences(instances, hubs, "database.v1:old", "database.v1:new")
251
+
252
+ expect(instances[0].inputs?.database).toEqual([
253
+ { instanceId: "database.v1:new", output: "connection" },
254
+ ])
255
+ expect(hubs[0].inputs).toEqual([{ instanceId: "database.v1:new", output: "host" }])
256
+ })
257
+ })
258
+
259
+ describe("applyInstancePatch", () => {
260
+ test.concurrent("applies args patch", () => {
261
+ const instance: InstanceModel = {
262
+ id: "server.v1:web",
263
+ name: "web",
264
+ type: "server.v1",
265
+ kind: "unit",
266
+ args: { port: 3000 },
267
+ }
268
+
269
+ const patch: InstanceModelPatch = {
270
+ args: { port: 8080, host: "0.0.0.0" },
271
+ }
272
+
273
+ applyInstancePatch(instance, patch)
274
+
275
+ expect(instance.args).toEqual({ port: 8080, host: "0.0.0.0" })
276
+ })
277
+
278
+ test.concurrent("applies position patch", () => {
279
+ const instance: InstanceModel = {
280
+ id: "server.v1:web",
281
+ name: "web",
282
+ type: "server.v1",
283
+ kind: "unit",
284
+ position: { x: 100, y: 200 },
285
+ }
286
+
287
+ const patch: InstanceModelPatch = {
288
+ position: { x: 300, y: 400 },
289
+ }
290
+
291
+ applyInstancePatch(instance, patch)
292
+
293
+ expect(instance.position).toEqual({ x: 300, y: 400 })
294
+ })
295
+
296
+ test.concurrent("applies inputs patch", () => {
297
+ const instance: InstanceModel = {
298
+ id: "server.v1:web",
299
+ name: "web",
300
+ type: "server.v1",
301
+ kind: "unit",
302
+ inputs: {
303
+ database: [{ instanceId: "database.v1:main", output: "connection" }],
304
+ },
305
+ }
306
+
307
+ const patch: InstanceModelPatch = {
308
+ inputs: {
309
+ cache: [{ instanceId: "cache.v1:redis", output: "url" }],
310
+ },
311
+ }
312
+
313
+ applyInstancePatch(instance, patch)
314
+
315
+ expect(instance.inputs).toEqual({
316
+ cache: [{ instanceId: "cache.v1:redis", output: "url" }],
317
+ })
318
+ })
319
+
320
+ test.concurrent("removes inputs when empty object provided", () => {
321
+ const instance: InstanceModel = {
322
+ id: "server.v1:web",
323
+ name: "web",
324
+ type: "server.v1",
325
+ kind: "unit",
326
+ inputs: {
327
+ database: [{ instanceId: "database.v1:main", output: "connection" }],
328
+ },
329
+ }
330
+
331
+ const patch: InstanceModelPatch = {
332
+ inputs: {},
333
+ }
334
+
335
+ applyInstancePatch(instance, patch)
336
+
337
+ expect(instance).not.toHaveProperty("inputs")
338
+ })
339
+
340
+ test.concurrent("applies hubInputs patch", () => {
341
+ const instance: InstanceModel = {
342
+ id: "server.v1:web",
343
+ name: "web",
344
+ type: "server.v1",
345
+ kind: "unit",
346
+ }
347
+
348
+ const patch: InstanceModelPatch = {
349
+ hubInputs: {
350
+ config: [{ hubId: "hub123" }],
351
+ },
352
+ }
353
+
354
+ applyInstancePatch(instance, patch)
355
+
356
+ expect(instance.hubInputs).toEqual({
357
+ config: [{ hubId: "hub123" }],
358
+ })
359
+ })
360
+
361
+ test.concurrent("removes hubInputs when empty object provided", () => {
362
+ const instance: InstanceModel = {
363
+ id: "server.v1:web",
364
+ name: "web",
365
+ type: "server.v1",
366
+ kind: "unit",
367
+ hubInputs: {
368
+ config: [{ hubId: "hub123" }],
369
+ },
370
+ }
371
+
372
+ const patch: InstanceModelPatch = {
373
+ hubInputs: {},
374
+ }
375
+
376
+ applyInstancePatch(instance, patch)
377
+
378
+ expect(instance).not.toHaveProperty("hubInputs")
379
+ })
380
+
381
+ test.concurrent("applies injectionInputs patch", () => {
382
+ const instance: InstanceModel = {
383
+ id: "server.v1:web",
384
+ name: "web",
385
+ type: "server.v1",
386
+ kind: "unit",
387
+ }
388
+
389
+ const patch: InstanceModelPatch = {
390
+ injectionInputs: [{ hubId: "hub123" }],
391
+ }
392
+
393
+ applyInstancePatch(instance, patch)
394
+
395
+ expect(instance.injectionInputs).toEqual([{ hubId: "hub123" }])
396
+ })
397
+
398
+ test.concurrent("removes injectionInputs when empty array provided", () => {
399
+ const instance: InstanceModel = {
400
+ id: "server.v1:web",
401
+ name: "web",
402
+ type: "server.v1",
403
+ kind: "unit",
404
+ injectionInputs: [{ hubId: "hub123" }],
405
+ }
406
+
407
+ const patch: InstanceModelPatch = {
408
+ injectionInputs: [],
409
+ }
410
+
411
+ applyInstancePatch(instance, patch)
412
+
413
+ expect(instance).not.toHaveProperty("injectionInputs")
414
+ })
415
+
416
+ test.concurrent("applies multiple patches at once", () => {
417
+ const instance: InstanceModel = {
418
+ id: "server.v1:web",
419
+ name: "web",
420
+ type: "server.v1",
421
+ kind: "unit",
422
+ args: { port: 3000 },
423
+ }
424
+
425
+ const patch: InstanceModelPatch = {
426
+ args: { port: 8080 },
427
+ position: { x: 100, y: 200 },
428
+ inputs: {
429
+ database: [{ instanceId: "database.v1:main", output: "connection" }],
430
+ },
431
+ }
432
+
433
+ applyInstancePatch(instance, patch)
434
+
435
+ expect(instance).toEqual({
436
+ id: "server.v1:web",
437
+ name: "web",
438
+ type: "server.v1",
439
+ kind: "unit",
440
+ args: { port: 8080 },
441
+ position: { x: 100, y: 200 },
442
+ inputs: {
443
+ database: [{ instanceId: "database.v1:main", output: "connection" }],
444
+ },
445
+ })
446
+ })
447
+ })
448
+
449
+ describe("applyHubPatch", () => {
450
+ test.concurrent("applies position patch", () => {
451
+ const hub: HubModel = {
452
+ id: "hub123",
453
+ position: { x: 100, y: 200 },
454
+ }
455
+
456
+ const patch: HubModelPatch = {
457
+ position: { x: 300, y: 400 },
458
+ }
459
+
460
+ applyHubPatch(hub, patch)
461
+
462
+ expect(hub.position).toEqual({ x: 300, y: 400 })
463
+ })
464
+
465
+ test.concurrent("applies inputs patch", () => {
466
+ const hub: HubModel = {
467
+ id: "hub123",
468
+ inputs: [{ instanceId: "database.v1:main", output: "host" }],
469
+ }
470
+
471
+ const patch: HubModelPatch = {
472
+ inputs: [{ instanceId: "server.v1:web", output: "endpoint" }],
473
+ }
474
+
475
+ applyHubPatch(hub, patch)
476
+
477
+ expect(hub.inputs).toEqual([{ instanceId: "server.v1:web", output: "endpoint" }])
478
+ })
479
+
480
+ test.concurrent("removes inputs when empty array provided", () => {
481
+ const hub: HubModel = {
482
+ id: "hub123",
483
+ inputs: [{ instanceId: "database.v1:main", output: "host" }],
484
+ }
485
+
486
+ const patch: HubModelPatch = {
487
+ inputs: [],
488
+ }
489
+
490
+ applyHubPatch(hub, patch)
491
+
492
+ expect(hub).not.toHaveProperty("inputs")
493
+ })
494
+
495
+ test.concurrent("applies injectionInputs patch", () => {
496
+ const hub: HubModel = {
497
+ id: "hub123",
498
+ }
499
+
500
+ const patch: HubModelPatch = {
501
+ injectionInputs: [{ hubId: "hub456" }],
502
+ }
503
+
504
+ applyHubPatch(hub, patch)
505
+
506
+ expect(hub.injectionInputs).toEqual([{ hubId: "hub456" }])
507
+ })
508
+
509
+ test.concurrent("removes injectionInputs when empty array provided", () => {
510
+ const hub: HubModel = {
511
+ id: "hub123",
512
+ injectionInputs: [{ hubId: "hub456" }],
513
+ }
514
+
515
+ const patch: HubModelPatch = {
516
+ injectionInputs: [],
517
+ }
518
+
519
+ applyHubPatch(hub, patch)
520
+
521
+ expect(hub).not.toHaveProperty("injectionInputs")
522
+ })
523
+
524
+ test.concurrent("applies multiple patches at once", () => {
525
+ const hub: HubModel = {
526
+ id: "hub123",
527
+ }
528
+
529
+ const patch: HubModelPatch = {
530
+ position: { x: 100, y: 200 },
531
+ inputs: [{ instanceId: "server.v1:web", output: "endpoint" }],
532
+ injectionInputs: [{ hubId: "hub456" }],
533
+ }
534
+
535
+ applyHubPatch(hub, patch)
536
+
537
+ expect(hub).toEqual({
538
+ id: "hub123",
539
+ position: { x: 100, y: 200 },
540
+ inputs: [{ instanceId: "server.v1:web", output: "endpoint" }],
541
+ injectionInputs: [{ hubId: "hub456" }],
542
+ })
543
+ })
544
+ })