@elench/testkit 0.1.65 → 0.1.66

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 (305) hide show
  1. package/lib/app/browser-bridge.mjs +66 -0
  2. package/lib/app/configs.mjs +81 -0
  3. package/lib/app/configs.test.mjs +34 -0
  4. package/lib/cli/command-helpers.mjs +2 -10
  5. package/lib/cli/commands/browser/serve.mjs +3 -62
  6. package/lib/cli/db.mjs +3 -68
  7. package/lib/config/binaries.mjs +34 -0
  8. package/lib/config/database.mjs +9 -6
  9. package/lib/config/index.mjs +2 -31
  10. package/lib/config/runtime.mjs +24 -95
  11. package/lib/config/validation.mjs +18 -62
  12. package/lib/coverage/backend-discovery.mjs +68 -85
  13. package/lib/coverage/backend-discovery.test.mjs +55 -46
  14. package/lib/coverage/graph-builder.mjs +5 -5
  15. package/lib/coverage/next-ir-to-graph.mjs +0 -1
  16. package/lib/coverage/routing.mjs +2 -29
  17. package/lib/coverage/routing.test.mjs +0 -16
  18. package/lib/coverage/shared.mjs +22 -82
  19. package/lib/database/fingerprint.mjs +1 -1
  20. package/lib/known-failures/github-cache.mjs +159 -0
  21. package/lib/known-failures/github-transport.mjs +174 -0
  22. package/lib/known-failures/github.mjs +17 -325
  23. package/lib/runner/default-runtime-runner.mjs +4 -10
  24. package/lib/runner/execution-config.mjs +12 -83
  25. package/lib/runner/live-run.mjs +45 -0
  26. package/lib/runner/managed-processes.mjs +29 -0
  27. package/lib/runner/orchestrator.mjs +57 -188
  28. package/lib/runner/playwright-runner.mjs +4 -11
  29. package/lib/runner/run-finalization.mjs +132 -0
  30. package/lib/runner/run-guards.mjs +45 -0
  31. package/lib/runner/runtime-preparation.mjs +1 -1
  32. package/lib/runner/services.mjs +3 -4
  33. package/lib/runner/template-steps.mjs +8 -45
  34. package/lib/runner/template.mjs +7 -28
  35. package/lib/shared/configured-steps.mjs +178 -0
  36. package/lib/shared/configured-steps.test.mjs +73 -0
  37. package/lib/shared/execution-schema.mjs +74 -0
  38. package/lib/shared/execution-schema.test.mjs +26 -0
  39. package/node_modules/@elench/next-analysis/dist/api-routes.d.ts +7 -0
  40. package/node_modules/@elench/next-analysis/dist/api-routes.d.ts.map +1 -0
  41. package/node_modules/@elench/next-analysis/dist/api-routes.js +66 -0
  42. package/node_modules/@elench/next-analysis/dist/api-routes.js.map +1 -0
  43. package/node_modules/@elench/next-analysis/dist/app-root.d.ts +2 -0
  44. package/node_modules/@elench/next-analysis/dist/app-root.d.ts.map +1 -0
  45. package/node_modules/@elench/next-analysis/dist/app-root.js +7 -0
  46. package/node_modules/@elench/next-analysis/dist/app-root.js.map +1 -0
  47. package/node_modules/@elench/next-analysis/dist/backend-links.d.ts +8 -0
  48. package/node_modules/@elench/next-analysis/dist/backend-links.d.ts.map +1 -0
  49. package/node_modules/@elench/next-analysis/dist/backend-links.js +30 -0
  50. package/node_modules/@elench/next-analysis/dist/backend-links.js.map +1 -0
  51. package/node_modules/@elench/next-analysis/dist/index.d.ts +11 -0
  52. package/node_modules/@elench/next-analysis/dist/index.d.ts.map +1 -0
  53. package/node_modules/@elench/next-analysis/dist/index.js +10 -0
  54. package/node_modules/@elench/next-analysis/dist/index.js.map +1 -0
  55. package/node_modules/@elench/next-analysis/dist/pages.d.ts +7 -0
  56. package/node_modules/@elench/next-analysis/dist/pages.d.ts.map +1 -0
  57. package/node_modules/@elench/next-analysis/dist/pages.js +47 -0
  58. package/node_modules/@elench/next-analysis/dist/pages.js.map +1 -0
  59. package/node_modules/@elench/next-analysis/dist/project.d.ts +3 -0
  60. package/node_modules/@elench/next-analysis/dist/project.d.ts.map +1 -0
  61. package/node_modules/@elench/next-analysis/dist/project.js +102 -0
  62. package/node_modules/@elench/next-analysis/dist/project.js.map +1 -0
  63. package/node_modules/@elench/next-analysis/dist/route-tree.d.ts +7 -0
  64. package/node_modules/@elench/next-analysis/dist/route-tree.d.ts.map +1 -0
  65. package/node_modules/@elench/next-analysis/dist/route-tree.js +575 -0
  66. package/node_modules/@elench/next-analysis/dist/route-tree.js.map +1 -0
  67. package/node_modules/@elench/next-analysis/dist/routes.d.ts +6 -0
  68. package/node_modules/@elench/next-analysis/dist/routes.d.ts.map +1 -0
  69. package/node_modules/@elench/next-analysis/dist/routes.js +41 -0
  70. package/node_modules/@elench/next-analysis/dist/routes.js.map +1 -0
  71. package/node_modules/@elench/next-analysis/dist/server-actions.d.ts +7 -0
  72. package/node_modules/@elench/next-analysis/dist/server-actions.d.ts.map +1 -0
  73. package/node_modules/@elench/next-analysis/dist/server-actions.js +37 -0
  74. package/node_modules/@elench/next-analysis/dist/server-actions.js.map +1 -0
  75. package/node_modules/@elench/next-analysis/dist/shared.d.ts +57 -0
  76. package/node_modules/@elench/next-analysis/dist/shared.d.ts.map +1 -0
  77. package/node_modules/@elench/next-analysis/dist/shared.js +229 -0
  78. package/node_modules/@elench/next-analysis/dist/shared.js.map +1 -0
  79. package/node_modules/@elench/next-analysis/dist/swc.d.ts +53 -0
  80. package/node_modules/@elench/next-analysis/dist/swc.d.ts.map +1 -0
  81. package/node_modules/@elench/next-analysis/dist/swc.js +387 -0
  82. package/node_modules/@elench/next-analysis/dist/swc.js.map +1 -0
  83. package/node_modules/@elench/next-analysis/dist/types.d.ts +125 -0
  84. package/node_modules/@elench/next-analysis/dist/types.d.ts.map +1 -0
  85. package/node_modules/@elench/next-analysis/dist/types.js +2 -0
  86. package/node_modules/@elench/next-analysis/dist/types.js.map +1 -0
  87. package/node_modules/@elench/next-analysis/package.json +15 -2
  88. package/node_modules/@elench/testkit-bridge/dist/index.d.ts +36 -0
  89. package/node_modules/@elench/testkit-bridge/dist/index.d.ts.map +1 -0
  90. package/node_modules/@elench/testkit-bridge/dist/index.js +538 -0
  91. package/node_modules/@elench/testkit-bridge/dist/index.js.map +1 -0
  92. package/node_modules/@elench/testkit-bridge/package.json +16 -5
  93. package/node_modules/@elench/testkit-protocol/dist/index.d.ts +190 -0
  94. package/node_modules/@elench/testkit-protocol/dist/index.d.ts.map +1 -0
  95. package/node_modules/@elench/testkit-protocol/dist/index.js +296 -0
  96. package/node_modules/@elench/testkit-protocol/dist/index.js.map +1 -0
  97. package/node_modules/@elench/testkit-protocol/package.json +14 -7
  98. package/node_modules/@elench/ts-analysis/dist/callables.d.ts +8 -0
  99. package/node_modules/@elench/ts-analysis/dist/callables.d.ts.map +1 -0
  100. package/node_modules/@elench/ts-analysis/dist/callables.js +126 -0
  101. package/node_modules/@elench/ts-analysis/dist/callables.js.map +1 -0
  102. package/node_modules/@elench/ts-analysis/dist/exports.d.ts +6 -0
  103. package/node_modules/@elench/ts-analysis/dist/exports.d.ts.map +1 -0
  104. package/node_modules/@elench/ts-analysis/dist/exports.js +70 -0
  105. package/node_modules/@elench/ts-analysis/dist/exports.js.map +1 -0
  106. package/node_modules/@elench/ts-analysis/dist/index.d.ts +10 -0
  107. package/node_modules/@elench/ts-analysis/dist/index.d.ts.map +1 -0
  108. package/node_modules/@elench/ts-analysis/{src/index.mjs → dist/index.js} +9 -14
  109. package/node_modules/@elench/ts-analysis/dist/index.js.map +1 -0
  110. package/node_modules/@elench/ts-analysis/dist/jsx.d.ts +9 -0
  111. package/node_modules/@elench/ts-analysis/dist/jsx.d.ts.map +1 -0
  112. package/node_modules/@elench/ts-analysis/dist/jsx.js +68 -0
  113. package/node_modules/@elench/ts-analysis/dist/jsx.js.map +1 -0
  114. package/node_modules/@elench/ts-analysis/dist/project.d.ts +5 -0
  115. package/node_modules/@elench/ts-analysis/dist/project.d.ts.map +1 -0
  116. package/node_modules/@elench/ts-analysis/dist/project.js +90 -0
  117. package/node_modules/@elench/ts-analysis/dist/project.js.map +1 -0
  118. package/node_modules/@elench/ts-analysis/dist/requests.d.ts +6 -0
  119. package/node_modules/@elench/ts-analysis/dist/requests.d.ts.map +1 -0
  120. package/node_modules/@elench/ts-analysis/dist/requests.js +140 -0
  121. package/node_modules/@elench/ts-analysis/dist/requests.js.map +1 -0
  122. package/node_modules/@elench/ts-analysis/dist/resolution.d.ts +4 -0
  123. package/node_modules/@elench/ts-analysis/dist/resolution.d.ts.map +1 -0
  124. package/node_modules/@elench/ts-analysis/dist/resolution.js +53 -0
  125. package/node_modules/@elench/ts-analysis/dist/resolution.js.map +1 -0
  126. package/node_modules/@elench/ts-analysis/dist/shared.d.ts +6 -0
  127. package/node_modules/@elench/ts-analysis/dist/shared.d.ts.map +1 -0
  128. package/node_modules/@elench/ts-analysis/dist/shared.js +31 -0
  129. package/node_modules/@elench/ts-analysis/dist/shared.js.map +1 -0
  130. package/node_modules/@elench/ts-analysis/dist/syntax.d.ts +7 -0
  131. package/node_modules/@elench/ts-analysis/dist/syntax.d.ts.map +1 -0
  132. package/node_modules/@elench/ts-analysis/dist/syntax.js +27 -0
  133. package/node_modules/@elench/ts-analysis/dist/syntax.js.map +1 -0
  134. package/node_modules/@elench/ts-analysis/dist/types.d.ts +58 -0
  135. package/node_modules/@elench/ts-analysis/dist/types.d.ts.map +1 -0
  136. package/node_modules/@elench/ts-analysis/dist/types.js +2 -0
  137. package/node_modules/@elench/ts-analysis/dist/types.js.map +1 -0
  138. package/node_modules/@elench/ts-analysis/package.json +18 -2
  139. package/node_modules/typescript/LICENSE.txt +55 -0
  140. package/node_modules/typescript/README.md +50 -0
  141. package/node_modules/typescript/SECURITY.md +41 -0
  142. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  143. package/node_modules/typescript/bin/tsc +2 -0
  144. package/node_modules/typescript/bin/tsserver +2 -0
  145. package/node_modules/typescript/lib/_tsc.js +133818 -0
  146. package/node_modules/typescript/lib/_tsserver.js +659 -0
  147. package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  148. package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  149. package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  150. package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  151. package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  152. package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  153. package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  154. package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  155. package/node_modules/typescript/lib/lib.d.ts +22 -0
  156. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  157. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  158. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  159. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  160. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  161. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  162. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  163. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  164. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  165. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  166. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  167. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  168. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  169. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  170. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  171. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  172. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  173. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  174. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  175. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  176. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  177. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  178. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  179. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  180. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  181. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  182. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  183. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  184. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  185. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  186. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  187. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  188. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  189. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  190. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  191. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  192. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  193. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  194. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  195. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  196. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  197. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  198. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  199. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  200. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  201. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  202. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  203. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  204. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  205. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  206. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  207. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  208. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  209. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  210. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  211. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  212. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  213. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  214. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  215. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  216. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  217. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  218. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  219. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  220. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  221. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  222. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  223. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  224. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  225. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  226. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  227. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  228. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  229. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  230. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  231. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  232. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  233. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  234. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  235. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  236. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  237. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  238. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  239. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  240. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  241. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  242. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  243. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  244. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  245. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  246. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  247. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  248. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  249. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  250. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  251. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  252. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  253. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  254. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  255. package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  256. package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  257. package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  258. package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  259. package/node_modules/typescript/lib/tsc.js +8 -0
  260. package/node_modules/typescript/lib/tsserver.js +8 -0
  261. package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  262. package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  263. package/node_modules/typescript/lib/typesMap.json +497 -0
  264. package/node_modules/typescript/lib/typescript.d.ts +11437 -0
  265. package/node_modules/typescript/lib/typescript.js +200276 -0
  266. package/node_modules/typescript/lib/typingsInstaller.js +8 -0
  267. package/node_modules/typescript/lib/watchGuard.js +53 -0
  268. package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  269. package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  270. package/node_modules/typescript/package.json +120 -0
  271. package/package.json +12 -9
  272. package/lib/coverage/fs-walk.mjs +0 -64
  273. package/node_modules/@elench/next-analysis/src/api-routes.mjs +0 -81
  274. package/node_modules/@elench/next-analysis/src/api-routes.test.mjs +0 -22
  275. package/node_modules/@elench/next-analysis/src/app-root.mjs +0 -7
  276. package/node_modules/@elench/next-analysis/src/backend-links.mjs +0 -31
  277. package/node_modules/@elench/next-analysis/src/index.mjs +0 -21
  278. package/node_modules/@elench/next-analysis/src/pages.mjs +0 -68
  279. package/node_modules/@elench/next-analysis/src/project.mjs +0 -94
  280. package/node_modules/@elench/next-analysis/src/project.test.mjs +0 -35
  281. package/node_modules/@elench/next-analysis/src/route-tree.mjs +0 -621
  282. package/node_modules/@elench/next-analysis/src/routes.mjs +0 -41
  283. package/node_modules/@elench/next-analysis/src/routes.test.mjs +0 -25
  284. package/node_modules/@elench/next-analysis/src/server-actions.mjs +0 -53
  285. package/node_modules/@elench/next-analysis/src/server-actions.test.mjs +0 -37
  286. package/node_modules/@elench/next-analysis/src/shared.mjs +0 -209
  287. package/node_modules/@elench/next-analysis/src/swc.mjs +0 -388
  288. package/node_modules/@elench/testkit-bridge/src/index.mjs +0 -583
  289. package/node_modules/@elench/testkit-bridge/src/index.test.mjs +0 -409
  290. package/node_modules/@elench/testkit-protocol/src/index.d.ts +0 -231
  291. package/node_modules/@elench/testkit-protocol/src/index.mjs +0 -265
  292. package/node_modules/@elench/testkit-protocol/src/index.test.mjs +0 -242
  293. package/node_modules/@elench/ts-analysis/src/callables.mjs +0 -135
  294. package/node_modules/@elench/ts-analysis/src/callables.test.mjs +0 -55
  295. package/node_modules/@elench/ts-analysis/src/exports.mjs +0 -69
  296. package/node_modules/@elench/ts-analysis/src/exports.test.mjs +0 -50
  297. package/node_modules/@elench/ts-analysis/src/jsx.mjs +0 -69
  298. package/node_modules/@elench/ts-analysis/src/jsx.test.mjs +0 -43
  299. package/node_modules/@elench/ts-analysis/src/project.mjs +0 -100
  300. package/node_modules/@elench/ts-analysis/src/project.test.mjs +0 -54
  301. package/node_modules/@elench/ts-analysis/src/requests.mjs +0 -141
  302. package/node_modules/@elench/ts-analysis/src/requests.test.mjs +0 -35
  303. package/node_modules/@elench/ts-analysis/src/resolution.mjs +0 -53
  304. package/node_modules/@elench/ts-analysis/src/shared.mjs +0 -32
  305. package/node_modules/@elench/ts-analysis/src/syntax.mjs +0 -27
