@testsmith/testblocks 0.9.4 → 0.9.7

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 (300) hide show
  1. package/dist/cli/index.js +4 -1
  2. package/dist/client/assets/index-B8OSvcUg.css +1 -0
  3. package/dist/client/assets/index-CMMJHs_d.js +2197 -0
  4. package/dist/client/assets/index-CMMJHs_d.js.map +1 -0
  5. package/dist/client/index.html +2 -2
  6. package/dist/core/blocks/api/ApiAssertBodyContainsBlock.d.ts +13 -0
  7. package/dist/core/blocks/api/ApiAssertBodyContainsBlock.js +40 -0
  8. package/dist/core/blocks/api/ApiAssertStatusBlock.d.ts +13 -0
  9. package/dist/core/blocks/api/ApiAssertStatusBlock.js +35 -0
  10. package/dist/core/blocks/api/ApiClearHeadersBlock.d.ts +13 -0
  11. package/dist/core/blocks/api/ApiClearHeadersBlock.js +25 -0
  12. package/dist/core/blocks/api/ApiDeleteBlock.d.ts +13 -0
  13. package/dist/core/blocks/api/ApiDeleteBlock.js +37 -0
  14. package/dist/core/blocks/api/ApiExtractBlock.d.ts +14 -0
  15. package/dist/core/blocks/api/ApiExtractBlock.js +40 -0
  16. package/dist/core/blocks/api/ApiExtractJsonPathBlock.d.ts +13 -0
  17. package/dist/core/blocks/api/ApiExtractJsonPathBlock.js +47 -0
  18. package/dist/core/blocks/api/ApiExtractXPathBlock.d.ts +13 -0
  19. package/dist/core/blocks/api/ApiExtractXPathBlock.js +70 -0
  20. package/dist/core/blocks/api/ApiGetBlock.d.ts +13 -0
  21. package/dist/core/blocks/api/ApiGetBlock.js +36 -0
  22. package/dist/core/blocks/api/ApiHeadersBlock.d.ts +14 -0
  23. package/dist/core/blocks/api/ApiHeadersBlock.js +44 -0
  24. package/dist/core/blocks/api/ApiJsonBodyBlock.d.ts +14 -0
  25. package/dist/core/blocks/api/ApiJsonBodyBlock.js +28 -0
  26. package/dist/core/blocks/api/ApiPatchBlock.d.ts +13 -0
  27. package/dist/core/blocks/api/ApiPatchBlock.js +47 -0
  28. package/dist/core/blocks/api/ApiPostBlock.d.ts +13 -0
  29. package/dist/core/blocks/api/ApiPostBlock.js +47 -0
  30. package/dist/core/blocks/api/ApiPutBlock.d.ts +13 -0
  31. package/dist/core/blocks/api/ApiPutBlock.js +47 -0
  32. package/dist/core/blocks/api/ApiSetHeaderBlock.d.ts +13 -0
  33. package/dist/core/blocks/api/ApiSetHeaderBlock.js +37 -0
  34. package/dist/core/blocks/api/ApiSetHeadersBlock.d.ts +13 -0
  35. package/dist/core/blocks/api/ApiSetHeadersBlock.js +41 -0
  36. package/dist/core/blocks/api/index.d.ts +25 -0
  37. package/dist/core/blocks/api/index.js +83 -0
  38. package/dist/core/blocks/base/Block.d.ts +59 -0
  39. package/dist/core/blocks/base/Block.js +151 -0
  40. package/dist/core/blocks/base/ContainerBlock.d.ts +14 -0
  41. package/dist/core/blocks/base/ContainerBlock.js +16 -0
  42. package/dist/core/blocks/base/ControlFlowBlock.d.ts +13 -0
  43. package/dist/core/blocks/base/ControlFlowBlock.js +17 -0
  44. package/dist/core/blocks/base/StatementBlock.d.ts +9 -0
  45. package/dist/core/blocks/base/StatementBlock.js +16 -0
  46. package/dist/core/blocks/base/ValueBlock.d.ts +12 -0
  47. package/dist/core/blocks/base/ValueBlock.js +16 -0
  48. package/dist/core/blocks/base/index.d.ts +5 -0
  49. package/dist/core/blocks/base/index.js +13 -0
  50. package/dist/core/blocks/data/DataCsvBlock.d.ts +14 -0
  51. package/dist/core/blocks/data/DataCsvBlock.js +51 -0
  52. package/dist/core/blocks/data/DataDefineBlock.d.ts +14 -0
  53. package/dist/core/blocks/data/DataDefineBlock.js +28 -0
  54. package/dist/core/blocks/data/DataForeachBlock.d.ts +13 -0
  55. package/dist/core/blocks/data/DataForeachBlock.js +37 -0
  56. package/dist/core/blocks/data/DataFromVariableBlock.d.ts +14 -0
  57. package/dist/core/blocks/data/DataFromVariableBlock.js +27 -0
  58. package/dist/core/blocks/data/DataGetCurrentBlock.d.ts +14 -0
  59. package/dist/core/blocks/data/DataGetCurrentBlock.js +34 -0
  60. package/dist/core/blocks/data/DataGetIndexBlock.d.ts +14 -0
  61. package/dist/core/blocks/data/DataGetIndexBlock.js +24 -0
  62. package/dist/core/blocks/data/DataGetNameBlock.d.ts +14 -0
  63. package/dist/core/blocks/data/DataGetNameBlock.js +24 -0
  64. package/dist/core/blocks/data/DataRangeBlock.d.ts +14 -0
  65. package/dist/core/blocks/data/DataRangeBlock.js +40 -0
  66. package/dist/core/blocks/data/DataRowBlock.d.ts +14 -0
  67. package/dist/core/blocks/data/DataRowBlock.js +33 -0
  68. package/dist/core/blocks/data/DataTableBlock.d.ts +14 -0
  69. package/dist/core/blocks/data/DataTableBlock.js +51 -0
  70. package/dist/core/blocks/data/index.d.ts +20 -0
  71. package/dist/core/blocks/data/index.js +57 -0
  72. package/dist/core/blocks/index.d.ts +66 -5
  73. package/dist/core/blocks/index.js +134 -35
  74. package/dist/core/blocks/lifecycle/LifecycleAfterAllBlock.d.ts +15 -0
  75. package/dist/core/blocks/lifecycle/LifecycleAfterAllBlock.js +27 -0
  76. package/dist/core/blocks/lifecycle/LifecycleAfterEachBlock.d.ts +15 -0
  77. package/dist/core/blocks/lifecycle/LifecycleAfterEachBlock.js +27 -0
  78. package/dist/core/blocks/lifecycle/LifecycleBeforeAllBlock.d.ts +15 -0
  79. package/dist/core/blocks/lifecycle/LifecycleBeforeAllBlock.js +28 -0
  80. package/dist/core/blocks/lifecycle/LifecycleBeforeEachBlock.d.ts +15 -0
  81. package/dist/core/blocks/lifecycle/LifecycleBeforeEachBlock.js +27 -0
  82. package/dist/core/blocks/lifecycle/LifecycleOnFailureBlock.d.ts +13 -0
  83. package/dist/core/blocks/lifecycle/LifecycleOnFailureBlock.js +25 -0
  84. package/dist/core/blocks/lifecycle/LifecycleRetryBlock.d.ts +13 -0
  85. package/dist/core/blocks/lifecycle/LifecycleRetryBlock.js +29 -0
  86. package/dist/core/blocks/lifecycle/LifecycleSetupBlock.d.ts +13 -0
  87. package/dist/core/blocks/lifecycle/LifecycleSetupBlock.js +27 -0
  88. package/dist/core/blocks/lifecycle/LifecycleSkipIfBlock.d.ts +13 -0
  89. package/dist/core/blocks/lifecycle/LifecycleSkipIfBlock.js +31 -0
  90. package/dist/core/blocks/lifecycle/LifecycleTeardownBlock.d.ts +13 -0
  91. package/dist/core/blocks/lifecycle/LifecycleTeardownBlock.js +27 -0
  92. package/dist/core/blocks/lifecycle/TestCaseBlock.d.ts +21 -0
  93. package/dist/core/blocks/lifecycle/TestCaseBlock.js +72 -0
  94. package/dist/core/blocks/lifecycle/TestCaseDataDrivenBlock.d.ts +21 -0
  95. package/dist/core/blocks/lifecycle/TestCaseDataDrivenBlock.js +102 -0
  96. package/dist/core/blocks/lifecycle/index.d.ts +21 -0
  97. package/dist/core/blocks/lifecycle/index.js +63 -0
  98. package/dist/core/blocks/logic/LogicArrayBlock.d.ts +14 -0
  99. package/dist/core/blocks/logic/LogicArrayBlock.js +28 -0
  100. package/dist/core/blocks/logic/LogicAssertBlock.d.ts +13 -0
  101. package/dist/core/blocks/logic/LogicAssertBlock.js +32 -0
  102. package/dist/core/blocks/logic/LogicBooleanBlock.d.ts +14 -0
  103. package/dist/core/blocks/logic/LogicBooleanBlock.js +26 -0
  104. package/dist/core/blocks/logic/LogicBooleanOpBlock.d.ts +14 -0
  105. package/dist/core/blocks/logic/LogicBooleanOpBlock.js +31 -0
  106. package/dist/core/blocks/logic/LogicCommentBlock.d.ts +13 -0
  107. package/dist/core/blocks/logic/LogicCommentBlock.js +26 -0
  108. package/dist/core/blocks/logic/LogicCompareBlock.d.ts +14 -0
  109. package/dist/core/blocks/logic/LogicCompareBlock.js +52 -0
  110. package/dist/core/blocks/logic/LogicFailBlock.d.ts +16 -0
  111. package/dist/core/blocks/logic/LogicFailBlock.js +30 -0
  112. package/dist/core/blocks/logic/LogicForeachBlock.d.ts +13 -0
  113. package/dist/core/blocks/logic/LogicForeachBlock.js +29 -0
  114. package/dist/core/blocks/logic/LogicGetVariableBlock.d.ts +14 -0
  115. package/dist/core/blocks/logic/LogicGetVariableBlock.js +27 -0
  116. package/dist/core/blocks/logic/LogicIfBlock.d.ts +13 -0
  117. package/dist/core/blocks/logic/LogicIfBlock.js +36 -0
  118. package/dist/core/blocks/logic/LogicLogBlock.d.ts +13 -0
  119. package/dist/core/blocks/logic/LogicLogBlock.js +30 -0
  120. package/dist/core/blocks/logic/LogicNotBlock.d.ts +14 -0
  121. package/dist/core/blocks/logic/LogicNotBlock.js +26 -0
  122. package/dist/core/blocks/logic/LogicNumberBlock.d.ts +14 -0
  123. package/dist/core/blocks/logic/LogicNumberBlock.js +26 -0
  124. package/dist/core/blocks/logic/LogicObjectBlock.d.ts +14 -0
  125. package/dist/core/blocks/logic/LogicObjectBlock.js +28 -0
  126. package/dist/core/blocks/logic/LogicRepeatBlock.d.ts +13 -0
  127. package/dist/core/blocks/logic/LogicRepeatBlock.js +27 -0
  128. package/dist/core/blocks/logic/LogicSetVariableBlock.d.ts +13 -0
  129. package/dist/core/blocks/logic/LogicSetVariableBlock.js +34 -0
  130. package/dist/core/blocks/logic/LogicTextBlock.d.ts +14 -0
  131. package/dist/core/blocks/logic/LogicTextBlock.js +27 -0
  132. package/dist/core/blocks/logic/LogicTryCatchBlock.d.ts +13 -0
  133. package/dist/core/blocks/logic/LogicTryCatchBlock.js +26 -0
  134. package/dist/core/blocks/logic/index.d.ts +28 -0
  135. package/dist/core/blocks/logic/index.js +95 -0
  136. package/dist/core/blocks/playwright/assertions/WebAssertAccessibleDescriptionBlock.d.ts +13 -0
  137. package/dist/core/blocks/playwright/assertions/WebAssertAccessibleDescriptionBlock.js +41 -0
  138. package/dist/core/blocks/playwright/assertions/WebAssertAccessibleNameBlock.d.ts +13 -0
  139. package/dist/core/blocks/playwright/assertions/WebAssertAccessibleNameBlock.js +41 -0
  140. package/dist/core/blocks/playwright/assertions/WebAssertAttachedBlock.d.ts +13 -0
  141. package/dist/core/blocks/playwright/assertions/WebAssertAttachedBlock.js +39 -0
  142. package/dist/core/blocks/playwright/assertions/WebAssertAttributeBlock.d.ts +13 -0
  143. package/dist/core/blocks/playwright/assertions/WebAssertAttributeBlock.js +44 -0
  144. package/dist/core/blocks/playwright/assertions/WebAssertCheckedBlock.d.ts +13 -0
  145. package/dist/core/blocks/playwright/assertions/WebAssertCheckedBlock.js +48 -0
  146. package/dist/core/blocks/playwright/assertions/WebAssertClassBlock.d.ts +13 -0
  147. package/dist/core/blocks/playwright/assertions/WebAssertClassBlock.js +43 -0
  148. package/dist/core/blocks/playwright/assertions/WebAssertCountBlock.d.ts +13 -0
  149. package/dist/core/blocks/playwright/assertions/WebAssertCountBlock.js +41 -0
  150. package/dist/core/blocks/playwright/assertions/WebAssertCssBlock.d.ts +13 -0
  151. package/dist/core/blocks/playwright/assertions/WebAssertCssBlock.js +44 -0
  152. package/dist/core/blocks/playwright/assertions/WebAssertDisabledBlock.d.ts +13 -0
  153. package/dist/core/blocks/playwright/assertions/WebAssertDisabledBlock.js +39 -0
  154. package/dist/core/blocks/playwright/assertions/WebAssertEditableBlock.d.ts +13 -0
  155. package/dist/core/blocks/playwright/assertions/WebAssertEditableBlock.js +39 -0
  156. package/dist/core/blocks/playwright/assertions/WebAssertEmptyBlock.d.ts +13 -0
  157. package/dist/core/blocks/playwright/assertions/WebAssertEmptyBlock.js +39 -0
  158. package/dist/core/blocks/playwright/assertions/WebAssertEnabledBlock.d.ts +13 -0
  159. package/dist/core/blocks/playwright/assertions/WebAssertEnabledBlock.js +39 -0
  160. package/dist/core/blocks/playwright/assertions/WebAssertFocusedBlock.d.ts +13 -0
  161. package/dist/core/blocks/playwright/assertions/WebAssertFocusedBlock.js +39 -0
  162. package/dist/core/blocks/playwright/assertions/WebAssertIdBlock.d.ts +13 -0
  163. package/dist/core/blocks/playwright/assertions/WebAssertIdBlock.js +41 -0
  164. package/dist/core/blocks/playwright/assertions/WebAssertInViewportBlock.d.ts +13 -0
  165. package/dist/core/blocks/playwright/assertions/WebAssertInViewportBlock.js +39 -0
  166. package/dist/core/blocks/playwright/assertions/WebAssertNotVisibleBlock.d.ts +13 -0
  167. package/dist/core/blocks/playwright/assertions/WebAssertNotVisibleBlock.js +39 -0
  168. package/dist/core/blocks/playwright/assertions/WebAssertRoleBlock.d.ts +13 -0
  169. package/dist/core/blocks/playwright/assertions/WebAssertRoleBlock.js +69 -0
  170. package/dist/core/blocks/playwright/assertions/WebAssertTextContainsBlock.d.ts +13 -0
  171. package/dist/core/blocks/playwright/assertions/WebAssertTextContainsBlock.js +41 -0
  172. package/dist/core/blocks/playwright/assertions/WebAssertTextEqualsBlock.d.ts +13 -0
  173. package/dist/core/blocks/playwright/assertions/WebAssertTextEqualsBlock.js +41 -0
  174. package/dist/core/blocks/playwright/assertions/WebAssertTitleContainsBlock.d.ts +13 -0
  175. package/dist/core/blocks/playwright/assertions/WebAssertTitleContainsBlock.js +39 -0
  176. package/dist/core/blocks/playwright/assertions/WebAssertTitleEqualsBlock.d.ts +13 -0
  177. package/dist/core/blocks/playwright/assertions/WebAssertTitleEqualsBlock.js +36 -0
  178. package/dist/core/blocks/playwright/assertions/WebAssertUrlContainsBlock.d.ts +13 -0
  179. package/dist/core/blocks/playwright/assertions/WebAssertUrlContainsBlock.js +40 -0
  180. package/dist/core/blocks/playwright/assertions/WebAssertUrlEqualsBlock.d.ts +13 -0
  181. package/dist/core/blocks/playwright/assertions/WebAssertUrlEqualsBlock.js +37 -0
  182. package/dist/core/blocks/playwright/assertions/WebAssertValueBlock.d.ts +13 -0
  183. package/dist/core/blocks/playwright/assertions/WebAssertValueBlock.js +43 -0
  184. package/dist/core/blocks/playwright/assertions/WebAssertValueContainsBlock.d.ts +13 -0
  185. package/dist/core/blocks/playwright/assertions/WebAssertValueContainsBlock.js +43 -0
  186. package/dist/core/blocks/playwright/assertions/WebAssertVisibleBlock.d.ts +13 -0
  187. package/dist/core/blocks/playwright/assertions/WebAssertVisibleBlock.js +39 -0
  188. package/dist/core/blocks/playwright/assertions/index.d.ts +36 -0
  189. package/dist/core/blocks/playwright/assertions/index.js +127 -0
  190. package/dist/core/blocks/playwright/index.d.ts +16 -0
  191. package/dist/core/blocks/playwright/index.js +28 -3
  192. package/dist/core/blocks/playwright/interactions/WebCheckboxBlock.d.ts +13 -0
  193. package/dist/core/blocks/playwright/interactions/WebCheckboxBlock.js +43 -0
  194. package/dist/core/blocks/playwright/interactions/WebClickBlock.d.ts +13 -0
  195. package/dist/core/blocks/playwright/interactions/WebClickBlock.js +34 -0
  196. package/dist/core/blocks/playwright/interactions/WebDragAndDropBlock.d.ts +13 -0
  197. package/dist/core/blocks/playwright/interactions/WebDragAndDropBlock.js +37 -0
  198. package/dist/core/blocks/playwright/interactions/WebFillBlock.d.ts +13 -0
  199. package/dist/core/blocks/playwright/interactions/WebFillBlock.js +38 -0
  200. package/dist/core/blocks/playwright/interactions/WebFocusBlock.d.ts +13 -0
  201. package/dist/core/blocks/playwright/interactions/WebFocusBlock.js +34 -0
  202. package/dist/core/blocks/playwright/interactions/WebHoverBlock.d.ts +13 -0
  203. package/dist/core/blocks/playwright/interactions/WebHoverBlock.js +34 -0
  204. package/dist/core/blocks/playwright/interactions/WebPressKeyBlock.d.ts +13 -0
  205. package/dist/core/blocks/playwright/interactions/WebPressKeyBlock.js +37 -0
  206. package/dist/core/blocks/playwright/interactions/WebScrollIntoViewBlock.d.ts +13 -0
  207. package/dist/core/blocks/playwright/interactions/WebScrollIntoViewBlock.js +34 -0
  208. package/dist/core/blocks/playwright/interactions/WebSelectBlock.d.ts +13 -0
  209. package/dist/core/blocks/playwright/interactions/WebSelectBlock.js +37 -0
  210. package/dist/core/blocks/playwright/interactions/WebTypeBlock.d.ts +13 -0
  211. package/dist/core/blocks/playwright/interactions/WebTypeBlock.js +41 -0
  212. package/dist/core/blocks/playwright/interactions/WebUploadFileBlock.d.ts +13 -0
  213. package/dist/core/blocks/playwright/interactions/WebUploadFileBlock.js +39 -0
  214. package/dist/core/blocks/playwright/interactions/index.d.ts +21 -0
  215. package/dist/core/blocks/playwright/interactions/index.js +56 -0
  216. package/dist/core/blocks/playwright/navigation/WebNavigateBlock.d.ts +13 -0
  217. package/dist/core/blocks/playwright/navigation/WebNavigateBlock.js +36 -0
  218. package/dist/core/blocks/playwright/navigation/WebScreenshotBlock.d.ts +13 -0
  219. package/dist/core/blocks/playwright/navigation/WebScreenshotBlock.js +36 -0
  220. package/dist/core/blocks/playwright/navigation/WebWaitBlock.d.ts +13 -0
  221. package/dist/core/blocks/playwright/navigation/WebWaitBlock.js +32 -0
  222. package/dist/core/blocks/playwright/navigation/WebWaitForElementBlock.d.ts +13 -0
  223. package/dist/core/blocks/playwright/navigation/WebWaitForElementBlock.js +37 -0
  224. package/dist/core/blocks/playwright/navigation/WebWaitForUrlBlock.d.ts +13 -0
  225. package/dist/core/blocks/playwright/navigation/WebWaitForUrlBlock.js +34 -0
  226. package/dist/core/blocks/playwright/navigation/index.d.ts +15 -0
  227. package/dist/core/blocks/playwright/navigation/index.js +32 -0
  228. package/dist/core/blocks/playwright/retrieval/WebCountElementsBlock.d.ts +16 -0
  229. package/dist/core/blocks/playwright/retrieval/WebCountElementsBlock.js +36 -0
  230. package/dist/core/blocks/playwright/retrieval/WebGetAttributeBlock.d.ts +16 -0
  231. package/dist/core/blocks/playwright/retrieval/WebGetAttributeBlock.js +42 -0
  232. package/dist/core/blocks/playwright/retrieval/WebGetInputValueBlock.d.ts +16 -0
  233. package/dist/core/blocks/playwright/retrieval/WebGetInputValueBlock.js +40 -0
  234. package/dist/core/blocks/playwright/retrieval/WebGetTextBlock.d.ts +16 -0
  235. package/dist/core/blocks/playwright/retrieval/WebGetTextBlock.js +40 -0
  236. package/dist/core/blocks/playwright/retrieval/WebGetTitleBlock.d.ts +16 -0
  237. package/dist/core/blocks/playwright/retrieval/WebGetTitleBlock.js +31 -0
  238. package/dist/core/blocks/playwright/retrieval/WebGetUrlBlock.d.ts +16 -0
  239. package/dist/core/blocks/playwright/retrieval/WebGetUrlBlock.js +31 -0
  240. package/dist/core/blocks/playwright/retrieval/index.d.ts +16 -0
  241. package/dist/core/blocks/playwright/retrieval/index.js +36 -0
  242. package/dist/core/blocks/playwright/types.d.ts +14 -0
  243. package/dist/core/blocks/procedures/ProcedureCallBlock.d.ts +13 -0
  244. package/dist/core/blocks/procedures/ProcedureCallBlock.js +66 -0
  245. package/dist/core/blocks/procedures/ProcedureCallWithReturnBlock.d.ts +14 -0
  246. package/dist/core/blocks/procedures/ProcedureCallWithReturnBlock.js +51 -0
  247. package/dist/core/blocks/procedures/ProcedureDefineBlock.d.ts +15 -0
  248. package/dist/core/blocks/procedures/ProcedureDefineBlock.js +59 -0
  249. package/dist/core/blocks/procedures/ProcedureFillFormBlock.d.ts +13 -0
  250. package/dist/core/blocks/procedures/ProcedureFillFormBlock.js +30 -0
  251. package/dist/core/blocks/procedures/ProcedureGetParamBlock.d.ts +14 -0
  252. package/dist/core/blocks/procedures/ProcedureGetParamBlock.js +33 -0
  253. package/dist/core/blocks/procedures/ProcedureInlineBlock.d.ts +14 -0
  254. package/dist/core/blocks/procedures/ProcedureInlineBlock.js +31 -0
  255. package/dist/core/blocks/procedures/ProcedureLoginBlock.d.ts +13 -0
  256. package/dist/core/blocks/procedures/ProcedureLoginBlock.js +37 -0
  257. package/dist/core/blocks/procedures/ProcedureMapBlock.d.ts +14 -0
  258. package/dist/core/blocks/procedures/ProcedureMapBlock.js +36 -0
  259. package/dist/core/blocks/procedures/ProcedureReturnBlock.d.ts +15 -0
  260. package/dist/core/blocks/procedures/ProcedureReturnBlock.js +28 -0
  261. package/dist/core/blocks/procedures/ProcedureWaitAndClickBlock.d.ts +13 -0
  262. package/dist/core/blocks/procedures/ProcedureWaitAndClickBlock.js +32 -0
  263. package/dist/core/blocks/procedures/index.d.ts +21 -0
  264. package/dist/core/blocks/procedures/index.js +62 -0
  265. package/dist/core/blocks/{procedures.d.ts → procedures/procedureRegistry.d.ts} +10 -2
  266. package/dist/core/blocks/procedures/procedureRegistry.js +27 -0
  267. package/dist/core/blocks/utils/apiUtils.d.ts +81 -0
  268. package/dist/core/blocks/utils/apiUtils.js +176 -0
  269. package/dist/core/blocks/utils/index.d.ts +2 -0
  270. package/dist/core/blocks/utils/index.js +16 -0
  271. package/dist/core/blocks/utils/variableUtils.d.ts +19 -0
  272. package/dist/core/blocks/utils/variableUtils.js +69 -0
  273. package/dist/server/index.js +117 -11
  274. package/dist/server/openApiParser.d.ts +82 -0
  275. package/dist/server/openApiParser.js +495 -0
  276. package/dist/server/startServer.d.ts +1 -0
  277. package/dist/server/startServer.js +164 -0
  278. package/package.json +4 -2
  279. package/dist/client/assets/index-BLBBQ6Rn.js +0 -2195
  280. package/dist/client/assets/index-BLBBQ6Rn.js.map +0 -1
  281. package/dist/client/assets/index-qjoPPl9y.css +0 -1
  282. package/dist/core/blocks/api.d.ts +0 -2
  283. package/dist/core/blocks/api.js +0 -607
  284. package/dist/core/blocks/data-driven.d.ts +0 -2
  285. package/dist/core/blocks/data-driven.js +0 -245
  286. package/dist/core/blocks/lifecycle.d.ts +0 -2
  287. package/dist/core/blocks/lifecycle.js +0 -201
  288. package/dist/core/blocks/logic.d.ts +0 -2
  289. package/dist/core/blocks/logic.js +0 -360
  290. package/dist/core/blocks/playwright/assertions.d.ts +0 -5
  291. package/dist/core/blocks/playwright/assertions.js +0 -311
  292. package/dist/core/blocks/playwright/interactions.d.ts +0 -5
  293. package/dist/core/blocks/playwright/interactions.js +0 -208
  294. package/dist/core/blocks/playwright/navigation.d.ts +0 -5
  295. package/dist/core/blocks/playwright/navigation.js +0 -131
  296. package/dist/core/blocks/playwright/retrieval.d.ts +0 -5
  297. package/dist/core/blocks/playwright/retrieval.js +0 -153
  298. package/dist/core/blocks/playwright.d.ts +0 -13
  299. package/dist/core/blocks/playwright.js +0 -17
  300. package/dist/core/blocks/procedures.js +0 -321
@@ -0,0 +1,495 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.parseOpenApiSpec = parseOpenApiSpec;
40
+ exports.generateTestFiles = generateTestFiles;
41
+ const swagger_parser_1 = __importDefault(require("@apidevtools/swagger-parser"));
42
+ /**
43
+ * Parse an OpenAPI/Swagger spec from a URL or content string
44
+ */
45
+ async function parseOpenApiSpec(source, isUrl = true) {
46
+ let api;
47
+ if (isUrl) {
48
+ api = await swagger_parser_1.default.dereference(source);
49
+ }
50
+ else {
51
+ // Parse from content string (JSON or YAML)
52
+ const content = source.trim();
53
+ let parsed;
54
+ if (content.startsWith('{')) {
55
+ parsed = JSON.parse(content);
56
+ }
57
+ else {
58
+ // Import yaml dynamically
59
+ const yaml = await Promise.resolve().then(() => __importStar(require('yaml')));
60
+ parsed = yaml.parse(content);
61
+ }
62
+ api = await swagger_parser_1.default.dereference(parsed);
63
+ }
64
+ return extractSpecInfo(api);
65
+ }
66
+ /**
67
+ * Extract structured information from a parsed OpenAPI spec
68
+ */
69
+ function extractSpecInfo(api) {
70
+ const isV3 = 'openapi' in api;
71
+ // Extract info
72
+ const info = {
73
+ title: api.info.title,
74
+ version: api.info.version,
75
+ description: api.info.description,
76
+ };
77
+ // Extract servers
78
+ const servers = [];
79
+ if (isV3) {
80
+ const v3Api = api;
81
+ if (v3Api.servers) {
82
+ servers.push(...v3Api.servers.map(s => ({ url: s.url, description: s.description })));
83
+ }
84
+ }
85
+ else {
86
+ const v2Api = api;
87
+ const scheme = v2Api.schemes?.[0] || 'https';
88
+ const host = v2Api.host || 'localhost';
89
+ const basePath = v2Api.basePath || '';
90
+ servers.push({ url: `${scheme}://${host}${basePath}` });
91
+ }
92
+ // Extract security schemes
93
+ const securitySchemes = {};
94
+ if (isV3) {
95
+ const v3Api = api;
96
+ const schemes = v3Api.components?.securitySchemes || {};
97
+ for (const [name, scheme] of Object.entries(schemes)) {
98
+ if ('type' in scheme) {
99
+ securitySchemes[name] = extractSecurityScheme(scheme);
100
+ }
101
+ }
102
+ }
103
+ else {
104
+ const v2Api = api;
105
+ const schemes = v2Api.securityDefinitions || {};
106
+ for (const [name, scheme] of Object.entries(schemes)) {
107
+ securitySchemes[name] = extractSecuritySchemeV2(scheme);
108
+ }
109
+ }
110
+ // Extract tags
111
+ const tags = (api.tags || []).map(t => ({
112
+ name: t.name,
113
+ description: t.description,
114
+ }));
115
+ // Extract endpoints
116
+ const endpoints = [];
117
+ const paths = api.paths || {};
118
+ for (const [path, pathItem] of Object.entries(paths)) {
119
+ if (!pathItem)
120
+ continue;
121
+ const methods = ['get', 'post', 'put', 'patch', 'delete'];
122
+ for (const method of methods) {
123
+ const operation = pathItem[method];
124
+ if (!operation)
125
+ continue;
126
+ const endpoint = extractEndpoint(path, method, operation, pathItem, isV3);
127
+ endpoints.push(endpoint);
128
+ }
129
+ }
130
+ return { info, servers, endpoints, securitySchemes, tags };
131
+ }
132
+ /**
133
+ * Extract a single endpoint from an operation
134
+ */
135
+ function extractEndpoint(path, method, operation, pathItem, isV3) {
136
+ // Combine path-level and operation-level parameters
137
+ const pathParams = (pathItem.parameters || []);
138
+ const opParams = (operation.parameters || []);
139
+ const allParams = [...pathParams, ...opParams];
140
+ // Extract parameters
141
+ const parameters = allParams.map(param => ({
142
+ name: param.name,
143
+ in: param.in,
144
+ required: param.required || false,
145
+ description: param.description,
146
+ schema: isV3
147
+ ? extractSchema(param.schema)
148
+ : extractSchemaV2(param),
149
+ }));
150
+ // Extract request body
151
+ let requestBody;
152
+ if (isV3) {
153
+ const v3Op = operation;
154
+ if (v3Op.requestBody && 'content' in v3Op.requestBody) {
155
+ const rb = v3Op.requestBody;
156
+ const contentType = Object.keys(rb.content)[0] || 'application/json';
157
+ const mediaType = rb.content[contentType];
158
+ requestBody = {
159
+ required: rb.required || false,
160
+ contentType,
161
+ schema: mediaType?.schema,
162
+ example: mediaType?.example || mediaType?.schema?.example,
163
+ };
164
+ }
165
+ }
166
+ else {
167
+ const v2Op = operation;
168
+ const bodyParam = allParams.find(p => p.in === 'body');
169
+ if (bodyParam) {
170
+ requestBody = {
171
+ required: bodyParam.required || false,
172
+ contentType: 'application/json',
173
+ schema: bodyParam.schema,
174
+ example: bodyParam.schema?.example,
175
+ };
176
+ }
177
+ }
178
+ // Extract responses
179
+ const responses = [];
180
+ for (const [statusCode, response] of Object.entries(operation.responses || {})) {
181
+ if (!response || '$ref' in response)
182
+ continue;
183
+ const resp = response;
184
+ let example;
185
+ let schema;
186
+ if (isV3) {
187
+ const v3Resp = resp;
188
+ const content = v3Resp.content?.['application/json'];
189
+ schema = content?.schema;
190
+ example = content?.example || content?.schema?.example;
191
+ }
192
+ else {
193
+ const v2Resp = resp;
194
+ schema = v2Resp.schema;
195
+ example = v2Resp.schema?.example;
196
+ }
197
+ responses.push({
198
+ statusCode,
199
+ description: resp.description,
200
+ schema,
201
+ example,
202
+ });
203
+ }
204
+ // Generate operation ID if not present
205
+ const operationId = operation.operationId || `${method}_${path.replace(/[^a-zA-Z0-9]/g, '_')}`;
206
+ return {
207
+ operationId,
208
+ method,
209
+ path,
210
+ summary: operation.summary,
211
+ description: operation.description,
212
+ tags: operation.tags || [],
213
+ parameters,
214
+ requestBody,
215
+ responses,
216
+ security: operation.security,
217
+ deprecated: operation.deprecated,
218
+ };
219
+ }
220
+ function extractSchema(schema) {
221
+ if (!schema)
222
+ return undefined;
223
+ return {
224
+ type: schema.type || 'string',
225
+ format: schema.format,
226
+ default: schema.default,
227
+ example: schema.example,
228
+ };
229
+ }
230
+ function extractSchemaV2(param) {
231
+ if (!('type' in param))
232
+ return undefined;
233
+ const p = param;
234
+ return {
235
+ type: p.type || 'string',
236
+ format: p.format,
237
+ default: p.default,
238
+ example: undefined, // V2 doesn't have example on parameters
239
+ };
240
+ }
241
+ function extractSecurityScheme(scheme) {
242
+ return {
243
+ type: scheme.type,
244
+ name: 'name' in scheme ? scheme.name : undefined,
245
+ in: 'in' in scheme ? scheme.in : undefined,
246
+ scheme: 'scheme' in scheme ? scheme.scheme : undefined,
247
+ bearerFormat: 'bearerFormat' in scheme ? scheme.bearerFormat : undefined,
248
+ description: scheme.description,
249
+ };
250
+ }
251
+ function extractSecuritySchemeV2(scheme) {
252
+ return {
253
+ type: scheme.type === 'basic' ? 'http' : scheme.type,
254
+ name: 'name' in scheme ? scheme.name : undefined,
255
+ in: 'in' in scheme ? scheme.in : undefined,
256
+ scheme: scheme.type === 'basic' ? 'basic' : undefined,
257
+ description: scheme.description,
258
+ };
259
+ }
260
+ /**
261
+ * Generate test files from selected endpoints
262
+ */
263
+ function generateTestFiles(spec, selectedEndpoints, options) {
264
+ const endpoints = spec.endpoints.filter(e => selectedEndpoints.includes(e.operationId));
265
+ if (endpoints.length === 0) {
266
+ return [];
267
+ }
268
+ switch (options.fileStrategy) {
269
+ case 'single':
270
+ return [generateSingleFile(spec, endpoints, options)];
271
+ case 'per-tag':
272
+ return generatePerTagFiles(spec, endpoints, options);
273
+ case 'per-path':
274
+ return generatePerPathFiles(spec, endpoints, options);
275
+ default:
276
+ return [generateSingleFile(spec, endpoints, options)];
277
+ }
278
+ }
279
+ function generateSingleFile(spec, endpoints, options) {
280
+ const variables = extractVariables(endpoints, options);
281
+ const tests = endpoints.map(endpoint => generateTestCase(endpoint, options));
282
+ const testFile = {
283
+ version: '1.0.0',
284
+ name: spec.info.title,
285
+ description: spec.info.description || `API tests generated from ${spec.info.title} v${spec.info.version}`,
286
+ variables,
287
+ tests,
288
+ };
289
+ const fileName = sanitizeFileName(spec.info.title) + '.testblocks.json';
290
+ return { fileName, testFile };
291
+ }
292
+ function generatePerTagFiles(spec, endpoints, options) {
293
+ // Group endpoints by tag
294
+ const byTag = new Map();
295
+ for (const endpoint of endpoints) {
296
+ const tag = endpoint.tags[0] || 'default';
297
+ if (!byTag.has(tag)) {
298
+ byTag.set(tag, []);
299
+ }
300
+ byTag.get(tag).push(endpoint);
301
+ }
302
+ const files = [];
303
+ for (const [tag, tagEndpoints] of byTag) {
304
+ const variables = extractVariables(tagEndpoints, options);
305
+ const tests = tagEndpoints.map(endpoint => generateTestCase(endpoint, options));
306
+ const tagInfo = spec.tags.find(t => t.name === tag);
307
+ const testFile = {
308
+ version: '1.0.0',
309
+ name: `${spec.info.title} - ${tag}`,
310
+ description: tagInfo?.description || `API tests for ${tag}`,
311
+ variables,
312
+ tests,
313
+ };
314
+ const fileName = sanitizeFileName(`${spec.info.title}-${tag}`) + '.testblocks.json';
315
+ files.push({ fileName, testFile });
316
+ }
317
+ return files;
318
+ }
319
+ function generatePerPathFiles(spec, endpoints, options) {
320
+ // Group endpoints by base path (first segment)
321
+ const byPath = new Map();
322
+ for (const endpoint of endpoints) {
323
+ const segments = endpoint.path.split('/').filter(Boolean);
324
+ const basePath = segments[0] || 'root';
325
+ if (!byPath.has(basePath)) {
326
+ byPath.set(basePath, []);
327
+ }
328
+ byPath.get(basePath).push(endpoint);
329
+ }
330
+ const files = [];
331
+ for (const [basePath, pathEndpoints] of byPath) {
332
+ const variables = extractVariables(pathEndpoints, options);
333
+ const tests = pathEndpoints.map(endpoint => generateTestCase(endpoint, options));
334
+ const testFile = {
335
+ version: '1.0.0',
336
+ name: `${spec.info.title} - /${basePath}`,
337
+ description: `API tests for /${basePath} endpoints`,
338
+ variables,
339
+ tests,
340
+ };
341
+ const fileName = sanitizeFileName(`${spec.info.title}-${basePath}`) + '.testblocks.json';
342
+ files.push({ fileName, testFile });
343
+ }
344
+ return files;
345
+ }
346
+ function extractVariables(endpoints, options) {
347
+ const variables = {
348
+ baseUrl: {
349
+ type: 'string',
350
+ default: options.baseUrl || '',
351
+ description: 'API base URL',
352
+ },
353
+ };
354
+ // Extract unique path parameters
355
+ const pathParams = new Set();
356
+ for (const endpoint of endpoints) {
357
+ for (const param of endpoint.parameters) {
358
+ if (param.in === 'path') {
359
+ pathParams.add(param.name);
360
+ }
361
+ }
362
+ }
363
+ for (const paramName of pathParams) {
364
+ const param = endpoints
365
+ .flatMap(e => e.parameters)
366
+ .find(p => p.name === paramName && p.in === 'path');
367
+ variables[paramName] = {
368
+ type: (param?.schema?.type || 'string'),
369
+ default: param?.schema?.example || param?.schema?.default || '',
370
+ description: param?.description || `Path parameter: ${paramName}`,
371
+ };
372
+ }
373
+ return variables;
374
+ }
375
+ function generateTestCase(endpoint, options) {
376
+ const steps = [];
377
+ // Generate API call step
378
+ const apiStep = generateApiCallStep(endpoint, options);
379
+ steps.push(apiStep);
380
+ // Generate assertion step if enabled
381
+ if (options.generateAssertions) {
382
+ const assertionStep = generateAssertionStep(endpoint);
383
+ if (assertionStep) {
384
+ steps.push(assertionStep);
385
+ }
386
+ }
387
+ return {
388
+ id: `test-${endpoint.operationId}-${Date.now()}`,
389
+ name: `${endpoint.method.toUpperCase()} ${endpoint.path}`,
390
+ description: endpoint.summary || endpoint.description,
391
+ tags: endpoint.tags,
392
+ steps,
393
+ };
394
+ }
395
+ function generateApiCallStep(endpoint, options) {
396
+ const blockType = `api_${endpoint.method}`;
397
+ // Convert path parameters from {param} to ${param}
398
+ const urlPath = endpoint.path.replace(/\{([^}]+)\}/g, '${$1}');
399
+ const url = `\${baseUrl}${urlPath}`;
400
+ const params = {
401
+ URL: url,
402
+ };
403
+ // Add request body for POST/PUT/PATCH
404
+ if (['post', 'put', 'patch'].includes(endpoint.method) && endpoint.requestBody) {
405
+ let body = '{}';
406
+ if (options.includeExamples && endpoint.requestBody.example) {
407
+ body = JSON.stringify(endpoint.requestBody.example, null, 2);
408
+ }
409
+ else if (endpoint.requestBody.schema) {
410
+ body = generateSchemaExample(endpoint.requestBody.schema);
411
+ }
412
+ params.BODY = body;
413
+ }
414
+ return {
415
+ id: `step-${endpoint.operationId}-call-${Date.now()}`,
416
+ type: blockType,
417
+ params,
418
+ };
419
+ }
420
+ function generateAssertionStep(endpoint) {
421
+ // Find the first 2xx response
422
+ const successResponse = endpoint.responses.find(r => r.statusCode.startsWith('2'));
423
+ if (!successResponse) {
424
+ return null;
425
+ }
426
+ const statusCode = parseInt(successResponse.statusCode, 10);
427
+ return {
428
+ id: `step-${endpoint.operationId}-assert-${Date.now()}`,
429
+ type: 'api_assert_status',
430
+ params: {
431
+ STATUS: isNaN(statusCode) ? 200 : statusCode,
432
+ },
433
+ };
434
+ }
435
+ function generateSchemaExample(schema) {
436
+ // Simple schema-to-example generation
437
+ const type = schema.type;
438
+ if (schema.example !== undefined) {
439
+ return JSON.stringify(schema.example, null, 2);
440
+ }
441
+ switch (type) {
442
+ case 'object': {
443
+ const properties = schema.properties;
444
+ if (!properties)
445
+ return '{}';
446
+ const obj = {};
447
+ for (const [key, prop] of Object.entries(properties)) {
448
+ obj[key] = getDefaultValueForType(prop.type, prop.example, prop.format);
449
+ }
450
+ return JSON.stringify(obj, null, 2);
451
+ }
452
+ case 'array': {
453
+ const items = schema.items;
454
+ if (!items)
455
+ return '[]';
456
+ const itemValue = getDefaultValueForType(items.type, items.example, items.format);
457
+ return JSON.stringify([itemValue], null, 2);
458
+ }
459
+ default:
460
+ return '{}';
461
+ }
462
+ }
463
+ function getDefaultValueForType(type, example, format) {
464
+ if (example !== undefined)
465
+ return example;
466
+ switch (type) {
467
+ case 'string':
468
+ if (format === 'email')
469
+ return 'user@example.com';
470
+ if (format === 'date')
471
+ return '2024-01-01';
472
+ if (format === 'date-time')
473
+ return '2024-01-01T00:00:00Z';
474
+ if (format === 'uuid')
475
+ return '00000000-0000-0000-0000-000000000000';
476
+ return 'string';
477
+ case 'integer':
478
+ case 'number':
479
+ return 0;
480
+ case 'boolean':
481
+ return true;
482
+ case 'array':
483
+ return [];
484
+ case 'object':
485
+ return {};
486
+ default:
487
+ return null;
488
+ }
489
+ }
490
+ function sanitizeFileName(name) {
491
+ return name
492
+ .toLowerCase()
493
+ .replace(/[^a-z0-9]+/g, '-')
494
+ .replace(/^-|-$/g, '');
495
+ }
@@ -2,6 +2,7 @@ export interface ServerOptions {
2
2
  port?: number;
3
3
  pluginsDir?: string;
4
4
  globalsDir?: string;
5
+ projectDir?: string;
5
6
  open?: boolean;
6
7
  }
7
8
  export declare function startServer(options?: ServerOptions): Promise<void>;
@@ -140,6 +140,7 @@ async function startServer(options = {}) {
140
140
  // Set directories
141
141
  const pluginsDir = options.pluginsDir || path_1.default.join(workingDir, 'plugins');
142
142
  const globalsDir = options.globalsDir || workingDir;
143
+ const projectDir = options.projectDir ? path_1.default.resolve(options.projectDir) : null;
143
144
  (0, plugins_1.setPluginsDirectory)(pluginsDir);
144
145
  (0, globals_1.setGlobalsDirectory)(globalsDir);
145
146
  // Load plugins and globals
@@ -167,6 +168,166 @@ async function startServer(options = {}) {
167
168
  app.get('/api/version', (_req, res) => {
168
169
  res.json({ version: VERSION });
169
170
  });
171
+ // Initial project directory (for auto-open)
172
+ app.get('/api/initial-project', (_req, res) => {
173
+ res.json({ projectDir });
174
+ });
175
+ // Server-side file system access (when projectDir is specified)
176
+ // List files in project directory
177
+ app.get('/api/project/files', async (_req, res) => {
178
+ if (!projectDir) {
179
+ return res.status(400).json({ error: 'No project directory configured' });
180
+ }
181
+ try {
182
+ const scanDir = async (dirPath, relativePath = '') => {
183
+ const entries = await fs_1.default.promises.readdir(dirPath, { withFileTypes: true });
184
+ const items = [];
185
+ for (const entry of entries) {
186
+ // Skip hidden files and common non-project directories
187
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') {
188
+ continue;
189
+ }
190
+ const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
191
+ const fullPath = path_1.default.join(dirPath, entry.name);
192
+ if (entry.isDirectory()) {
193
+ const children = await scanDir(fullPath, entryRelativePath);
194
+ items.push({
195
+ name: entry.name,
196
+ path: entryRelativePath,
197
+ type: 'folder',
198
+ children,
199
+ });
200
+ }
201
+ else if (entry.name.endsWith('.testblocks.json') || entry.name === 'globals.json') {
202
+ items.push({
203
+ name: entry.name,
204
+ path: entryRelativePath,
205
+ type: 'file',
206
+ });
207
+ }
208
+ }
209
+ // Sort: folders first, then alphabetically
210
+ items.sort((a, b) => {
211
+ const aObj = a;
212
+ const bObj = b;
213
+ if (aObj.type !== bObj.type) {
214
+ return aObj.type === 'folder' ? -1 : 1;
215
+ }
216
+ return aObj.name.localeCompare(bObj.name);
217
+ });
218
+ return items;
219
+ };
220
+ const files = await scanDir(projectDir);
221
+ res.json({
222
+ projectDir,
223
+ name: path_1.default.basename(projectDir),
224
+ files,
225
+ });
226
+ }
227
+ catch (error) {
228
+ res.status(500).json({ error: error.message });
229
+ }
230
+ });
231
+ // Read a file from project directory
232
+ app.get('/api/project/read', async (req, res) => {
233
+ if (!projectDir) {
234
+ return res.status(400).json({ error: 'No project directory configured' });
235
+ }
236
+ const filePath = req.query.path;
237
+ if (!filePath) {
238
+ return res.status(400).json({ error: 'File path is required' });
239
+ }
240
+ // Security: ensure path doesn't escape project directory
241
+ const fullPath = path_1.default.resolve(projectDir, filePath);
242
+ if (!fullPath.startsWith(projectDir)) {
243
+ return res.status(403).json({ error: 'Access denied' });
244
+ }
245
+ try {
246
+ const content = await fs_1.default.promises.readFile(fullPath, 'utf-8');
247
+ res.json({ content: JSON.parse(content) });
248
+ }
249
+ catch (error) {
250
+ res.status(500).json({ error: error.message });
251
+ }
252
+ });
253
+ // Write a file to project directory
254
+ app.post('/api/project/write', async (req, res) => {
255
+ if (!projectDir) {
256
+ return res.status(400).json({ error: 'No project directory configured' });
257
+ }
258
+ const { path: filePath, content } = req.body;
259
+ if (!filePath) {
260
+ return res.status(400).json({ error: 'File path is required' });
261
+ }
262
+ // Security: ensure path doesn't escape project directory
263
+ const fullPath = path_1.default.resolve(projectDir, filePath);
264
+ if (!fullPath.startsWith(projectDir)) {
265
+ return res.status(403).json({ error: 'Access denied' });
266
+ }
267
+ try {
268
+ // Ensure parent directory exists
269
+ await fs_1.default.promises.mkdir(path_1.default.dirname(fullPath), { recursive: true });
270
+ await fs_1.default.promises.writeFile(fullPath, JSON.stringify(content, null, 2));
271
+ res.json({ success: true });
272
+ }
273
+ catch (error) {
274
+ res.status(500).json({ error: error.message });
275
+ }
276
+ });
277
+ // Create a new file in project directory
278
+ app.post('/api/project/create', async (req, res) => {
279
+ if (!projectDir) {
280
+ return res.status(400).json({ error: 'No project directory configured' });
281
+ }
282
+ const { path: filePath, content } = req.body;
283
+ if (!filePath) {
284
+ return res.status(400).json({ error: 'File path is required' });
285
+ }
286
+ // Security: ensure path doesn't escape project directory
287
+ const fullPath = path_1.default.resolve(projectDir, filePath);
288
+ if (!fullPath.startsWith(projectDir)) {
289
+ return res.status(403).json({ error: 'Access denied' });
290
+ }
291
+ try {
292
+ // Check if file already exists
293
+ try {
294
+ await fs_1.default.promises.access(fullPath);
295
+ return res.status(409).json({ error: 'File already exists' });
296
+ }
297
+ catch {
298
+ // File doesn't exist, good
299
+ }
300
+ // Ensure parent directory exists
301
+ await fs_1.default.promises.mkdir(path_1.default.dirname(fullPath), { recursive: true });
302
+ await fs_1.default.promises.writeFile(fullPath, JSON.stringify(content, null, 2));
303
+ res.json({ success: true });
304
+ }
305
+ catch (error) {
306
+ res.status(500).json({ error: error.message });
307
+ }
308
+ });
309
+ // Delete a file from project directory
310
+ app.delete('/api/project/delete', async (req, res) => {
311
+ if (!projectDir) {
312
+ return res.status(400).json({ error: 'No project directory configured' });
313
+ }
314
+ const filePath = req.query.path;
315
+ if (!filePath) {
316
+ return res.status(400).json({ error: 'File path is required' });
317
+ }
318
+ // Security: ensure path doesn't escape project directory
319
+ const fullPath = path_1.default.resolve(projectDir, filePath);
320
+ if (!fullPath.startsWith(projectDir)) {
321
+ return res.status(403).json({ error: 'Access denied' });
322
+ }
323
+ try {
324
+ await fs_1.default.promises.unlink(fullPath);
325
+ res.json({ success: true });
326
+ }
327
+ catch (error) {
328
+ res.status(500).json({ error: error.message });
329
+ }
330
+ });
170
331
  // List available plugins (with full block definitions for client registration)
171
332
  app.get('/api/plugins', (_req, res) => {
172
333
  const available = (0, plugins_1.discoverPlugins)();
@@ -517,6 +678,9 @@ async function startServer(options = {}) {
517
678
  console.log(` Working directory: ${workingDir}`);
518
679
  console.log(` Plugins: ${pluginsDir}`);
519
680
  console.log(` Globals: ${globalsDir}`);
681
+ if (projectDir) {
682
+ console.log(` Project (auto-open): ${projectDir}`);
683
+ }
520
684
  console.log('\nPress Ctrl+C to stop\n');
521
685
  // Open browser if requested
522
686
  if (options.open) {