@wirebench/engine 2.2.1 → 3.1.0-rc.1

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 (566) hide show
  1. package/README.md +134 -1
  2. package/dist/account/schema.d.ts +34 -0
  3. package/dist/account/schema.js +29 -0
  4. package/dist/assert/callback.d.ts +76 -0
  5. package/dist/assert/callback.js +320 -0
  6. package/dist/assert/capture-source.d.ts +50 -0
  7. package/dist/assert/capture-source.js +89 -0
  8. package/dist/assert/check.d.ts +8 -0
  9. package/dist/assert/check.js +18 -0
  10. package/dist/assert/header.d.ts +5 -0
  11. package/dist/assert/header.js +48 -0
  12. package/dist/assert/index.d.ts +2 -2
  13. package/dist/assert/index.js +12 -0
  14. package/dist/assert/match.d.ts +6 -0
  15. package/dist/assert/match.js +13 -4
  16. package/dist/assert/model.d.ts +110 -3
  17. package/dist/assert/model.js +16 -1
  18. package/dist/assert/schema.d.ts +194 -1
  19. package/dist/assert/schema.js +154 -12
  20. package/dist/assert/status-names.d.ts +9 -0
  21. package/dist/assert/status-names.js +27 -0
  22. package/dist/assert/status.d.ts +4 -1
  23. package/dist/assert/status.js +27 -3
  24. package/dist/asyncapi/browser.d.ts +7 -0
  25. package/dist/asyncapi/browser.js +6 -0
  26. package/dist/asyncapi/frame-check-worker-host.d.ts +44 -0
  27. package/dist/asyncapi/frame-check-worker-host.js +175 -0
  28. package/dist/asyncapi/frame-check-worker.d.ts +12 -0
  29. package/dist/asyncapi/frame-check-worker.js +25 -0
  30. package/dist/asyncapi/frame-check.d.ts +25 -0
  31. package/dist/asyncapi/frame-check.js +78 -0
  32. package/dist/asyncapi/import.d.ts +25 -0
  33. package/dist/asyncapi/import.js +34 -0
  34. package/dist/asyncapi/map.d.ts +40 -0
  35. package/dist/asyncapi/map.js +230 -0
  36. package/dist/asyncapi/model.d.ts +84 -0
  37. package/dist/asyncapi/model.js +7 -0
  38. package/dist/asyncapi/normalise-2.d.ts +13 -0
  39. package/dist/asyncapi/normalise-2.js +113 -0
  40. package/dist/asyncapi/normalise-3.d.ts +14 -0
  41. package/dist/asyncapi/normalise-3.js +133 -0
  42. package/dist/asyncapi/parse.d.ts +31 -0
  43. package/dist/asyncapi/parse.js +85 -0
  44. package/dist/asyncapi/read.d.ts +35 -0
  45. package/dist/asyncapi/read.js +186 -0
  46. package/dist/asyncapi/security.d.ts +14 -0
  47. package/dist/asyncapi/security.js +55 -0
  48. package/dist/asyncapi/update.d.ts +53 -0
  49. package/dist/asyncapi/update.js +220 -0
  50. package/dist/errors.d.ts +16 -0
  51. package/dist/errors.js +22 -0
  52. package/dist/grpc/events.d.ts +22 -0
  53. package/dist/grpc/events.js +1 -0
  54. package/dist/grpc/expand.d.ts +1 -1
  55. package/dist/grpc/expand.js +15 -5
  56. package/dist/grpc/files.d.ts +271 -0
  57. package/dist/grpc/files.js +62 -0
  58. package/dist/grpc/model.d.ts +11 -1
  59. package/dist/grpc/module.d.ts +2 -0
  60. package/dist/grpc/module.js +13 -0
  61. package/dist/grpc/run.d.ts +73 -0
  62. package/dist/grpc/run.js +407 -0
  63. package/dist/grpc/script-types.d.ts +8 -0
  64. package/dist/grpc/script-types.js +149 -0
  65. package/dist/grpc/scripting.d.ts +34 -0
  66. package/dist/grpc/scripting.js +147 -0
  67. package/dist/grpc/send-input.d.ts +46 -0
  68. package/dist/grpc/send-input.js +42 -0
  69. package/dist/grpc/send.d.ts +2 -2
  70. package/dist/grpc/status.d.ts +9 -2
  71. package/dist/grpc/status.js +11 -24
  72. package/dist/grpc/storage.d.ts +9 -0
  73. package/dist/grpc/storage.js +167 -0
  74. package/dist/{rest/auth.d.ts → http/auth/apply-auth.d.ts} +4 -4
  75. package/dist/{rest/auth.js → http/auth/apply-auth.js} +1 -1
  76. package/dist/http/auth/apply.d.ts +1 -1
  77. package/dist/{rest → http/auth}/oauth2.d.ts +2 -2
  78. package/dist/{rest → http/auth}/oauth2.js +1 -1
  79. package/dist/http/auth/send-auth.d.ts +57 -0
  80. package/dist/http/auth/send-auth.js +7 -0
  81. package/dist/http/client.js +150 -8
  82. package/dist/http/cookies.d.ts +79 -0
  83. package/dist/http/cookies.js +81 -0
  84. package/dist/http/curl.d.ts +4 -14
  85. package/dist/http/curl.js +4 -154
  86. package/dist/http/decompress.d.ts +7 -0
  87. package/dist/http/decompress.js +23 -1
  88. package/dist/http/document-fetch.d.ts +42 -0
  89. package/dist/http/document-fetch.js +207 -0
  90. package/dist/http/entries.d.ts +27 -0
  91. package/dist/http/entries.js +16 -0
  92. package/dist/http/escape.d.ts +18 -0
  93. package/dist/http/escape.js +30 -0
  94. package/dist/http/fetch-document.d.ts +28 -0
  95. package/dist/{wsdl/fetch.js → http/fetch-document.js} +8 -16
  96. package/dist/http/media-type.d.ts +9 -0
  97. package/dist/http/media-type.js +12 -0
  98. package/dist/http/transcript-cap.d.ts +26 -0
  99. package/dist/http/transcript-cap.js +36 -0
  100. package/dist/http/types.d.ts +59 -0
  101. package/dist/http/webhook-signature.d.ts +81 -0
  102. package/dist/http/webhook-signature.js +227 -0
  103. package/dist/import-detect.d.ts +2 -2
  104. package/dist/import-detect.js +10 -1
  105. package/dist/index.d.ts +207 -55
  106. package/dist/index.js +129 -32
  107. package/dist/json/cursor.d.ts +2 -0
  108. package/dist/json/cursor.js +1 -0
  109. package/dist/json/pointer-range.d.ts +18 -0
  110. package/dist/json/pointer-range.js +157 -0
  111. package/dist/json/schema/model.d.ts +59 -0
  112. package/dist/json/schema/model.js +8 -0
  113. package/dist/json/schema/parse-text.d.ts +16 -0
  114. package/dist/json/schema/parse-text.js +37 -0
  115. package/dist/{rest/openapi → json/schema}/refs.d.ts +2 -2
  116. package/dist/{rest/openapi → json/schema}/refs.js +3 -3
  117. package/dist/{rest/openapi → json/schema}/sample.d.ts +4 -0
  118. package/dist/{rest/openapi → json/schema}/sample.js +2 -2
  119. package/dist/json/schema/source.d.ts +21 -0
  120. package/dist/json/schema/source.js +8 -0
  121. package/dist/json/schema-validate.d.ts +49 -0
  122. package/dist/json/schema-validate.js +557 -0
  123. package/dist/{wss/keystore → keystore}/index.js +1 -1
  124. package/dist/{wss/keystore → keystore}/pem.js +1 -1
  125. package/dist/{wss/keystore → keystore}/pkcs12.js +1 -1
  126. package/dist/project/attachments-cache.d.ts +3 -1
  127. package/dist/{wsdl → project}/cache-naming.js +1 -1
  128. package/dist/project/endpoints.d.ts +18 -8
  129. package/dist/project/endpoints.js +21 -6
  130. package/dist/project/environments.d.ts +7 -5
  131. package/dist/project/history.d.ts +105 -9
  132. package/dist/project/history.js +195 -23
  133. package/dist/project/inherit.d.ts +7 -0
  134. package/dist/project/inherit.js +9 -0
  135. package/dist/project/keystores.d.ts +1 -1
  136. package/dist/project/load-helpers.d.ts +89 -0
  137. package/dist/project/load-helpers.js +177 -0
  138. package/dist/project/load.d.ts +30 -4
  139. package/dist/project/load.js +168 -545
  140. package/dist/project/managed-files.d.ts +36 -0
  141. package/dist/project/managed-files.js +97 -0
  142. package/dist/project/migrate.d.ts +2 -2
  143. package/dist/project/migrate.js +2 -2
  144. package/dist/project/model.d.ts +92 -14
  145. package/dist/project/model.js +50 -4
  146. package/dist/project/paths.d.ts +10 -1
  147. package/dist/project/paths.js +10 -1
  148. package/dist/project/preferences.d.ts +11 -2
  149. package/dist/project/preferences.js +5 -1
  150. package/dist/project/properties.d.ts +31 -17
  151. package/dist/project/properties.js +89 -70
  152. package/dist/project/request-location.d.ts +20 -0
  153. package/dist/project/request-location.js +62 -0
  154. package/dist/project/save.d.ts +12 -2
  155. package/dist/project/save.js +186 -141
  156. package/dist/project/schema-parts.d.ts +337 -0
  157. package/dist/project/schema-parts.js +248 -0
  158. package/dist/project/schema.d.ts +72 -928
  159. package/dist/project/schema.js +17 -466
  160. package/dist/project/sequence-guards.d.ts +43 -0
  161. package/dist/project/sequence-guards.js +109 -0
  162. package/dist/project/serialize-helpers.d.ts +60 -0
  163. package/dist/project/serialize-helpers.js +108 -0
  164. package/dist/project/serialize.d.ts +7 -8
  165. package/dist/project/serialize.js +34 -293
  166. package/dist/protocol/features.d.ts +51 -0
  167. package/dist/protocol/features.js +64 -0
  168. package/dist/protocol/index.d.ts +7 -0
  169. package/dist/protocol/index.js +4 -0
  170. package/dist/protocol/module.d.ts +247 -0
  171. package/dist/protocol/module.js +48 -0
  172. package/dist/protocol/registry.d.ts +42 -0
  173. package/dist/protocol/registry.js +47 -0
  174. package/dist/protocols.d.ts +77 -0
  175. package/dist/protocols.js +40 -0
  176. package/dist/redact/index.d.ts +12 -1
  177. package/dist/redact/index.js +55 -7
  178. package/dist/redact/literal.d.ts +10 -0
  179. package/dist/redact/literal.js +110 -12
  180. package/dist/rest/body.d.ts +2 -10
  181. package/dist/rest/body.js +3 -25
  182. package/dist/rest/browser.d.ts +4 -0
  183. package/dist/rest/browser.js +5 -0
  184. package/dist/rest/contract-check-worker-host.d.ts +36 -0
  185. package/dist/rest/contract-check-worker-host.js +158 -0
  186. package/dist/rest/contract-check-worker.d.ts +7 -0
  187. package/dist/rest/contract-check-worker.js +28 -0
  188. package/dist/rest/contract-check.d.ts +43 -0
  189. package/dist/rest/contract-check.js +217 -0
  190. package/dist/rest/cookie-jar.d.ts +62 -0
  191. package/dist/rest/cookie-jar.js +262 -0
  192. package/dist/rest/cookies.d.ts +6 -22
  193. package/dist/rest/cookies.js +6 -42
  194. package/dist/rest/curl.js +5 -1
  195. package/dist/rest/events.d.ts +12 -0
  196. package/dist/rest/events.js +1 -0
  197. package/dist/rest/expand.d.ts +6 -1
  198. package/dist/rest/expand.js +29 -11
  199. package/dist/rest/files.d.ts +439 -0
  200. package/dist/rest/files.js +107 -0
  201. package/dist/rest/json-form.d.ts +97 -0
  202. package/dist/rest/json-form.js +396 -0
  203. package/dist/rest/model.d.ts +35 -24
  204. package/dist/rest/model.js +6 -9
  205. package/dist/rest/module.d.ts +2 -0
  206. package/dist/rest/module.js +13 -0
  207. package/dist/rest/openapi/cache.d.ts +7 -2
  208. package/dist/rest/openapi/cache.js +2 -2
  209. package/dist/rest/openapi/import.d.ts +11 -16
  210. package/dist/rest/openapi/import.js +6 -2
  211. package/dist/rest/openapi/map.d.ts +38 -1
  212. package/dist/rest/openapi/map.js +151 -41
  213. package/dist/rest/openapi/match.d.ts +20 -0
  214. package/dist/rest/openapi/match.js +117 -0
  215. package/dist/rest/openapi/model.d.ts +33 -45
  216. package/dist/rest/openapi/parse.d.ts +3 -12
  217. package/dist/rest/openapi/parse.js +138 -67
  218. package/dist/rest/openapi/responses.d.ts +23 -0
  219. package/dist/rest/openapi/responses.js +59 -0
  220. package/dist/rest/openapi/runtime-expression.d.ts +69 -0
  221. package/dist/rest/openapi/runtime-expression.js +213 -0
  222. package/dist/rest/openapi/update.d.ts +116 -0
  223. package/dist/rest/openapi/update.js +456 -0
  224. package/dist/rest/postman/map.d.ts +1 -0
  225. package/dist/rest/postman/map.js +66 -4
  226. package/dist/rest/postman/model.d.ts +9 -0
  227. package/dist/rest/postman/parse.js +33 -10
  228. package/dist/rest/response.d.ts +2 -23
  229. package/dist/rest/response.js +3 -75
  230. package/dist/rest/run.d.ts +56 -0
  231. package/dist/rest/run.js +395 -0
  232. package/dist/rest/script-types.d.ts +7 -0
  233. package/dist/rest/script-types.js +83 -0
  234. package/dist/rest/scripting.d.ts +38 -0
  235. package/dist/rest/scripting.js +282 -0
  236. package/dist/rest/send-input.d.ts +54 -0
  237. package/dist/rest/send-input.js +73 -0
  238. package/dist/rest/send.d.ts +77 -4
  239. package/dist/rest/send.js +128 -7
  240. package/dist/rest/sse-transcript.d.ts +25 -0
  241. package/dist/rest/sse-transcript.js +95 -0
  242. package/dist/rest/sse.d.ts +43 -0
  243. package/dist/rest/sse.js +195 -0
  244. package/dist/rest/storage.d.ts +26 -0
  245. package/dist/rest/storage.js +262 -0
  246. package/dist/rest/url.d.ts +10 -4
  247. package/dist/rest/url.js +38 -5
  248. package/dist/run/baseline-update.d.ts +35 -0
  249. package/dist/run/baseline-update.js +97 -0
  250. package/dist/run/baseline.d.ts +42 -0
  251. package/dist/run/baseline.js +93 -0
  252. package/dist/run/context.d.ts +86 -0
  253. package/dist/run/context.js +31 -0
  254. package/dist/run/current-values.d.ts +32 -0
  255. package/dist/run/current-values.js +43 -0
  256. package/dist/run/event-queue.d.ts +14 -0
  257. package/dist/run/event-queue.js +46 -0
  258. package/dist/run/exchange.d.ts +62 -0
  259. package/dist/run/exchange.js +65 -0
  260. package/dist/run/host.d.ts +89 -0
  261. package/dist/run/host.js +1 -0
  262. package/dist/run/index.d.ts +20 -7
  263. package/dist/run/index.js +12 -4
  264. package/dist/run/oauth2-token.d.ts +42 -0
  265. package/dist/run/oauth2-token.js +92 -0
  266. package/dist/run/open.d.ts +12 -0
  267. package/dist/run/open.js +16 -0
  268. package/dist/run/run.d.ts +124 -4
  269. package/dist/run/run.js +293 -134
  270. package/dist/run/scope.d.ts +11 -0
  271. package/dist/run/scope.js +26 -0
  272. package/dist/run/script-support.d.ts +53 -0
  273. package/dist/run/script-support.js +68 -0
  274. package/dist/run/secret-needs.d.ts +11 -4
  275. package/dist/run/secret-needs.js +48 -96
  276. package/dist/run/select.d.ts +34 -25
  277. package/dist/run/select.js +45 -54
  278. package/dist/run/send-helpers.d.ts +93 -0
  279. package/dist/run/send-helpers.js +255 -0
  280. package/dist/run/tree.d.ts +50 -0
  281. package/dist/run/tree.js +54 -0
  282. package/dist/script/api/postman.d.ts +10 -0
  283. package/dist/script/api/postman.js +264 -0
  284. package/dist/script/api/prelude.d.ts +20 -0
  285. package/dist/script/api/prelude.js +215 -0
  286. package/dist/script/apply.d.ts +44 -0
  287. package/dist/script/apply.js +120 -0
  288. package/dist/script/check/host.d.ts +41 -0
  289. package/dist/script/check/host.js +143 -0
  290. package/dist/script/check/service.d.ts +52 -0
  291. package/dist/script/check/service.js +195 -0
  292. package/dist/script/check/worker.d.ts +1 -0
  293. package/dist/script/check/worker.js +40 -0
  294. package/dist/script/index.d.ts +16 -0
  295. package/dist/script/index.js +10 -0
  296. package/dist/script/lookup.d.ts +10 -0
  297. package/dist/script/lookup.js +23 -0
  298. package/dist/script/model.d.ts +82 -0
  299. package/dist/script/model.js +18 -0
  300. package/dist/script/props.d.ts +8 -0
  301. package/dist/script/props.js +28 -0
  302. package/dist/script/request-scripts.d.ts +83 -0
  303. package/dist/script/request-scripts.js +160 -0
  304. package/dist/script/run.d.ts +47 -0
  305. package/dist/script/run.js +146 -0
  306. package/dist/script/sandbox/execute.d.ts +26 -0
  307. package/dist/script/sandbox/execute.js +212 -0
  308. package/dist/script/sandbox/host-api.d.ts +27 -0
  309. package/dist/script/sandbox/host-api.js +101 -0
  310. package/dist/script/sandbox/host.d.ts +18 -0
  311. package/dist/script/sandbox/host.js +172 -0
  312. package/dist/script/sandbox/model.d.ts +69 -0
  313. package/dist/script/sandbox/model.js +24 -0
  314. package/dist/script/sandbox/worker.d.ts +1 -0
  315. package/dist/script/sandbox/worker.js +20 -0
  316. package/dist/script/send.d.ts +27 -0
  317. package/dist/script/send.js +76 -0
  318. package/dist/script/strip.d.ts +5 -0
  319. package/dist/script/strip.js +43 -0
  320. package/dist/script/types/api.d.ts +38 -0
  321. package/dist/script/types/api.js +113 -0
  322. package/dist/script/types/json-schema.d.ts +26 -0
  323. package/dist/script/types/json-schema.js +206 -0
  324. package/dist/secrets/env-names.d.ts +9 -1
  325. package/dist/secrets/env-names.js +17 -1
  326. package/dist/secrets/resolve.d.ts +44 -4
  327. package/dist/secrets/resolve.js +58 -1
  328. package/dist/secrets/scan/apply.d.ts +36 -0
  329. package/dist/secrets/scan/apply.js +194 -0
  330. package/dist/secrets/scan/rules.d.ts +32 -0
  331. package/dist/secrets/scan/rules.js +346 -0
  332. package/dist/secrets/scan/scan.d.ts +6 -0
  333. package/dist/secrets/scan/scan.js +57 -0
  334. package/dist/secrets/scan/walk.d.ts +70 -0
  335. package/dist/secrets/scan/walk.js +156 -0
  336. package/dist/secrets/secret-refs.d.ts +8 -0
  337. package/dist/secrets/secret-refs.js +25 -0
  338. package/dist/secrets/secret-token.d.ts +17 -0
  339. package/dist/secrets/secret-token.js +25 -0
  340. package/dist/sequence/file.d.ts +169 -0
  341. package/dist/sequence/file.js +237 -0
  342. package/dist/sequence/index.d.ts +7 -0
  343. package/dist/sequence/index.js +5 -0
  344. package/dist/sequence/load.d.ts +32 -0
  345. package/dist/sequence/load.js +56 -0
  346. package/dist/sequence/model.d.ts +115 -0
  347. package/dist/sequence/model.js +53 -0
  348. package/dist/sequence/run.d.ts +131 -0
  349. package/dist/sequence/run.js +191 -0
  350. package/dist/sequence/transfer.d.ts +24 -0
  351. package/dist/sequence/transfer.js +75 -0
  352. package/dist/server-api/audit.d.ts +455 -0
  353. package/dist/server-api/audit.js +186 -0
  354. package/dist/server-api/ci-tokens.d.ts +50 -0
  355. package/dist/server-api/ci-tokens.js +35 -0
  356. package/dist/server-api/hooks.d.ts +337 -0
  357. package/dist/server-api/hooks.js +152 -0
  358. package/dist/server-api/identity.d.ts +210 -0
  359. package/dist/server-api/identity.js +115 -0
  360. package/dist/server-api/licensing.d.ts +80 -0
  361. package/dist/server-api/licensing.js +53 -0
  362. package/dist/server-api/live.d.ts +132 -0
  363. package/dist/server-api/live.js +102 -0
  364. package/dist/server-api/meta.d.ts +31 -0
  365. package/dist/server-api/meta.js +21 -0
  366. package/dist/server-api/sync.d.ts +179 -0
  367. package/dist/server-api/sync.js +124 -0
  368. package/dist/server-api/teams.d.ts +306 -0
  369. package/dist/server-api/teams.js +113 -0
  370. package/dist/snapshot/diff.d.ts +30 -0
  371. package/dist/snapshot/diff.js +75 -0
  372. package/dist/snapshot/format.d.ts +17 -0
  373. package/dist/snapshot/format.js +40 -0
  374. package/dist/snapshot/golden-file.d.ts +45 -0
  375. package/dist/snapshot/golden-file.js +173 -0
  376. package/dist/snapshot/ignore.d.ts +14 -0
  377. package/dist/snapshot/ignore.js +79 -0
  378. package/dist/snapshot/index.d.ts +9 -0
  379. package/dist/snapshot/index.js +9 -0
  380. package/dist/snapshot/json-diff.d.ts +3 -0
  381. package/dist/snapshot/json-diff.js +93 -0
  382. package/dist/snapshot/xml-diff.d.ts +10 -0
  383. package/dist/snapshot/xml-diff.js +194 -0
  384. package/dist/soap/auth.d.ts +26 -0
  385. package/dist/soap/auth.js +54 -0
  386. package/dist/soap/curl.d.ts +20 -0
  387. package/dist/soap/curl.js +161 -0
  388. package/dist/soap/expand.d.ts +24 -0
  389. package/dist/soap/expand.js +95 -0
  390. package/dist/soap/files.d.ts +384 -0
  391. package/dist/soap/files.js +114 -0
  392. package/dist/soap/form-request.d.ts +13 -0
  393. package/dist/soap/form-request.js +2 -2
  394. package/dist/soap/generate.d.ts +12 -0
  395. package/dist/{generate.js → soap/generate.js} +4 -4
  396. package/dist/{import.d.ts → soap/import.d.ts} +4 -4
  397. package/dist/{import.js → soap/import.js} +13 -13
  398. package/dist/soap/json-operation.d.ts +35 -0
  399. package/dist/soap/json-operation.js +225 -0
  400. package/dist/soap/legacy-project/env-refs.d.ts +19 -0
  401. package/dist/soap/legacy-project/env-refs.js +105 -0
  402. package/dist/soap/legacy-project/map.d.ts +2 -2
  403. package/dist/soap/legacy-project/map.js +6 -0
  404. package/dist/soap/mime/multipart.d.ts +2 -2
  405. package/dist/soap/mime/multipart.js +2 -5
  406. package/dist/soap/mime/send-pipeline.d.ts +1 -1
  407. package/dist/soap/mime/send-pipeline.js +1 -1
  408. package/dist/soap/mime/types.d.ts +1 -3
  409. package/dist/soap/module.d.ts +2 -0
  410. package/dist/soap/module.js +13 -0
  411. package/dist/soap/namespace-scope.js +1 -1
  412. package/dist/soap/operations.d.ts +12 -0
  413. package/dist/{operations.js → soap/operations.js} +4 -4
  414. package/dist/soap/run.d.ts +70 -0
  415. package/dist/soap/run.js +549 -0
  416. package/dist/soap/script-types.d.ts +65 -0
  417. package/dist/soap/script-types.js +379 -0
  418. package/dist/soap/scripting.d.ts +45 -0
  419. package/dist/soap/scripting.js +221 -0
  420. package/dist/soap/send-input.d.ts +61 -0
  421. package/dist/{send-options.js → soap/send-input.js} +5 -109
  422. package/dist/{send.d.ts → soap/send.d.ts} +1 -1
  423. package/dist/{send.js → soap/send.js} +28 -12
  424. package/dist/soap/storage.d.ts +9 -0
  425. package/dist/soap/storage.js +237 -0
  426. package/dist/soap/transforms.d.ts +3 -12
  427. package/dist/soap/transforms.js +3 -14
  428. package/dist/{types.d.ts → soap/types.d.ts} +34 -84
  429. package/dist/sync/git-cli.d.ts +202 -0
  430. package/dist/sync/git-cli.js +684 -0
  431. package/dist/sync/three-way-merge.d.ts +41 -0
  432. package/dist/sync/three-way-merge.js +85 -0
  433. package/dist/sync/tree-paths.d.ts +34 -0
  434. package/dist/sync/tree-paths.js +131 -0
  435. package/dist/team-secrets/envelope.d.ts +10 -0
  436. package/dist/team-secrets/envelope.js +121 -0
  437. package/dist/team-secrets/errors.d.ts +26 -0
  438. package/dist/team-secrets/errors.js +27 -0
  439. package/dist/team-secrets/index.d.ts +14 -0
  440. package/dist/team-secrets/index.js +8 -0
  441. package/dist/team-secrets/keys.d.ts +52 -0
  442. package/dist/team-secrets/keys.js +158 -0
  443. package/dist/team-secrets/log.d.ts +48 -0
  444. package/dist/team-secrets/log.js +175 -0
  445. package/dist/team-secrets/resolve-conflict.d.ts +7 -0
  446. package/dist/team-secrets/resolve-conflict.js +14 -0
  447. package/dist/team-secrets/schema.d.ts +97 -0
  448. package/dist/team-secrets/schema.js +157 -0
  449. package/dist/team-secrets/sign.d.ts +24 -0
  450. package/dist/team-secrets/sign.js +71 -0
  451. package/dist/team-secrets/vault.d.ts +49 -0
  452. package/dist/team-secrets/vault.js +148 -0
  453. package/dist/validate/wsi/run-message.d.ts +2 -2
  454. package/dist/validate/wsi/run-message.js +1 -1
  455. package/dist/validate/wsi/run-wsdl.d.ts +2 -2
  456. package/dist/validate/wsi/run-wsdl.js +1 -1
  457. package/dist/validate/wsi/types.d.ts +1 -1
  458. package/dist/webhooks/model.d.ts +138 -0
  459. package/dist/webhooks/model.js +150 -0
  460. package/dist/workspace/commit-message.d.ts +1 -1
  461. package/dist/workspace/commit-message.js +6 -1
  462. package/dist/workspace/environments.d.ts +11 -4
  463. package/dist/workspace/environments.js +12 -0
  464. package/dist/workspace/index.d.ts +3 -3
  465. package/dist/workspace/index.js +2 -2
  466. package/dist/workspace/paths.d.ts +5 -2
  467. package/dist/workspace/paths.js +5 -2
  468. package/dist/workspace/schema.d.ts +7 -3
  469. package/dist/workspace/schema.js +24 -3
  470. package/dist/workspace/share.d.ts +30 -11
  471. package/dist/workspace/share.js +32 -6
  472. package/dist/ws/call.d.ts +1 -1
  473. package/dist/ws/call.js +2 -2
  474. package/dist/ws/connect.d.ts +60 -0
  475. package/dist/ws/connect.js +131 -0
  476. package/dist/ws/events.d.ts +17 -0
  477. package/dist/ws/events.js +1 -0
  478. package/dist/ws/expand.d.ts +1 -1
  479. package/dist/ws/expand.js +1 -1
  480. package/dist/ws/files.d.ts +284 -0
  481. package/dist/ws/files.js +71 -0
  482. package/dist/ws/history-entry.d.ts +44 -0
  483. package/dist/ws/history-entry.js +93 -0
  484. package/dist/ws/model.d.ts +44 -3
  485. package/dist/ws/model.js +3 -0
  486. package/dist/ws/module.d.ts +2 -0
  487. package/dist/ws/module.js +11 -0
  488. package/dist/ws/run.d.ts +63 -0
  489. package/dist/ws/run.js +470 -0
  490. package/dist/ws/session.d.ts +18 -0
  491. package/dist/ws/session.js +52 -25
  492. package/dist/ws/storage.d.ts +9 -0
  493. package/dist/ws/storage.js +176 -0
  494. package/dist/ws/transcript.d.ts +3 -4
  495. package/dist/ws/transcript.js +26 -17
  496. package/dist/ws/url.d.ts +1 -1
  497. package/dist/wsdl/cache.js +1 -1
  498. package/dist/wsdl/docs-generator.d.ts +3 -3
  499. package/dist/wsdl/docs-generator.js +1 -1
  500. package/dist/wsdl/export-definition.js +1 -1
  501. package/dist/wsdl/qname.d.ts +2 -5
  502. package/dist/wsdl/resolver.d.ts +4 -11
  503. package/dist/wsdl/resolver.js +3 -3
  504. package/dist/wsdl/update-definition.d.ts +5 -5
  505. package/dist/wsdl/update-definition.js +6 -6
  506. package/dist/wss/apply.js +1 -1
  507. package/dist/{project/wss-configs.d.ts → wss/configs.d.ts} +2 -2
  508. package/dist/{project/wss-configs.js → wss/configs.js} +2 -2
  509. package/dist/wss/incoming/decrypt.d.ts +1 -1
  510. package/dist/wss/incoming/index.js +1 -1
  511. package/dist/wss/incoming/verify.d.ts +1 -1
  512. package/dist/wss/incoming/verify.js +1 -1
  513. package/dist/wss/key-identifiers.js +1 -1
  514. package/dist/wss/model.d.ts +1 -1
  515. package/dist/wss/outgoing/encryption.d.ts +1 -1
  516. package/dist/wss/outgoing/signature.d.ts +1 -1
  517. package/dist/xml/decode.d.ts +15 -0
  518. package/dist/xml/decode.js +22 -0
  519. package/dist/xml/entitize.d.ts +17 -0
  520. package/dist/xml/entitize.js +19 -0
  521. package/dist/xml/index.d.ts +1 -1
  522. package/dist/xml/index.js +1 -1
  523. package/dist/xml/locate.d.ts +39 -0
  524. package/dist/xml/locate.js +117 -0
  525. package/dist/xml/qname.d.ts +12 -0
  526. package/dist/xml/qname.js +8 -0
  527. package/dist/xpath/evaluate-async.d.ts +19 -0
  528. package/dist/xpath/evaluate-async.js +31 -11
  529. package/dist/xpath/evaluate.d.ts +1 -1
  530. package/dist/xpath/namespaces.js +1 -1
  531. package/dist/xpath/worker.d.ts +11 -5
  532. package/dist/xpath/worker.js +24 -7
  533. package/dist/xsd/form-model.d.ts +19 -2
  534. package/dist/xsd/form-model.js +14 -2
  535. package/dist/xsd/json-bridge.d.ts +152 -0
  536. package/dist/xsd/json-bridge.js +1213 -0
  537. package/dist/xsd/locate.d.ts +2 -30
  538. package/dist/xsd/locate.js +1 -109
  539. package/dist/xsd/xml-scan.d.ts +2 -0
  540. package/dist/xsd/xml-scan.js +1 -1
  541. package/dist/xsd/xml-writer.d.ts +2 -0
  542. package/dist/xsd/xml-writer.js +4 -0
  543. package/package.json +12 -1
  544. package/dist/generate.d.ts +0 -12
  545. package/dist/operations.d.ts +0 -12
  546. package/dist/run/effective-auth.d.ts +0 -10
  547. package/dist/run/effective-auth.js +0 -19
  548. package/dist/run/prepare.d.ts +0 -43
  549. package/dist/run/prepare.js +0 -280
  550. package/dist/send-options.d.ts +0 -141
  551. package/dist/wsdl/fetch.d.ts +0 -13
  552. /package/dist/{soap → http}/charset.d.ts +0 -0
  553. /package/dist/{soap → http}/charset.js +0 -0
  554. /package/dist/{wsdl → http}/ref-policy.d.ts +0 -0
  555. /package/dist/{wsdl → http}/ref-policy.js +0 -0
  556. /package/dist/{wss/keystore → keystore}/certificate.d.ts +0 -0
  557. /package/dist/{wss/keystore → keystore}/certificate.js +0 -0
  558. /package/dist/{wss/keystore → keystore}/index.d.ts +0 -0
  559. /package/dist/{wss/keystore → keystore}/model.d.ts +0 -0
  560. /package/dist/{wss/keystore → keystore}/model.js +0 -0
  561. /package/dist/{wss/keystore → keystore}/pem.d.ts +0 -0
  562. /package/dist/{wss/keystore → keystore}/pkcs12.d.ts +0 -0
  563. /package/dist/{wsdl → project}/cache-naming.d.ts +0 -0
  564. /package/dist/{types.js → soap/types.js} +0 -0
  565. /package/dist/{soap → xml}/prefixes.d.ts +0 -0
  566. /package/dist/{soap → xml}/prefixes.js +0 -0