@@ -0,0 +1,132 @@
1
+ import { buildRunArtifact, buildStatusArtifact } from "./reporting.mjs";
2
+ import { applyKnownFailureIssueValidationToArtifacts, applyKnownFailuresToArtifacts } from "./triage.mjs";
3
+ import { writeRunArtifact, writeStatusArtifact } from "./artifacts.mjs";
4
+ import { summarizeDbBackend } from "./results.mjs";
5
+ import { formatError } from "./formatting.mjs";
6
+ import { uploadTelemetryArtifact } from "../telemetry/index.mjs";
7
+ import { loadHistory, saveHistory, updateHistoryFromRunArtifact } from "../history/index.mjs";
8
+ import { shouldFailKnownFailureIssueValidation, validateKnownFailureIssues } from "../known-failures/github.mjs";
9
+
10
+ export async function finalizeRunArtifacts({
11
+ productDir,
12
+ results,
13
+ startedAt,
14
+ finishedAt,
15
+ execution,
16
+ workerCount,
17
+ runtimeInstanceCount,
18
+ runtimeStats,
19
+ selection,
20
+ metadata,
21
+ logRegistry,
22
+ setupRegistry,
23
+ knownFailures,
24
+ issueValidationConfig,
25
+ telemetry,
26
+ reporter,
27
+ writeStatus,
28
+ }) {
29
+ const runArtifact = buildRunArtifact({
30
+ productDir,
31
+ results,
32
+ startedAt,
33
+ finishedAt,
34
+ execution,
35
+ workerCount,
36
+ runtimeInstanceCount,
37
+ runtimeStats,
38
+ typeValues: selection.typeValues,
39
+ suiteSelectors: selection.suiteSelectors,
40
+ fileNames: selection.fileNames,
41
+ shard: selection.shard,
42
+ serviceFilter: selection.serviceFilter,
43
+ scenarioSeed: selection.scenarioSeed,
44
+ metadata,
45
+ summarizeDbBackend,
46
+ serviceLogs: logRegistry.listServiceLogs(),
47
+ setupLogs: logRegistry.listSetupLogs(),
48
+ setupOperations: setupRegistry.listOperations(),
49
+ });
50
+ const statusArtifact = writeStatus
51
+ ? buildStatusArtifact({
52
+ productDir,
53
+ results,
54
+ typeValues: selection.typeValues,
55
+ suiteSelectors: selection.suiteSelectors,
56
+ fileNames: selection.fileNames,
57
+ shard: selection.shard,
58
+ serviceFilter: selection.serviceFilter,
59
+ scenarioSeed: selection.scenarioSeed,
60
+ metadata,
61
+ })
62
+ : null;
63
+ const enrichedArtifacts = applyKnownFailuresToArtifacts(runArtifact, statusArtifact, knownFailures);
64
+ const knownFailureIssueValidation = await validateKnownFailureIssues({
65
+ productDir,
66
+ document: knownFailures,
67
+ runArtifact: enrichedArtifacts.runArtifact,
68
+ statusArtifact: enrichedArtifacts.statusArtifact,
69
+ config: issueValidationConfig,
70
+ gitMetadata: metadata.git,
71
+ });
72
+ applyKnownFailureIssueValidationToArtifacts(
73
+ enrichedArtifacts.runArtifact,
74
+ enrichedArtifacts.statusArtifact,
75
+ knownFailureIssueValidation
76
+ );
77
+ attachKnownFailureIssueValidation(
78
+ enrichedArtifacts.runArtifact,
79
+ enrichedArtifacts.statusArtifact,
80
+ knownFailureIssueValidation
81
+ );
82
+
83
+ writeRunArtifact(productDir, enrichedArtifacts.runArtifact);
84
+ if (writeStatus) {
85
+ writeStatusArtifact(productDir, enrichedArtifacts.statusArtifact);
86
+ }
87
+ const nextHistory = updateHistoryFromRunArtifact(
88
+ loadHistory(productDir),
89
+ enrichedArtifacts.runArtifact,
90
+ enrichedArtifacts.runArtifact.generatedAt
91
+ );
92
+ saveHistory(productDir, nextHistory);
93
+
94
+ reporter?.runSummary?.(results, finishedAt - startedAt, knownFailureIssueValidation);
95
+ await reportTelemetry(telemetry, enrichedArtifacts.runArtifact, reporter);
96
+
97
+ return {
98
+ runArtifact: enrichedArtifacts.runArtifact,
99
+ statusArtifact: enrichedArtifacts.statusArtifact,
100
+ knownFailureIssueValidation,
101
+ shouldFailIssueValidation: shouldFailKnownFailureIssueValidation(knownFailureIssueValidation),
102
+ };
103
+ }
104
+
105
+ async function reportTelemetry(telemetry, artifact, reporter = null) {
106
+ if (!telemetry?.enabled) return;
107
+
108
+ try {
109
+ const outcome = await uploadTelemetryArtifact(telemetry, artifact);
110
+ if (outcome?.ok) {
111
+ reporter?.telemetry?.("Telemetry: uploaded run artifact");
112
+ return;
113
+ }
114
+ if (outcome?.reason === "missing-token") {
115
+ reporter?.telemetry?.(
116
+ `Telemetry: skipped upload because ${telemetry.tokenEnv || "configured token env"} is not set`
117
+ );
118
+ return;
119
+ }
120
+ if (outcome?.reason && !outcome.skipped) return;
121
+ } catch (error) {
122
+ reporter?.telemetry?.(`Telemetry: upload failed (${formatError(error)})`);
123
+ }
124
+ }
125
+
126
+ function attachKnownFailureIssueValidation(runArtifact, statusArtifact, validation) {
127
+ if (!validation) return;
128
+ runArtifact.knownFailuresIssueValidation = validation;
129
+ if (statusArtifact) {
130
+ statusArtifact.knownFailuresIssueValidation = validation;
131
+ }
132
+ }
@@ -0,0 +1,45 @@
1
+ import { collectSuites } from "./planning.mjs";
2
+ import { findUnmatchedRequestedFiles, isFullRunSelection } from "./selection.mjs";
3
+
4
+ export function ensureRequestedFilesMatch(configs, typeValues, suiteSelectors, requestedFiles = []) {
5
+ if (requestedFiles.length === 0) return;
6
+ const unmatchedFiles = findUnmatchedRequestedFiles(
7
+ configs,
8
+ typeValues,
9
+ suiteSelectors,
10
+ requestedFiles,
11
+ collectSuites,
12
+ normalizePathSeparators
13
+ );
14
+ if (unmatchedFiles.length === 0) return;
15
+
16
+ throw new Error(
17
+ `Requested file${unmatchedFiles.length === 1 ? "" : "s"} did not match any selected suites:\n` +
18
+ unmatchedFiles.map((file) => `- ${file}`).join("\n")
19
+ );
20
+ }
21
+
22
+ export function ensureStatusWriteAllowed(opts, typeValues, suiteSelectors, requestedFiles = []) {
23
+ if (
24
+ !opts.writeStatus ||
25
+ opts.allowPartialStatus ||
26
+ isFullRunSelection(
27
+ typeValues,
28
+ suiteSelectors,
29
+ requestedFiles,
30
+ opts.shard || null,
31
+ opts.serviceFilter || null
32
+ )
33
+ ) {
34
+ return;
35
+ }
36
+
37
+ throw new Error(
38
+ "Refusing to overwrite testkit.status.json from a filtered run. " +
39
+ "Run the full suite with --write-status, or pass --allow-partial-status to opt in."
40
+ );
41
+ }
42
+
43
+ function normalizePathSeparators(filePath) {
44
+ return filePath.split("\\").join("/");
45
+ }
@@ -1,7 +1,7 @@
1
1
  import crypto from "crypto";
2
2
  import fs from "fs";
3
3
  import path from "path";
4
- import { resolveServiceCwd } from "../config/index.mjs";
4
+ import { resolveServiceCwd } from "../config/paths.mjs";
5
5
  import { appendFileToHash, appendInputToHash } from "../database/fingerprint.mjs";
6
6
  import { announceResolvedToolchain, resolveConfiguredToolchain } from "../toolchains/index.mjs";
7
7
  import { readDatabaseUrl } from "./state-io.mjs";
@@ -1,9 +1,10 @@
1
- import { resolveServiceCwd } from "../config/index.mjs";
1
+ import { resolveServiceCwd } from "../config/paths.mjs";
2
2
  import {
3
3
  announceResolvedToolchain,
4
4
  applyToolchainEnv,
5
5
  resolveConfiguredToolchain,
6
6
  } from "../toolchains/index.mjs";
7
+ import { registerManagedService } from "./managed-processes.mjs";
7
8
  import { buildExecutionEnv, numericPortFromUrl } from "./template.mjs";
8
9
  import { DEFAULT_READY_TIMEOUT_MS, assertLocalServicePortsAvailable, isPortInUse, waitForReady } from "./readiness.mjs";
9
10
  import { captureOutput, killChildProcess, startDetachedCommand, stopChildProcess, sleep } from "./processes.mjs";
@@ -70,9 +71,7 @@ export async function startLocalService(config, lifecycle, options = {}) {
70
71
  },
71
72
  }),
72
73
  ];
73
- lifecycle.registerService(config, child, cwd, () => {
74
- killChildProcess(child, "SIGTERM");
75
- });
74
+ registerManagedService(lifecycle, config, child, cwd, "SIGTERM");
76
75
 
77
76
  const readyTimeoutMs = config.testkit.local.readyTimeoutMs || DEFAULT_READY_TIMEOUT_MS;
78
77
 
@@ -4,7 +4,14 @@ import path from "path";
4
4
  import { build } from "esbuild";
5
5
  import { execa, execaCommand } from "execa";
6
6
  import { fileURLToPath } from "url";
7
- import { resolveServiceCwd } from "../config/index.mjs";
7
+ import {
8
+ collectConfiguredInputs,
9
+ parseModuleSpecifier,
10
+ resolveConfiguredCwd,
11
+ resolveConfiguredPath,
12
+ summarizeConfiguredStep,
13
+ } from "../shared/configured-steps.mjs";
14
+ export { collectConfiguredInputs, parseModuleSpecifier, resolveConfiguredCwd, resolveConfiguredPath } from "../shared/configured-steps.mjs";
8
15
  import {
9
16
  announceResolvedToolchain,
10
17
  applyToolchainEnv,
@@ -72,35 +79,6 @@ export async function runConfiguredSteps({
72
79
  }
73
80
  }
74
81
 
75
- export function collectConfiguredInputs(productDir, { inputs = [], steps = [] } = {}) {
76
- const collected = new Set();
77
- for (const input of inputs) {
78
- collected.add(resolveConfiguredPath(productDir, null, input));
79
- }
80
- for (const step of steps) {
81
- if (step.kind === "sql-file") {
82
- collected.add(resolveConfiguredPath(productDir, step.cwd, step.path));
83
- }
84
- if (step.kind === "module") {
85
- collected.add(
86
- resolveConfiguredPath(productDir, step.cwd, parseModuleSpecifier(step.specifier).modulePath)
87
- );
88
- }
89
- for (const input of step.inputs || []) {
90
- collected.add(resolveConfiguredPath(productDir, step.cwd, input));
91
- }
92
- }
93
- return [...collected].sort();
94
- }
95
-
96
- export function resolveConfiguredCwd(productDir, stepCwd) {
97
- return resolveServiceCwd(productDir, stepCwd || ".");
98
- }
99
-
100
- export function resolveConfiguredPath(productDir, stepCwd, targetPath) {
101
- return path.resolve(resolveConfiguredCwd(productDir, stepCwd), targetPath);
102
- }
103
-
104
82
  async function runConfiguredStep(config, step, env, resolvedToolchain, options = {}) {
105
83
  const runtimeEnv = applyToolchainEnv(env, resolvedToolchain);
106
84
  const cwd = resolveConfiguredCwd(config.productDir, step.cwd);
@@ -253,21 +231,6 @@ function resolvePackageSubpath(specifier) {
253
231
  throw new Error(`Unsupported @elench/testkit import "${specifier}" while loading template step`);
254
232
  }
255
233
 
256
- function parseModuleSpecifier(specifier) {
257
- const [modulePath, exportName] = String(specifier).split("#", 2);
258
- return {
259
- modulePath,
260
- exportName: exportName || "default",
261
- };
262
- }
263
-
264
- function summarizeConfiguredStep(step) {
265
- if (step.kind === "command") return `command: ${String(step.cmd).trim()}`;
266
- if (step.kind === "sql-file") return `sql: ${step.path}`;
267
- if (step.kind === "module") return `module: ${step.specifier}`;
268
- return step.kind;
269
- }
270
-
271
234
  async function awaitCapturedProcess(child, { livePrefix = "", liveWriter = null, logRecord = null } = {}) {
272
235
  const drains = [
273
236
  captureProcessOutput(child.stdout, "stdout", livePrefix, liveWriter, logRecord),
@@ -1,4 +1,5 @@
1
1
  import path from "path";
2
+ import { finalizeConfiguredInputs, finalizeConfiguredSteps } from "../shared/configured-steps.mjs";
2
3
  import { readDatabaseInfo } from "./state-io.mjs";
3
4
 
4
5
  const PORT_STRIDE = 100;
@@ -183,22 +184,11 @@ function finalizeDatabaseTemplate(template, context) {
183
184
  };
184
185
  }
185
186
 
186
- const finalizeStep = (step) => ({
187
- ...step,
188
- ...(typeof step.cmd === "string" ? { cmd: finalizeString(step.cmd, context) } : {}),
189
- ...(typeof step.cwd === "string" ? { cwd: finalizeString(step.cwd, context) } : {}),
190
- ...(typeof step.path === "string" ? { path: finalizeString(step.path, context) } : {}),
191
- ...(typeof step.specifier === "string"
192
- ? { specifier: finalizeString(step.specifier, context) }
193
- : {}),
194
- inputs: (step.inputs || []).map((input) => finalizeString(input, context)),
195
- });
196
-
197
187
  return {
198
- inputs: (template.inputs || []).map((input) => finalizeString(input, context)),
199
- migrate: (template.migrate || []).map(finalizeStep),
200
- seed: (template.seed || []).map(finalizeStep),
201
- verify: (template.verify || []).map(finalizeStep),
188
+ inputs: finalizeConfiguredInputs(template.inputs || [], (value) => finalizeString(value, context)),
189
+ migrate: finalizeConfiguredSteps(template.migrate || [], (value) => finalizeString(value, context)),
190
+ seed: finalizeConfiguredSteps(template.seed || [], (value) => finalizeString(value, context)),
191
+ verify: finalizeConfiguredSteps(template.verify || [], (value) => finalizeString(value, context)),
202
192
  };
203
193
  }
204
194
 
@@ -356,20 +346,9 @@ function finalizeRuntimePrepare(prepare, context) {
356
346
  };
357
347
  }
358
348
 
359
- const finalizeStep = (step) => ({
360
- ...step,
361
- ...(typeof step.cmd === "string" ? { cmd: finalizeString(step.cmd, context) } : {}),
362
- ...(typeof step.cwd === "string" ? { cwd: finalizeString(step.cwd, context) } : {}),
363
- ...(typeof step.path === "string" ? { path: finalizeString(step.path, context) } : {}),
364
- ...(typeof step.specifier === "string"
365
- ? { specifier: finalizeString(step.specifier, context) }
366
- : {}),
367
- inputs: (step.inputs || []).map((input) => finalizeString(input, context)),
368
- });
369
-
370
349
  return {
371
- inputs: (prepare.inputs || []).map((input) => finalizeString(input, context)),
372
- steps: (prepare.steps || []).map(finalizeStep),
350
+ inputs: finalizeConfiguredInputs(prepare.inputs || [], (value) => finalizeString(value, context)),
351
+ steps: finalizeConfiguredSteps(prepare.steps || [], (value) => finalizeString(value, context)),
373
352
  };
374
353
  }
375
354
 
@@ -0,0 +1,178 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ export function normalizeOptionalString(value) {
5
+ if (typeof value !== "string") return null;
6
+ const normalized = value.trim();
7
+ return normalized.length > 0 ? normalized : null;
8
+ }
9
+
10
+ export function normalizeConfiguredInputs(value, label) {
11
+ if (value == null) return [];
12
+ if (!Array.isArray(value)) {
13
+ throw new Error(`${label}.inputs must be an array`);
14
+ }
15
+
16
+ return value.map((entry, index) => {
17
+ const normalized = normalizeOptionalString(entry);
18
+ if (!normalized) {
19
+ throw new Error(`${label}.inputs[${index}] must be a non-empty string`);
20
+ }
21
+ return normalized;
22
+ });
23
+ }
24
+
25
+ export function normalizeConfiguredStepInputs(value, label) {
26
+ if (value == null) return [];
27
+ if (!Array.isArray(value)) {
28
+ throw new Error(`${label}.inputs must be an array`);
29
+ }
30
+
31
+ return value.map((entry, index) => {
32
+ const normalized = normalizeOptionalString(entry);
33
+ if (!normalized) {
34
+ throw new Error(`${label}.inputs[${index}] must be a non-empty string`);
35
+ }
36
+ return normalized;
37
+ });
38
+ }
39
+
40
+ export function normalizeConfiguredSteps(value, label) {
41
+ if (value == null) return [];
42
+ if (!Array.isArray(value)) {
43
+ throw new Error(`${label} must be an array`);
44
+ }
45
+
46
+ return value.map((step, index) => normalizeConfiguredStep(step, `${label}[${index}]`));
47
+ }
48
+
49
+ export function normalizeConfiguredStep(step, label) {
50
+ if (!step || typeof step !== "object") {
51
+ throw new Error(`${label} must be an object`);
52
+ }
53
+
54
+ const kind = normalizeOptionalString(step.kind);
55
+ if (kind === "command") {
56
+ const cmd = normalizeOptionalString(step.cmd);
57
+ if (!cmd) throw new Error(`${label}.cmd must be a non-empty string`);
58
+ return {
59
+ kind,
60
+ cmd,
61
+ cwd: normalizeOptionalString(step.cwd),
62
+ inputs: normalizeConfiguredStepInputs(step.inputs, label),
63
+ };
64
+ }
65
+ if (kind === "sql-file") {
66
+ const filePath = normalizeOptionalString(step.path);
67
+ if (!filePath) throw new Error(`${label}.path must be a non-empty string`);
68
+ return {
69
+ kind,
70
+ path: filePath,
71
+ cwd: normalizeOptionalString(step.cwd),
72
+ inputs: normalizeConfiguredStepInputs(step.inputs, label),
73
+ };
74
+ }
75
+ if (kind === "module") {
76
+ const specifier = normalizeOptionalString(step.specifier);
77
+ if (!specifier) throw new Error(`${label}.specifier must be a non-empty string`);
78
+ return {
79
+ kind,
80
+ specifier,
81
+ cwd: normalizeOptionalString(step.cwd),
82
+ inputs: normalizeConfiguredStepInputs(step.inputs, label),
83
+ };
84
+ }
85
+
86
+ throw new Error(`${label}.kind must be one of: command, sql-file, module`);
87
+ }
88
+
89
+ export function parseModuleSpecifier(specifier) {
90
+ const [modulePath, exportName] = String(specifier).split("#", 2);
91
+ return {
92
+ modulePath,
93
+ exportName: exportName || "default",
94
+ };
95
+ }
96
+
97
+ export function resolveConfiguredCwd(productDir, stepCwd) {
98
+ return path.resolve(productDir, stepCwd || ".");
99
+ }
100
+
101
+ export function resolveConfiguredPath(productDir, stepCwd, targetPath) {
102
+ return path.resolve(resolveConfiguredCwd(productDir, stepCwd), targetPath);
103
+ }
104
+
105
+ export function collectConfiguredInputs(productDir, { inputs = [], steps = [] } = {}) {
106
+ const collected = new Set();
107
+ for (const input of inputs) {
108
+ collected.add(resolveConfiguredPath(productDir, null, input));
109
+ }
110
+ for (const step of steps) {
111
+ if (step.kind === "sql-file") {
112
+ collected.add(resolveConfiguredPath(productDir, step.cwd, step.path));
113
+ }
114
+ if (step.kind === "module") {
115
+ collected.add(resolveConfiguredPath(productDir, step.cwd, parseModuleSpecifier(step.specifier).modulePath));
116
+ }
117
+ for (const input of step.inputs || []) {
118
+ collected.add(resolveConfiguredPath(productDir, step.cwd, input));
119
+ }
120
+ }
121
+ return [...collected].sort();
122
+ }
123
+
124
+ export function summarizeConfiguredStep(step) {
125
+ if (step.kind === "command") return `command: ${String(step.cmd).trim()}`;
126
+ if (step.kind === "sql-file") return `sql: ${step.path}`;
127
+ if (step.kind === "module") return `module: ${step.specifier}`;
128
+ return step.kind;
129
+ }
130
+
131
+ export function finalizeConfiguredInputs(inputs = [], transform) {
132
+ return inputs.map((input) => transform(input));
133
+ }
134
+
135
+ export function finalizeConfiguredStep(step, transform) {
136
+ return {
137
+ ...step,
138
+ ...(typeof step.cmd === "string" ? { cmd: transform(step.cmd) } : {}),
139
+ ...(typeof step.cwd === "string" ? { cwd: transform(step.cwd) } : {}),
140
+ ...(typeof step.path === "string" ? { path: transform(step.path) } : {}),
141
+ ...(typeof step.specifier === "string" ? { specifier: transform(step.specifier) } : {}),
142
+ inputs: finalizeConfiguredInputs(step.inputs || [], transform),
143
+ };
144
+ }
145
+
146
+ export function finalizeConfiguredSteps(steps = [], transform) {
147
+ return steps.map((step) => finalizeConfiguredStep(step, transform));
148
+ }
149
+
150
+ export function validateConfiguredCollection({ productDir, label, inputs = [], steps = [] }) {
151
+ for (const input of inputs) {
152
+ ensureExistingPath(resolveConfiguredPath(productDir, null, input), `${label} input`);
153
+ }
154
+
155
+ for (const step of steps) {
156
+ if (step.cwd) {
157
+ ensureExistingPath(resolveConfiguredCwd(productDir, step.cwd), `${label} step cwd`);
158
+ }
159
+ if (step.kind === "sql-file") {
160
+ ensureExistingPath(resolveConfiguredPath(productDir, step.cwd, step.path), `${label} sql file`);
161
+ }
162
+ if (step.kind === "module") {
163
+ ensureExistingPath(
164
+ resolveConfiguredPath(productDir, step.cwd, parseModuleSpecifier(step.specifier).modulePath),
165
+ `${label} module`
166
+ );
167
+ }
168
+ for (const input of step.inputs || []) {
169
+ ensureExistingPath(resolveConfiguredPath(productDir, step.cwd, input), `${label} step input`);
170
+ }
171
+ }
172
+ }
173
+
174
+ function ensureExistingPath(absolutePath, label) {
175
+ if (!fs.existsSync(absolutePath)) {
176
+ throw new Error(`${label} does not exist: ${absolutePath}`);
177
+ }
178
+ }
@@ -0,0 +1,73 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import {
6
+ collectConfiguredInputs,
7
+ finalizeConfiguredStep,
8
+ normalizeConfiguredStep,
9
+ parseModuleSpecifier,
10
+ validateConfiguredCollection,
11
+ } from "./configured-steps.mjs";
12
+
13
+ const tempDirs = [];
14
+
15
+ afterEach(() => {
16
+ for (const dir of tempDirs.splice(0)) {
17
+ fs.rmSync(dir, { recursive: true, force: true });
18
+ }
19
+ });
20
+
21
+ describe("shared configured steps", () => {
22
+ it("normalizes and finalizes configured steps", () => {
23
+ const normalized = normalizeConfiguredStep(
24
+ { kind: "module", specifier: "./seed.mjs#run", cwd: "db", inputs: ["schema.sql"] },
25
+ 'Service "api" database.template.seed[0]'
26
+ );
27
+
28
+ expect(normalized).toEqual({
29
+ kind: "module",
30
+ specifier: "./seed.mjs#run",
31
+ cwd: "db",
32
+ inputs: ["schema.sql"],
33
+ });
34
+ expect(parseModuleSpecifier(normalized.specifier)).toEqual({
35
+ modulePath: "./seed.mjs",
36
+ exportName: "run",
37
+ });
38
+ expect(finalizeConfiguredStep(normalized, (value) => value.toUpperCase())).toEqual({
39
+ kind: "module",
40
+ specifier: "./SEED.MJS#RUN",
41
+ cwd: "DB",
42
+ inputs: ["SCHEMA.SQL"],
43
+ });
44
+ });
45
+
46
+ it("collects and validates configured input paths", () => {
47
+ const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-configured-steps-"));
48
+ tempDirs.push(productDir);
49
+ fs.mkdirSync(path.join(productDir, "db"), { recursive: true });
50
+ fs.writeFileSync(path.join(productDir, "db", "schema.sql"), "-- schema\n");
51
+ fs.writeFileSync(path.join(productDir, "db", "seed.mjs"), "export default async function run() {}\n");
52
+
53
+ const collection = {
54
+ inputs: ["db/schema.sql"],
55
+ steps: [
56
+ { kind: "sql-file", path: "schema.sql", cwd: "db", inputs: [] },
57
+ { kind: "module", specifier: "./seed.mjs#run", cwd: "db", inputs: [] },
58
+ ],
59
+ };
60
+
61
+ expect(collectConfiguredInputs(productDir, collection)).toEqual([
62
+ path.join(productDir, "db", "schema.sql"),
63
+ path.join(productDir, "db", "seed.mjs"),
64
+ ]);
65
+ expect(() =>
66
+ validateConfiguredCollection({
67
+ productDir,
68
+ label: 'Service "api" runtime.prepare',
69
+ ...collection,
70
+ })
71
+ ).not.toThrow();
72
+ });
73
+ });
@@ -0,0 +1,74 @@
1
+ import {
2
+ DEFAULT_FILE_TIMEOUT_SECONDS,
3
+ normalizeFileTimeoutSeconds,
4
+ parseFileTimeoutOption,
5
+ } from "./file-timeout.mjs";
6
+
7
+ export const DATABASE_BINDINGS = new Set(["shared", "per-runtime"]);
8
+
9
+ export { DEFAULT_FILE_TIMEOUT_SECONDS, parseFileTimeoutOption };
10
+
11
+ export function parseWorkersOption(value) {
12
+ return parsePositiveInteger(value, "--workers");
13
+ }
14
+
15
+ export function parseRuntimeInstancesOption(value, label = "runtime.instances") {
16
+ return parsePositiveInteger(value, label);
17
+ }
18
+
19
+ export function normalizeRuntimeInstances(value, label = "runtime.instances") {
20
+ return normalizePositiveInteger(value, label);
21
+ }
22
+
23
+ export function parseRuntimeMaxConcurrentTasksOption(value, label = "runtime.maxConcurrentTasks") {
24
+ return parsePositiveInteger(value, label);
25
+ }
26
+
27
+ export function normalizeRuntimeMaxConcurrentTasks(value, label = "runtime.maxConcurrentTasks") {
28
+ if (value === undefined || value === null) {
29
+ return Number.POSITIVE_INFINITY;
30
+ }
31
+ return normalizePositiveInteger(value, label);
32
+ }
33
+
34
+ export function normalizeDatabaseBinding(value, label = "database.binding") {
35
+ const normalized = String(value || "").trim();
36
+ if (!DATABASE_BINDINGS.has(normalized)) {
37
+ throw new Error(`Invalid ${label} value "${value}". Expected one of: shared, per-runtime.`);
38
+ }
39
+ return normalized;
40
+ }
41
+
42
+ export function resolveExecutionConfig({ cli = {}, repo = {} } = {}) {
43
+ return normalizeExecutionConfig({
44
+ workers: cli.workers ?? repo.workers ?? 1,
45
+ fileTimeoutSeconds: cli.fileTimeoutSeconds ?? repo.fileTimeoutSeconds ?? DEFAULT_FILE_TIMEOUT_SECONDS,
46
+ });
47
+ }
48
+
49
+ export function normalizeExecutionConfig(input = {}) {
50
+ return {
51
+ workers: normalizePositiveInteger(input.workers ?? 1, "execution.workers"),
52
+ fileTimeoutSeconds: normalizeFileTimeoutSeconds(input.fileTimeoutSeconds ?? DEFAULT_FILE_TIMEOUT_SECONDS),
53
+ };
54
+ }
55
+
56
+ export function buildRuntimeIds(count) {
57
+ return Array.from({ length: count }, (_unused, index) => `runtime-${index + 1}`);
58
+ }
59
+
60
+ function parsePositiveInteger(value, label) {
61
+ const parsed = Number.parseInt(String(value), 10);
62
+ if (!Number.isInteger(parsed) || parsed <= 0) {
63
+ throw new Error(`Invalid ${label} value "${value}". Expected a positive integer.`);
64
+ }
65
+ return parsed;
66
+ }
67
+
68
+ function normalizePositiveInteger(value, label) {
69
+ const parsed = Number(value);
70
+ if (!Number.isInteger(parsed) || parsed <= 0) {
71
+ throw new Error(`${label} must be a positive integer.`);
72
+ }
73
+ return parsed;
74
+ }
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ normalizeDatabaseBinding,
4
+ normalizeExecutionConfig,
5
+ normalizeRuntimeMaxConcurrentTasks,
6
+ resolveExecutionConfig,
7
+ } from "./execution-schema.mjs";
8
+
9
+ describe("shared execution schema", () => {
10
+ it("normalizes execution config and repo/cli overrides", () => {
11
+ expect(normalizeExecutionConfig({ workers: 2, fileTimeoutSeconds: 30 })).toEqual({
12
+ workers: 2,
13
+ fileTimeoutSeconds: 30,
14
+ });
15
+ expect(resolveExecutionConfig({ cli: { workers: 3 }, repo: { workers: 2, fileTimeoutSeconds: 45 } })).toEqual({
16
+ workers: 3,
17
+ fileTimeoutSeconds: 45,
18
+ });
19
+ });
20
+
21
+ it("validates runtime concurrency and database binding", () => {
22
+ expect(normalizeRuntimeMaxConcurrentTasks(undefined)).toBe(Number.POSITIVE_INFINITY);
23
+ expect(normalizeDatabaseBinding("shared")).toBe("shared");
24
+ expect(() => normalizeDatabaseBinding("legacy")).toThrow('Invalid database.binding value "legacy"');
25
+ });
26
+ });