@@ -47,26 +47,5 @@ export interface PrettyBody {
47
47
  * broken body *is* the interesting thing when an API misbehaves, and hiding it would hide the bug.
48
48
  */
49
49
  export declare function prettyBody(text: string, language: BodyLanguage, indent?: number): PrettyBody;
50
- /** One cookie a response set, with the attributes it declared. */
51
- export interface Cookie {
52
- readonly name: string;
53
- readonly value: string;
54
- readonly domain?: string;
55
- readonly path?: string;
56
- /** As declared, in ISO form when it could be parsed; absent for a session cookie. */
57
- readonly expires?: string;
58
- readonly maxAge?: number;
59
- readonly secure?: boolean;
60
- readonly httpOnly?: boolean;
61
- readonly sameSite?: 'Strict' | 'Lax' | 'None';
62
- /** Set when the header could not be parsed as a cookie; `name` then holds the whole line. */
63
- readonly malformed?: boolean;
64
- }
65
- /**
66
- * Parses every `Set-Cookie` header of a response (RFC 6265 §5.2).
67
- *
68
- * `rawHeaders` rather than the merged map, because several cookies arrive as several headers and
69
- * joining them with `, ` — which is what merging does — makes them unparseable. A line that is not
70
- * a cookie at all is kept as `malformed` instead of dropped: it is evidence about the server.
71
- */
72
- export declare function parseSetCookie(rawHeaders: readonly (readonly [string, string])[]): Cookie[];
50
+ export { parseSetCookie } from '../http/cookies.js';
51
+ export type { Cookie } from '../http/cookies.js';
@@ -7,8 +7,8 @@
7
7
  * promised, a `Set-Cookie` with an attribute in the wrong order — and none of that may throw,
8
8
  * because the user still has to be able to look at it.
9
9
  */
10
- import { decodeBody } from '../soap/charset.js';
11
- import { mediaTypeOf } from '../soap/mime/multipart.js';
10
+ import { decodeBody } from '../http/charset.js';
11
+ import { mediaTypeOf } from '../http/media-type.js';
12
12
  import { formatXml } from '../xml/pretty.js';
13
13
  /**
14
14
  * The language of a response body.
@@ -146,76 +146,4 @@ function formatHtml(text, indent) {
146
146
  }
147
147
  return lines.join('\n');
148
148
  }
149
- /**
150
- * Parses every `Set-Cookie` header of a response (RFC 6265 §5.2).
151
- *
152
- * `rawHeaders` rather than the merged map, because several cookies arrive as several headers and
153
- * joining them with `, ` — which is what merging does — makes them unparseable. A line that is not
154
- * a cookie at all is kept as `malformed` instead of dropped: it is evidence about the server.
155
- */
156
- export function parseSetCookie(rawHeaders) {
157
- const cookies = [];
158
- for (const [name, value] of rawHeaders) {
159
- if (name.toLowerCase() !== 'set-cookie') {
160
- continue;
161
- }
162
- cookies.push(parseOne(value));
163
- }
164
- return cookies;
165
- }
166
- function parseOne(header) {
167
- const parts = header.split(';');
168
- const pair = parts[0] ?? '';
169
- const equals = pair.indexOf('=');
170
- if (equals <= 0) {
171
- return { name: header.trim(), value: '', malformed: true };
172
- }
173
- const cookie = {
174
- name: pair.slice(0, equals).trim(),
175
- value: unquote(pair.slice(equals + 1).trim()),
176
- };
177
- for (const attribute of parts.slice(1)) {
178
- const split = attribute.indexOf('=');
179
- const key = (split === -1 ? attribute : attribute.slice(0, split)).trim().toLowerCase();
180
- const attributeValue = split === -1 ? '' : attribute.slice(split + 1).trim();
181
- switch (key) {
182
- case 'domain':
183
- // A leading dot is legal and means the same as its absence (RFC 6265 §5.2.3).
184
- cookie.domain = attributeValue.replace(/^\./, '').toLowerCase();
185
- break;
186
- case 'path':
187
- cookie.path = attributeValue;
188
- break;
189
- case 'expires': {
190
- const date = new Date(attributeValue);
191
- cookie.expires = Number.isNaN(date.getTime()) ? attributeValue : date.toISOString();
192
- break;
193
- }
194
- case 'max-age': {
195
- const seconds = Number.parseInt(attributeValue, 10);
196
- if (!Number.isNaN(seconds)) {
197
- cookie.maxAge = seconds;
198
- }
199
- break;
200
- }
201
- case 'secure':
202
- cookie.secure = true;
203
- break;
204
- case 'httponly':
205
- cookie.httpOnly = true;
206
- break;
207
- case 'samesite': {
208
- const normalized = attributeValue.toLowerCase();
209
- cookie.sameSite = normalized === 'strict' ? 'Strict' : normalized === 'none' ? 'None' : 'Lax';
210
- break;
211
- }
212
- default:
213
- break;
214
- }
215
- }
216
- return cookie;
217
- }
218
- /** Strips one layer of double quotes from a cookie value, which some servers add. */
219
- function unquote(value) {
220
- return value.length > 1 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
221
- }
149
+ export { parseSetCookie } from '../http/cookies.js';
@@ -0,0 +1,56 @@
1
+ import type { AssertionSubject } from '../assert/model.js';
2
+ import type { AuthConfig, Project } from '../project/model.js';
3
+ import type { ProtocolRun } from '../protocol/module.js';
4
+ import type { RunContext } from '../run/context.js';
5
+ import type { Resolved } from '../run/send-helpers.js';
6
+ import type { EffectiveSigning } from '../webhooks/model.js';
7
+ import type { RestApi, RestFolder, RestRequestDef } from './model.js';
8
+ import type { RestExchange, RestSendInput } from './send.js';
9
+ /** One saved REST request, or one webhook item, selected for a run. */
10
+ export interface RestSelected {
11
+ readonly kind: 'rest';
12
+ readonly path: string;
13
+ readonly group: string;
14
+ readonly api: RestApi;
15
+ readonly chain: readonly RestFolder[];
16
+ readonly request: RestRequestDef;
17
+ /** A webhook item's effective signing (webhook-signatures §5.2); absent for an API request. */
18
+ readonly signing?: EffectiveSigning;
19
+ }
20
+ /** Innermost first, as the app's `authChainFor` builds it: request, its folders inside-out, the API. */
21
+ export declare function restEffectiveAuth(selected: RestSelected): AuthConfig;
22
+ /**
23
+ * One REST request resolved (spec §3.4): its properties and secret tokens expanded (the secrets
24
+ * behind `context.secretPlaceholders` when given), nothing connected and the credentials still as
25
+ * configured, so the input holds no `auth`. A reference nothing resolves is reported in
26
+ * `unresolved`, not thrown: the send refuses it, a preview shows it.
27
+ *
28
+ * A webhook item goes to its callback URL when the host names one: that URL is the whole
29
+ * destination, taken literally (ADR-0015), with no base. Otherwise it goes to its target, which
30
+ * must expand to an `http(s)` URL.
31
+ *
32
+ * @throws WirebenchError `secret-missing` | `rest-file-outside-project` | `webhook-target-missing` |
33
+ * `webhook-target-invalid`
34
+ */
35
+ export declare function resolveRest(selected: RestSelected, context: RunContext): Promise<Resolved<RestSendInput>>;
36
+ /**
37
+ * TLS, signing, credentials (an OAuth2 token included) and the proxy, over a resolved input: what
38
+ * a send does after its pre-request script, so the script never sees a credential (spec §7).
39
+ *
40
+ * @throws WirebenchError `secret-missing` | `auth-grant-unsupported` | `keystore-missing` |
41
+ * `webhook-signing-secret`
42
+ */
43
+ export declare function connectRest(selected: RestSelected, context: RunContext, input: RestSendInput): Promise<RestSendInput>;
44
+ /**
45
+ * A REST response as assertions and sequence transfers see it. A buffered event stream is the data
46
+ * of its events, in order, as a JSON array (spec §5.2).
47
+ */
48
+ export declare function restSubject(exchange: RestExchange): AssertionSubject;
49
+ /**
50
+ * The REST item for `requestId`, an API request or a webhook item, built as a run builds it — and
51
+ * found even when its contract no longer has it (`orphaned`), which a run skips and a person may
52
+ * still send. Undefined when no REST request has that id.
53
+ */
54
+ export declare function restItemFor(project: Project, requestId: string): RestSelected | undefined;
55
+ /** REST's run facet. */
56
+ export declare const restRun: ProtocolRun<RestSelected>;
@@ -0,0 +1,395 @@
1
+ /**
2
+ * REST's run facet (spec §3.3): the requests of every API, and the project's webhook items as a
3
+ * group a run sends only when a selector names it. A send resolves the request (its properties and
4
+ * secret tokens), runs its pre-request script, connects (its TLS identity, a webhook item's signing
5
+ * secret, its credentials with an OAuth2 token, the proxy), then goes on the wire (spec §3.4). A
6
+ * send that is not live reads an event stream to its end or the timeout (spec §5.2).
7
+ */
8
+ import { readFile } from 'node:fs/promises';
9
+ import { readAttachment } from '../project/attachments-cache.js';
10
+ import { REQUESTS_DIR, WEBHOOKS_DIR } from '../project/paths.js';
11
+ import { scopesFor } from '../run/context.js';
12
+ import { exchangeController } from '../run/exchange.js';
13
+ import { authFor, baseUrlFor, dropRefusedToken, insideProject, keystoreNeeds, originOf, tlsFor, unresolvedError, withSecrets, } from '../run/send-helpers.js';
14
+ import { ORPHANED_STEP_REASON, byOrder, findInTree, walkTree } from '../run/tree.js';
15
+ import { applyRestSnapshot, restRequestSnapshot, restResponseSnapshot } from './scripting.js';
16
+ import { createSseParser, isEventStream } from './sse.js';
17
+ import { loadOpenApiDocument, restOperationFor, restScriptTypes } from './script-types.js';
18
+ import { secretNeedsOfAuth } from '../secrets/env-names.js';
19
+ import { toRestSendInput } from './send-input.js';
20
+ import { assertWebhookTarget, effectiveSigning, effectiveTarget, signingSecretMissing, signingSecretRef, signingSourceLabel, } from '../webhooks/model.js';
21
+ import { resolveAuthChain } from '../http/auth/apply-auth.js';
22
+ import { expandRestSendInput } from './expand.js';
23
+ import { createApi } from './model.js';
24
+ import { sendRest } from './send.js';
25
+ import { joinBase } from './url.js';
26
+ /** Innermost first, as the app's `authChainFor` builds it: request, its folders inside-out, the API. */
27
+ export function restEffectiveAuth(selected) {
28
+ const { api, chain, request } = selected;
29
+ return resolveAuthChain([request.auth, ...[...chain].reverse().map((folder) => folder.auth), api.auth]);
30
+ }
31
+ /** A REST multipart file part or binary body, read from inside the project folder. */
32
+ function restFileResolver(context) {
33
+ return async (source) => source.kind === 'cache'
34
+ ? readAttachment(context.projectDir, source.sha256)
35
+ : new Uint8Array(await readFile(await insideProject(context, source.path, 'rest-file-outside-project', source.path)));
36
+ }
37
+ /**
38
+ * A webhook item's signing with its secret, or `undefined` when it signs nothing. The secret is
39
+ * read through the run's `GetSecret` (the CLI: `WIREBENCH_SECRET_<secretEnv>`), so it is masked
40
+ * like every other secret the run hands out.
41
+ *
42
+ * @throws WirebenchError `webhook-signing-secret` when signing is set and the secret is not given
43
+ */
44
+ async function signFor(selected, context) {
45
+ const effective = selected.signing;
46
+ if (effective === undefined || effective.signing.mode !== 'sign')
47
+ return undefined;
48
+ const ref = signingSecretRef(effective.signing);
49
+ const secret = ref === undefined ? undefined : await context.host.getSecret(ref);
50
+ if (secret === undefined || secret === '')
51
+ throw signingSecretMissing(effective, ref);
52
+ return { scheme: effective.signing.scheme, secret };
53
+ }
54
+ /**
55
+ * One REST request resolved (spec §3.4): its properties and secret tokens expanded (the secrets
56
+ * behind `context.secretPlaceholders` when given), nothing connected and the credentials still as
57
+ * configured, so the input holds no `auth`. A reference nothing resolves is reported in
58
+ * `unresolved`, not thrown: the send refuses it, a preview shows it.
59
+ *
60
+ * A webhook item goes to its callback URL when the host names one: that URL is the whole
61
+ * destination, taken literally (ADR-0015), with no base. Otherwise it goes to its target, which
62
+ * must expand to an `http(s)` URL.
63
+ *
64
+ * @throws WirebenchError `secret-missing` | `rest-file-outside-project` | `webhook-target-missing` |
65
+ * `webhook-target-invalid`
66
+ */
67
+ export async function resolveRest(selected, context) {
68
+ const { api, request } = selected;
69
+ const scopes = scopesFor(context);
70
+ const callbackUrl = isWebhookItem(selected) ? await context.host.callbackUrlFor?.(selected) : undefined;
71
+ const unexpanded = toRestSendInput({
72
+ request: {
73
+ method: request.method,
74
+ url: callbackUrl ?? request.url,
75
+ pathParams: request.pathParams,
76
+ query: request.query,
77
+ headers: request.headers,
78
+ body: request.body,
79
+ settings: request.settings,
80
+ },
81
+ baseUrl: callbackUrl !== undefined ? '' : baseUrlFor(context, api),
82
+ projectSettings: context.project.settings,
83
+ ...(context.host.preferences !== undefined ? { preferences: context.host.preferences } : {}),
84
+ resolveFile: restFileResolver(context),
85
+ ...(context.signal !== undefined ? { signal: context.signal } : {}),
86
+ });
87
+ const withTokens = await withSecrets(unexpanded, scopes, context.host.getSecret, context.secretPlaceholders);
88
+ const { input, unresolved } = expandRestSendInput(unexpanded, withTokens, {
89
+ escape: request.settings.escapeProperties === true,
90
+ ...(callbackUrl !== undefined ? { literalUrl: true } : {}),
91
+ });
92
+ // A target holding a secret still behind its placeholder is checked by nothing: its value is not in.
93
+ if (isWebhookItem(selected) &&
94
+ callbackUrl === undefined &&
95
+ context.secretPlaceholders?.holds(input.baseUrl) !== true) {
96
+ assertWebhookTarget(input.baseUrl, input.request.url, unresolved.length > 0);
97
+ }
98
+ return {
99
+ input: {
100
+ ...input,
101
+ ...(context.timeoutMs !== undefined ? { settings: { ...input.settings, timeoutMs: context.timeoutMs } } : {}),
102
+ },
103
+ unresolved,
104
+ };
105
+ }
106
+ /**
107
+ * TLS, signing, credentials (an OAuth2 token included) and the proxy, over a resolved input: what
108
+ * a send does after its pre-request script, so the script never sees a credential (spec §7).
109
+ *
110
+ * @throws WirebenchError `secret-missing` | `auth-grant-unsupported` | `keystore-missing` |
111
+ * `webhook-signing-secret`
112
+ */
113
+ export async function connectRest(selected, context, input) {
114
+ const { request } = selected;
115
+ const tls = await tlsFor(context, request.settings.sslKeystoreRef, request.settings.trustInvalid === true);
116
+ // As the app does: a webhook item's signing secret is read before any OAuth2 token is fetched.
117
+ const sign = await signFor(selected, context);
118
+ const auth = await authFor(restEffectiveAuth(selected), selected.path, context, tls);
119
+ // As the app does: the proxy is chosen for the base URL, or the request's own URL when there is none.
120
+ const proxy = await context.host.proxyFor?.(input.baseUrl === '' ? input.request.url : input.baseUrl);
121
+ return {
122
+ ...input,
123
+ ...(auth !== undefined ? { auth } : {}),
124
+ ...(tls !== undefined ? { tls: { ...input.tls, ...tls } } : {}),
125
+ ...(proxy !== undefined ? { proxy } : {}),
126
+ ...(sign !== undefined ? { sign } : {}),
127
+ };
128
+ }
129
+ /**
130
+ * The data of every event in a buffered event stream, in order: what a run read of the stream, to
131
+ * its end or the timeout. Undefined for any other response, and for one a live send streamed.
132
+ */
133
+ function bufferedEvents(exchange) {
134
+ if (exchange.stream !== undefined || !isEventStream(exchange.headers['content-type']))
135
+ return undefined;
136
+ const events = [];
137
+ const parser = createSseParser((row) => {
138
+ if (row.kind === 'event')
139
+ events.push(row.data);
140
+ });
141
+ parser.push(exchange.body, 0);
142
+ parser.end();
143
+ return events;
144
+ }
145
+ /**
146
+ * A REST response as assertions and sequence transfers see it. A buffered event stream is the data
147
+ * of its events, in order, as a JSON array (spec §5.2).
148
+ */
149
+ export function restSubject(exchange) {
150
+ const events = bufferedEvents(exchange);
151
+ return {
152
+ protocol: 'rest',
153
+ status: exchange.status,
154
+ durationMs: exchange.durationMs,
155
+ bodyText: events !== undefined ? JSON.stringify(events) : exchange.text,
156
+ bodyKind: events !== undefined || exchange.language === 'json' ? 'json' : exchange.language === 'xml' ? 'xml' : 'other',
157
+ headers: exchange.rawHeaders,
158
+ };
159
+ }
160
+ /** A webhook item's signing secret, read from `WIREBENCH_SECRET_<secretEnv>` (§5.2). */
161
+ function signingNeeds(selected) {
162
+ const effective = selected.signing;
163
+ if (effective === undefined || effective.signing.mode !== 'sign')
164
+ return [];
165
+ const ref = signingSecretRef(effective.signing);
166
+ if (ref === undefined)
167
+ return [];
168
+ return [
169
+ {
170
+ ref,
171
+ ...(effective.signing.secretEnv !== undefined ? { envName: effective.signing.secretEnv } : {}),
172
+ purpose: `webhook signing secret (${signingSourceLabel(effective)})`,
173
+ },
174
+ ];
175
+ }
176
+ /**
177
+ * An API's requests in explorer order, without the ones its contract no longer has unless
178
+ * `orphaned` asks for them too.
179
+ */
180
+ function apiCandidates(api, orphaned = false) {
181
+ const out = [];
182
+ walkTree(api, [], api.name, `apis/${api.slug}/requests`, (request, chain, group) => request.orphaned === true && !orphaned
183
+ ? undefined
184
+ : { kind: 'rest', path: `${group}/${request.name}`, group, api, chain, request }, out);
185
+ return out;
186
+ }
187
+ /** True for a webhook item, which `webhookCandidates` builds against the synthetic `webhooks` API. */
188
+ function isWebhookItem(selected) {
189
+ return selected.api.id === 'webhooks';
190
+ }
191
+ /**
192
+ * The project's webhook items, as REST items against a synthetic API whose base URL is each item's
193
+ * effective target. A run has no history, so a callback uses the target.
194
+ */
195
+ function webhookCandidates(collection, orphaned = false) {
196
+ const out = [];
197
+ const visit = (folders, requests, chain) => {
198
+ const group = ['Webhooks', ...chain.map((folder) => folder.name)].join('/');
199
+ const dir = [WEBHOOKS_DIR, REQUESTS_DIR, ...chain.map((folder) => folder.slug)].join('/');
200
+ const api = createApi('Webhooks', {
201
+ id: 'webhooks',
202
+ slug: 'webhooks',
203
+ baseUrl: effectiveTarget(collection, chain),
204
+ ...(collection.auth !== undefined ? { auth: collection.auth } : {}),
205
+ });
206
+ for (const request of [...requests].sort(byOrder)) {
207
+ if (request.orphaned === true && !orphaned)
208
+ continue;
209
+ out.push({
210
+ item: {
211
+ kind: 'rest',
212
+ path: `${group}/${request.name}`,
213
+ group,
214
+ api,
215
+ chain,
216
+ request,
217
+ signing: effectiveSigning(collection, request.id),
218
+ },
219
+ diskPath: `${dir}/${request.slug}`,
220
+ });
221
+ }
222
+ for (const folder of [...folders].sort(byOrder))
223
+ visit(folder.folders, folder.requests, [...chain, folder]);
224
+ };
225
+ visit(collection.folders, collection.requests, []);
226
+ return out;
227
+ }
228
+ /**
229
+ * The REST item for `requestId`, an API request or a webhook item, built as a run builds it — and
230
+ * found even when its contract no longer has it (`orphaned`), which a run skips and a person may
231
+ * still send. Undefined when no REST request has that id.
232
+ */
233
+ export function restItemFor(project, requestId) {
234
+ const candidates = [
235
+ ...project.apis.flatMap((api) => apiCandidates(api, true)),
236
+ ...(project.webhooks !== undefined ? webhookCandidates(project.webhooks, true) : []),
237
+ ];
238
+ return candidates.find((candidate) => candidate.item.request.id === requestId)?.item;
239
+ }
240
+ /** What a failed send was about to put on the wire: the resolved URL, the method, the enabled headers. */
241
+ function attemptedOf(input) {
242
+ return {
243
+ url: joinBase(input.baseUrl, input.request.url),
244
+ method: input.request.method,
245
+ headers: Object.fromEntries(input.request.headers.filter((header) => header.enabled).map((header) => [header.name, header.value])),
246
+ };
247
+ }
248
+ /**
249
+ * Resolves, connects and sends one request, telling the host when either stage fails, then hands
250
+ * the response's cookies and its contract result to the host. A reference nothing resolves is
251
+ * refused in the prepare stage, with what would have been sent; a failure before resolve has an
252
+ * input is reported with nothing attempted.
253
+ */
254
+ async function connectAndSend(selected, context, resolve, controller, live,
255
+ /** The pre-request script's step, inside the prepare stage so its failure is reported with it. */
256
+ script) {
257
+ let startedAt = Date.now();
258
+ // Never masks the send's own error: a row that cannot be built, or a host that throws, is dropped.
259
+ const failed = (stage, error, attempted) => {
260
+ try {
261
+ context.host.events?.onFailed?.(selected, {
262
+ stage,
263
+ error,
264
+ startedAt,
265
+ durationMs: Date.now() - startedAt,
266
+ ...(attempted !== undefined ? { attempted: attemptedOf(attempted), input: attempted } : {}),
267
+ });
268
+ }
269
+ catch {
270
+ // Deliberately ignored — see above.
271
+ }
272
+ };
273
+ let input;
274
+ let connected;
275
+ try {
276
+ const resolved = await resolve();
277
+ input = resolved.input;
278
+ if (resolved.unresolved.length > 0) {
279
+ throw unresolvedError('rest-unresolved-properties', selected.path, resolved.unresolved);
280
+ }
281
+ connected = await connectRest(selected, context, script !== undefined ? await script(input) : input);
282
+ }
283
+ catch (error) {
284
+ failed('prepare', error, input);
285
+ throw error;
286
+ }
287
+ // The send stage's own clock: a send-stage failure never counts resolve, the script, the token or the proxy.
288
+ startedAt = Date.now();
289
+ let exchange;
290
+ try {
291
+ exchange = await sendRest({
292
+ ...connected,
293
+ signal: controller.signal,
294
+ // Not part of `connected`, which History and the log keep: the jar is the host's, per send.
295
+ ...(context.host.cookies !== undefined
296
+ ? { jar: { host: context.host.cookies, send: selected.request.settings.sendCookies === true } }
297
+ : {}),
298
+ // Only a live send parses an event stream; any other keeps the buffered body.
299
+ ...(live
300
+ ? {
301
+ onStream: {
302
+ onOpen: (status, headers) => controller.queue.push({ protocol: 'rest', kind: 'open', status, headers }),
303
+ onRow: (row) => controller.queue.push({ protocol: 'rest', kind: 'row', row }),
304
+ },
305
+ }
306
+ : {}),
307
+ });
308
+ }
309
+ catch (error) {
310
+ failed('send', error, connected);
311
+ throw error;
312
+ }
313
+ dropRefusedToken(context, connected.auth, exchange.status === 401);
314
+ // The request has gone out: a contract check that rejects checked nothing, and fails nothing.
315
+ const contract = await context.host.contractFor?.(selected, exchange, connected).catch(() => undefined);
316
+ return {
317
+ connected,
318
+ sent: {
319
+ subject: restSubject(exchange),
320
+ raw: exchange,
321
+ exchange: { kind: 'rest', rest: exchange, input: connected, ...(contract !== undefined ? { contract } : {}) },
322
+ ...originOf(exchange.request.url),
323
+ },
324
+ };
325
+ }
326
+ /**
327
+ * One REST request as a run sends it (spec §3.4): resolve, run its pre-request script when
328
+ * `scripts` is given, connect, send, then its post-response script.
329
+ */
330
+ async function sendRestItem(selected, context, scripts, controller, live) {
331
+ if (scripts === undefined) {
332
+ return (await connectAndSend(selected, context, () => resolveRest(selected, context), controller, live)).sent;
333
+ }
334
+ // Resolved with its secrets behind placeholders; the URL is rebuilt only when the script changed it.
335
+ const resolve = () => resolveRest(selected, { ...context, secretPlaceholders: scripts.placeholders });
336
+ let sent;
337
+ const result = await connectAndSend(selected, context, resolve, controller, live, async (input) => {
338
+ const before = restRequestSnapshot(input);
339
+ sent = await scripts.session.pre(before);
340
+ const changed = applyRestSnapshot(input, before, sent);
341
+ const restored = await scripts.placeholders.restore({ baseUrl: changed.baseUrl, request: changed.request }, context.host.getSecret);
342
+ return { ...changed, ...restored };
343
+ });
344
+ const exchange = result.sent.raw;
345
+ return {
346
+ ...result.sent,
347
+ script: await scripts.session.post(sent, restResponseSnapshot(exchange)),
348
+ };
349
+ }
350
+ /** REST's run facet. */
351
+ export const restRun = {
352
+ groups(project) {
353
+ const apis = project.apis.map((api) => ({
354
+ order: api.order,
355
+ name: api.name,
356
+ candidates: apiCandidates(api),
357
+ }));
358
+ // Webhook items deliver to a receiver rather than test an API: sent only when a selector names one.
359
+ return project.webhooks === undefined
360
+ ? apis
361
+ : [...apis, { order: 0, name: 'Webhooks', candidates: webhookCandidates(project.webhooks), explicitOnly: true }];
362
+ },
363
+ whyNotRunnable(project, requestId) {
364
+ if (project.webhooks !== undefined && findInTree(project.webhooks, requestId) !== undefined) {
365
+ return 'A webhook cannot be a sequence step';
366
+ }
367
+ for (const api of project.apis) {
368
+ const request = findInTree(api, requestId);
369
+ if (request !== undefined) {
370
+ return request.orphaned === true ? ORPHANED_STEP_REASON : undefined;
371
+ }
372
+ }
373
+ return undefined;
374
+ },
375
+ open(selected, scope, host, options) {
376
+ const controller = exchangeController('rest', options);
377
+ const context = { ...scope.context, host, signal: controller.signal };
378
+ return controller.handle(() => sendRestItem(selected, context, options.scripts, controller, options.live === true));
379
+ },
380
+ resolve(selected, scope, host) {
381
+ return resolveRest(selected, { ...scope.context, host });
382
+ },
383
+ async scriptTypes(selected, scope) {
384
+ const { api } = selected;
385
+ const openApi = await scope.memo(`rest:${api.id}:openapi`, () => loadOpenApiDocument(scope.context.projectDir, api.slug));
386
+ return { generated: restScriptTypes(restOperationFor(openApi, selected.request.contract)) };
387
+ },
388
+ secretNeeds(selected, project) {
389
+ return [
390
+ ...secretNeedsOfAuth(restEffectiveAuth(selected)),
391
+ ...keystoreNeeds(project, selected.request.settings.sslKeystoreRef),
392
+ ...signingNeeds(selected),
393
+ ];
394
+ },
395
+ };
@@ -0,0 +1,7 @@
1
+ import type { RestContractLink } from './model.js';
2
+ import type { OpenApiDocument, OpenApiOperation } from './openapi/model.js';
3
+ export declare function restScriptTypes(operation: OpenApiOperation | undefined): string;
4
+ /** The operation a REST request is linked to, by its method and templated path. */
5
+ export declare function restOperationFor(document: OpenApiDocument | undefined, contract: RestContractLink | undefined): OpenApiOperation | undefined;
6
+ /** An API's cached OpenAPI document, read offline; `undefined` when it has none or it cannot be read. */
7
+ export declare function loadOpenApiDocument(projectDir: string, apiSlug: string): Promise<OpenApiDocument | undefined>;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * A REST request's script types, from the OpenAPI operation it is linked to (spec §Types, REST).
3
+ *
4
+ * `WbRequestBody` is the JSON request body's type. `WbResponse` is a union with one arm per declared
5
+ * status. Each arm's `status` is a set of literals — one code, a range less the codes declared on
6
+ * their own, or everything left for `default` — so `response.status === 200` narrows `json()` exactly,
7
+ * and a status the contract does not declare falls into a last arm whose body is `unknown`.
8
+ */
9
+ import { ProjectError } from '../errors.js';
10
+ import { apiDefinitionDir } from '../project/paths.js';
11
+ import { JsonSchemaTypes } from '../script/types/json-schema.js';
12
+ import { createCachedApiFetch, readApiDefinitionCache } from './openapi/cache.js';
13
+ import { parseOpenApi } from './openapi/import.js';
14
+ /** The JSON media type among a content map's keys, if any. */
15
+ function jsonMedia(content) {
16
+ if (content === undefined) {
17
+ return undefined;
18
+ }
19
+ const key = Object.keys(content).find((k) => /^application\/json\b/i.test(k)) ??
20
+ Object.keys(content).find((k) => /\+json\b/i.test(k));
21
+ return key === undefined ? undefined : content[key];
22
+ }
23
+ export function restScriptTypes(operation) {
24
+ if (operation === undefined) {
25
+ return [
26
+ '// This request is not linked to an operation of its API, so its bodies are untyped.',
27
+ 'type WbRequestBody = unknown;',
28
+ 'type WbResponse = WbResponseArm<WbStatus, unknown>;',
29
+ '',
30
+ ].join('\n');
31
+ }
32
+ const types = new JsonSchemaTypes();
33
+ const requestMedia = jsonMedia(operation.requestBody?.content);
34
+ const requestBody = requestMedia?.schema !== undefined ? types.typeOf(requestMedia.schema) : 'unknown';
35
+ const responses = operation.responses ?? {};
36
+ const exact = Object.keys(responses).filter((key) => /^[1-5]\d\d$/.test(key));
37
+ const ranges = Object.keys(responses).filter((key) => /^[1-5]XX$/i.test(key));
38
+ const exactUnion = exact.length > 0 ? exact.join(' | ') : 'never';
39
+ const rangeTypes = ranges.map((key) => `WbRange${key[0]}`);
40
+ const arms = [];
41
+ const bodyOf = (key) => {
42
+ const media = jsonMedia(responses[key]?.content);
43
+ return media?.schema !== undefined ? types.typeOf(media.schema) : 'unknown';
44
+ };
45
+ for (const key of exact) {
46
+ arms.push(`WbResponseArm<${key}, ${bodyOf(key)}>`);
47
+ }
48
+ for (const key of ranges) {
49
+ arms.push(`WbResponseArm<Exclude<WbRange${key[0]}, ${exactUnion}>, ${bodyOf(key)}>`);
50
+ }
51
+ const covered = [exactUnion, ...rangeTypes].filter((t) => t !== 'never').join(' | ') || 'never';
52
+ const rest = `Exclude<WbStatus, ${covered}>`;
53
+ arms.push(`WbResponseArm<${rest}, ${responses['default'] !== undefined ? bodyOf('default') : 'unknown'}>`);
54
+ const where = `${operation.method.toUpperCase()} ${operation.path}`.replace(/\*\//g, '*\\/');
55
+ return [
56
+ `// Types from the contract's ${where}.`,
57
+ types.declarations(),
58
+ `type WbRequestBody = ${requestBody};`,
59
+ `type WbResponse =\n | ${arms.join('\n | ')};`,
60
+ '',
61
+ ].join('\n');
62
+ }
63
+ /** The operation a REST request is linked to, by its method and templated path. */
64
+ export function restOperationFor(document, contract) {
65
+ if (document === undefined || contract === undefined)
66
+ return undefined;
67
+ return document.operations.find((op) => op.method.toLowerCase() === contract.method.toLowerCase() && op.path === contract.path);
68
+ }
69
+ /** An API's cached OpenAPI document, read offline; `undefined` when it has none or it cannot be read. */
70
+ export async function loadOpenApiDocument(projectDir, apiSlug) {
71
+ const dir = apiDefinitionDir(projectDir, apiSlug);
72
+ try {
73
+ const cached = await readApiDefinitionCache(dir);
74
+ const offline = createCachedApiFetch(cached.manifest, dir, (location) => Promise.reject(new ProjectError('definition-cache-missing', `"${location}" is not in this API's definition cache`, {
75
+ details: { location },
76
+ })));
77
+ const parsed = await parseOpenApi({ kind: 'url', url: cached.manifest.rootLocation }, { fetchDocument: offline });
78
+ return parsed.document;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }