@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
@@ -0,0 +1,262 @@
1
+ /**
2
+ * How REST APIs are stored in a project folder (spec §3.2): `apis/<slug>/api.yaml` with
3
+ * `kind: rest`, and a tree of folders and `*.request.yaml` files under `requests/`, a raw body in
4
+ * the sibling `<slug>.body.<ext>`.
5
+ *
6
+ * `restRequestReader` and `signingOf` are exported for core's loader, which reads the project's
7
+ * webhook collection (REST requests in a tree of their own) until phase 3 of #184 moves it here.
8
+ */
9
+ import { toCallbackAssertion } from '../assert/schema.js';
10
+ import { ProjectError } from '../errors.js';
11
+ import { readFileIfExists } from '../project/fs.js';
12
+ import { abs, authConfig, definitionAuth, exact, keyValueEntries, loadFolderContents, loadScripts, optional, readYaml, } from '../project/load-helpers.js';
13
+ import { apiManagedFiles } from '../project/managed-files.js';
14
+ import { API_FILE, APIS_DIR, assertPathSegment, REQUEST_SUFFIX, REQUESTS_DIR, restBodyFileName, WEBHOOKS_DIR, } from '../project/paths.js';
15
+ import { assertSupportedKind, parseFile } from '../project/schema-parts.js';
16
+ import { addFolderFiles, authDocument, definitionDocument, keyValueDocuments, scriptsDocument, writeScriptFiles, } from '../project/serialize-helpers.js';
17
+ import { compact, stringifyYaml } from '../project/yaml.js';
18
+ import { toSignatureScheme } from '../http/webhook-signature.js';
19
+ import { apiFileSchema, restRequestFileSchema } from './files.js';
20
+ import { RAW_LANGUAGE_EXTENSIONS } from './model.js';
21
+ /** A parsed `signing` key as the model holds it. */
22
+ export function signingOf(parsed) {
23
+ if (parsed.mode === 'none')
24
+ return { mode: 'none' };
25
+ return {
26
+ mode: 'sign',
27
+ scheme: toSignatureScheme(parsed.scheme),
28
+ ...optional('secretRef', parsed.secretRef),
29
+ ...optional('secretEnv', parsed.secretEnv),
30
+ };
31
+ }
32
+ /**
33
+ * One request body as loaded. A raw body's text lives in a sibling file, so it is read here and
34
+ * the file name is dropped: the model holds the text, the layout holds the name
35
+ * (`project/paths.ts` rebuilds it on save from the language).
36
+ */
37
+ async function loadBody(fs, root, dir, document, requestName, problems) {
38
+ switch (document.kind) {
39
+ case 'raw': {
40
+ // The name comes from the request file, which a pull or an import may have written: it must
41
+ // name a file beside the request, never one elsewhere on the machine (`../…`).
42
+ assertPathSegment(document.file);
43
+ const relative = `${dir}/${document.file}`;
44
+ const text = await readFileIfExists(fs, abs(root, relative));
45
+ if (text === undefined) {
46
+ problems.push({
47
+ code: 'missing-body',
48
+ message: `Request "${requestName}" has no body file; loaded with an empty body`,
49
+ file: relative,
50
+ });
51
+ }
52
+ return {
53
+ kind: 'raw',
54
+ language: document.language,
55
+ ...optional('contentType', document.contentType),
56
+ text: text === undefined ? '' : text.toString('utf8'),
57
+ };
58
+ }
59
+ case 'form':
60
+ return { kind: 'form', fields: keyValueEntries(document.fields) };
61
+ case 'multipart':
62
+ return {
63
+ kind: 'multipart',
64
+ parts: document.parts.map((part) => part.kind === 'text'
65
+ ? exact({ ...part, kind: 'text' })
66
+ : exact({ ...part, kind: 'file' })),
67
+ };
68
+ case 'binary':
69
+ return { kind: 'binary', source: document.source, contentType: document.contentType };
70
+ default:
71
+ return { kind: 'none' };
72
+ }
73
+ }
74
+ /** Reads a REST request and its raw body file. */
75
+ export function restRequestReader(fs, root, problems) {
76
+ return async (dir, fileName, unclaimed) => {
77
+ const relative = `${dir}/${fileName}`;
78
+ const document = await readYaml(fs, root, relative);
79
+ assertSupportedKind(document, relative);
80
+ const parsed = parseFile(restRequestFileSchema, document, relative);
81
+ unclaimed.delete(fileName);
82
+ if (parsed.body.kind === 'raw') {
83
+ unclaimed.delete(parsed.body.file);
84
+ }
85
+ const slug = fileName.slice(0, -REQUEST_SUFFIX.length);
86
+ const scripts = await loadScripts(fs, root, dir, slug, parsed.scripts, parsed.name, problems, (name) => unclaimed.delete(name));
87
+ return {
88
+ kind: 'rest',
89
+ id: parsed.id,
90
+ name: parsed.name,
91
+ slug,
92
+ order: parsed.order,
93
+ ...optional('description', parsed.description),
94
+ method: parsed.method,
95
+ url: parsed.url,
96
+ pathParams: keyValueEntries(parsed.pathParams),
97
+ query: keyValueEntries(parsed.query),
98
+ headers: keyValueEntries(parsed.headers),
99
+ body: await loadBody(fs, root, dir, parsed.body, parsed.name, problems),
100
+ auth: authConfig(parsed.auth),
101
+ settings: exact(parsed.settings),
102
+ assertions: parsed.assertions.map((a) => (a.type === 'callback' ? toCallbackAssertion(a) : exact(a))),
103
+ ...(parsed.orphaned === true ? { orphaned: true } : {}),
104
+ ...(parsed.contract !== undefined
105
+ ? { contract: { method: parsed.contract.method, path: parsed.contract.path } }
106
+ : {}),
107
+ ...(parsed.hook !== undefined ? { hook: exact(parsed.hook) } : {}),
108
+ ...(parsed.signing !== undefined ? { signing: signingOf(parsed.signing) } : {}),
109
+ ...(scripts !== undefined ? { scripts } : {}),
110
+ };
111
+ };
112
+ }
113
+ /** A REST request under `apis/`: the same as {@link restRequestReader}, but a `hook` or `signing` has no place there. */
114
+ function apiRequestReader(fs, root, problems) {
115
+ const read = restRequestReader(fs, root, problems);
116
+ return async (dir, fileName, unclaimed) => {
117
+ const request = await read(dir, fileName, unclaimed);
118
+ const misplaced = request.hook !== undefined ? 'hook' : request.signing !== undefined ? 'signing' : undefined;
119
+ if (misplaced !== undefined) {
120
+ const file = `${dir}/${fileName}`;
121
+ throw new ProjectError('project-file-invalid', `Invalid project file ${file}: ${misplaced} is only allowed under ${WEBHOOKS_DIR}/`, {
122
+ details: { file, issues: [{ path: misplaced, message: `only allowed under ${WEBHOOKS_DIR}/` }] },
123
+ });
124
+ }
125
+ return request;
126
+ };
127
+ }
128
+ /** A `signing` key as written: the scheme's own fields, and references only. */
129
+ export function signingDocument(signing) {
130
+ if (signing === undefined)
131
+ return undefined;
132
+ if (signing.mode === 'none')
133
+ return { mode: 'none' };
134
+ return compact({
135
+ mode: 'sign',
136
+ scheme: compact({ ...signing.scheme }),
137
+ secretRef: signing.secretRef,
138
+ secretEnv: signing.secretEnv,
139
+ });
140
+ }
141
+ /**
142
+ * A body as written, plus the sibling file a raw body needs.
143
+ *
144
+ * The text of a raw body is deliberately *not* in the request document: it goes to
145
+ * `<slug>.body.<ext>` beside it, so a JSON payload is a JSON file in git — reviewable, searchable
146
+ * and mergeable — rather than a quoted blob inside YAML.
147
+ */
148
+ function bodyDocument(body, requestSlug) {
149
+ switch (body.kind) {
150
+ case 'raw': {
151
+ const name = restBodyFileName(requestSlug, RAW_LANGUAGE_EXTENSIONS[body.language]);
152
+ assertPathSegment(name);
153
+ return {
154
+ document: compact({ kind: 'raw', language: body.language, contentType: body.contentType, file: name }),
155
+ file: [name, body.text],
156
+ };
157
+ }
158
+ case 'form':
159
+ return { document: { kind: 'form', fields: keyValueDocuments(body.fields) } };
160
+ case 'multipart':
161
+ return {
162
+ document: {
163
+ kind: 'multipart',
164
+ parts: body.parts.map((part) => compact({ ...part, enabled: part.enabled ? undefined : false })),
165
+ },
166
+ };
167
+ case 'binary':
168
+ return { document: { kind: 'binary', source: { ...body.source }, contentType: body.contentType } };
169
+ default:
170
+ return { document: { kind: 'none' } };
171
+ }
172
+ }
173
+ function restRequestDocument(request) {
174
+ const body = bodyDocument(request.body, request.slug);
175
+ return compact({
176
+ kind: request.kind,
177
+ id: request.id,
178
+ name: request.name,
179
+ order: request.order,
180
+ description: request.description,
181
+ method: request.method,
182
+ url: request.url,
183
+ pathParams: request.pathParams.length > 0 ? keyValueDocuments(request.pathParams) : undefined,
184
+ query: request.query.length > 0 ? keyValueDocuments(request.query) : undefined,
185
+ headers: request.headers.length > 0 ? keyValueDocuments(request.headers) : undefined,
186
+ body: body.document,
187
+ auth: authDocument(request.auth),
188
+ settings: Object.keys(request.settings).length > 0 ? compact({ ...request.settings }) : undefined,
189
+ assertions: request.assertions.length > 0 ? request.assertions.map((a) => compact({ ...a })) : undefined,
190
+ orphaned: request.orphaned === true ? true : undefined,
191
+ contract: request.contract === undefined ? undefined : { method: request.contract.method, path: request.contract.path },
192
+ hook: request.hook === undefined ? undefined : { ...request.hook },
193
+ signing: signingDocument(request.signing),
194
+ scripts: scriptsDocument(request.scripts, request.slug).document,
195
+ });
196
+ }
197
+ /** A REST request as written: its document, its raw body file and its script files. Core writes the webhook collection's items with it. */
198
+ export const writeRestRequest = (files, dir, request) => {
199
+ const body = bodyDocument(request.body, request.slug);
200
+ files.set(`${dir}/${request.slug}${REQUEST_SUFFIX}`, stringifyYaml(restRequestDocument(request)));
201
+ if (body.file !== undefined) {
202
+ files.set(`${dir}/${body.file[0]}`, body.file[1]);
203
+ }
204
+ writeScriptFiles(files, dir, request.scripts, request.slug);
205
+ };
206
+ /** Every file one REST API occupies, keyed by path relative to the project root. */
207
+ function addApiFiles(files, api) {
208
+ assertPathSegment(api.slug);
209
+ const base = `${APIS_DIR}/${api.slug}`;
210
+ files.set(`${base}/${API_FILE}`, stringifyYaml(compact({
211
+ kind: api.kind,
212
+ id: api.id,
213
+ name: api.name,
214
+ order: api.order,
215
+ description: api.description,
216
+ baseUrl: api.baseUrl,
217
+ servers: api.servers.length > 0 ? api.servers.map((server) => compact({ ...server })) : undefined,
218
+ auth: api.auth === undefined ? undefined : authDocument(api.auth),
219
+ definition: api.definition === undefined ? undefined : definitionDocument(api.definition),
220
+ })));
221
+ addFolderFiles(files, `${base}/${REQUESTS_DIR}`, api, 0, writeRestRequest);
222
+ }
223
+ /** REST's storage facet. */
224
+ export const restStorage = {
225
+ dir: APIS_DIR,
226
+ async load(ctx, slug, document) {
227
+ const { fs, root, problems } = ctx;
228
+ const parsed = parseFile(apiFileSchema, document, `${APIS_DIR}/${slug}/${API_FILE}`);
229
+ const contents = await loadFolderContents(fs, root, `${APIS_DIR}/${slug}/${REQUESTS_DIR}`, 0, problems, apiRequestReader(fs, root, problems));
230
+ return {
231
+ kind: 'rest',
232
+ id: parsed.id,
233
+ name: parsed.name,
234
+ slug,
235
+ order: parsed.order,
236
+ ...optional('description', parsed.description),
237
+ baseUrl: parsed.baseUrl,
238
+ servers: parsed.servers.map((server) => exact(server)),
239
+ ...(parsed.auth !== undefined ? { auth: authConfig(parsed.auth) } : {}),
240
+ ...(parsed.definition !== undefined
241
+ ? {
242
+ definition: {
243
+ source: parsed.definition.source,
244
+ cache: parsed.definition.cache,
245
+ version: parsed.definition.version,
246
+ ...optional('auth', definitionAuth(parsed.definition.auth)),
247
+ },
248
+ }
249
+ : {}),
250
+ folders: contents.folders,
251
+ requests: contents.requests,
252
+ };
253
+ },
254
+ files(api) {
255
+ const files = new Map();
256
+ addApiFiles(files, api);
257
+ return files;
258
+ },
259
+ managed: (fs, root, slug) => apiManagedFiles(fs, root, slug),
260
+ containers: (project) => project.apis,
261
+ withContainers: (project, apis) => ({ ...project, apis }),
262
+ };
@@ -80,13 +80,19 @@ export declare function joinQuery(path: string, query: readonly KeyValueEntry[])
80
80
  * Builds the URL one send actually uses.
81
81
  *
82
82
  * Order of work: the request's URL wins over the base when it is absolute; `{name}` parameters are
83
- * filled from the enabled rows of `pathParams`; the URL's own query string and the `query` table
84
- * are concatenated, in that order, so a parameter typed into the field and one added in the table
85
- * both survive; every value is encoded unless `encode` is off.
83
+ * filled from the enabled rows of `pathParams`; the query is the enabled `query` rows, preceded by
84
+ * any parameter of the URL's own query string that no enabled row carries; every value is encoded
85
+ * unless `encode` is off.
86
+ *
87
+ * The table owns the query. The editor mirrors it into the URL field, so a saved request usually
88
+ * holds each parameter twice — once in `url`, once as a row — and sending both would send it twice.
89
+ * A URL parameter with the same name and value as an enabled row is that row, matched one for one
90
+ * so deliberate duplicates survive. One no row carries (a hand-written file, a URL with no table)
91
+ * is still sent, ahead of the rows, as it is written.
86
92
  *
87
93
  * @param base the API's effective base URL, already expanded
88
94
  * @param url the request's URL, already expanded
89
95
  * @param pathParams values for the URL's `{name}` placeholders
90
- * @param query query rows to append
96
+ * @param query query rows, the request's stored query
91
97
  */
92
98
  export declare function composeUrl(base: string, url: string, pathParams?: readonly KeyValueEntry[], query?: readonly KeyValueEntry[], options?: ComposeUrlOptions): ComposedUrl;
package/dist/rest/url.js CHANGED
@@ -159,14 +159,20 @@ export function joinQuery(path, query) {
159
159
  * Builds the URL one send actually uses.
160
160
  *
161
161
  * Order of work: the request's URL wins over the base when it is absolute; `{name}` parameters are
162
- * filled from the enabled rows of `pathParams`; the URL's own query string and the `query` table
163
- * are concatenated, in that order, so a parameter typed into the field and one added in the table
164
- * both survive; every value is encoded unless `encode` is off.
162
+ * filled from the enabled rows of `pathParams`; the query is the enabled `query` rows, preceded by
163
+ * any parameter of the URL's own query string that no enabled row carries; every value is encoded
164
+ * unless `encode` is off.
165
+ *
166
+ * The table owns the query. The editor mirrors it into the URL field, so a saved request usually
167
+ * holds each parameter twice — once in `url`, once as a row — and sending both would send it twice.
168
+ * A URL parameter with the same name and value as an enabled row is that row, matched one for one
169
+ * so deliberate duplicates survive. One no row carries (a hand-written file, a URL with no table)
170
+ * is still sent, ahead of the rows, as it is written.
165
171
  *
166
172
  * @param base the API's effective base URL, already expanded
167
173
  * @param url the request's URL, already expanded
168
174
  * @param pathParams values for the URL's `{name}` placeholders
169
- * @param query query rows to append
175
+ * @param query query rows, the request's stored query
170
176
  */
171
177
  export function composeUrl(base, url, pathParams = [], query = [], options = {}) {
172
178
  const encode = options.encode ?? true;
@@ -189,7 +195,7 @@ export function composeUrl(base, url, pathParams = [], query = [], options = {})
189
195
  // segment the request did not ask for.
190
196
  return encode ? encodeValue(value, "!$&'()*+,;=:@") : value;
191
197
  });
192
- const rows = [...inlineQuery, ...query].filter((row) => row.enabled);
198
+ const rows = [...unclaimed(inlineQuery, query), ...query.filter((row) => row.enabled)];
193
199
  const search = rows
194
200
  .map((row) => {
195
201
  const name = encode ? encodeValue(row.name, '') : row.name;
@@ -206,6 +212,33 @@ export function composeUrl(base, url, pathParams = [], query = [], options = {})
206
212
  }
207
213
  return { url: composed, problems };
208
214
  }
215
+ /**
216
+ * The rows of `inline` that no enabled row of `table` accounts for, in order. Each table row claims
217
+ * at most one inline row with its name and value, so `?t=a&t=a` against two `t=a` rows is fully
218
+ * claimed and against one leaves one.
219
+ */
220
+ function unclaimed(inline, table) {
221
+ const available = new Map();
222
+ for (const row of table) {
223
+ if (row.enabled) {
224
+ const key = queryKey(row);
225
+ available.set(key, (available.get(key) ?? 0) + 1);
226
+ }
227
+ }
228
+ return inline.filter((row) => {
229
+ const key = queryKey(row);
230
+ const left = available.get(key) ?? 0;
231
+ if (left === 0) {
232
+ return true;
233
+ }
234
+ available.set(key, left - 1);
235
+ return false;
236
+ });
237
+ }
238
+ /** One key per name and value; `=` cannot end a name, so the join is unambiguous. */
239
+ function queryKey(row) {
240
+ return `${row.name}=${row.value}`;
241
+ }
209
242
  /** Appends a query string to a URL that may already carry a fragment. */
210
243
  function appendSearch(url, search) {
211
244
  const hash = url.indexOf('#');
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The runner's `--update-baseline` decision (#217): whether one response replaces, creates or
3
+ * leaves its golden, compared as `--baseline` compares. Pure; the run reads and writes the file.
4
+ */
5
+ import type { AssertionSubject } from '../assert/model.js';
6
+ import type { GoldenFile, GoldenRead, GoldenWrite } from '../snapshot/golden-file.js';
7
+ import type { BaselineCheck, BaselineReport } from './baseline.js';
8
+ export interface BaselineUpdateInput {
9
+ readonly read: GoldenRead;
10
+ readonly subject: AssertionSubject;
11
+ /** The request's own assertions failed: nothing is written. */
12
+ readonly failed: boolean;
13
+ readonly containsKnownSecret?: (value: string) => boolean;
14
+ readonly now: () => Date;
15
+ }
16
+ export type BaselineUpdatePlan = {
17
+ readonly kind: 'done';
18
+ readonly check: BaselineCheck;
19
+ } | {
20
+ readonly kind: 'write';
21
+ readonly golden: GoldenFile;
22
+ readonly report: BaselineReport;
23
+ };
24
+ /** What the sink answered; `failed` when it threw. */
25
+ export type SinkOutcome = GoldenWrite | {
26
+ readonly status: 'failed';
27
+ readonly message: string;
28
+ };
29
+ /**
30
+ * Own assertions first, then the golden read, then the comparison. Only a golden about to be
31
+ * written is checked for a secret and for text, so a matching golden is never refused.
32
+ */
33
+ export declare function planBaselineUpdate(input: BaselineUpdateInput): BaselineUpdatePlan;
34
+ /** The check for a planned write, once the sink has answered. */
35
+ export declare function finishBaselineUpdate(report: BaselineReport, outcome: SinkOutcome): BaselineCheck;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The runner's `--update-baseline` decision (#217): whether one response replaces, creates or
3
+ * leaves its golden, compared as `--baseline` compares. Pure; the run reads and writes the file.
4
+ */
5
+ import { diffSnapshot } from '../snapshot/diff.js';
6
+ import { detectSnapshotFormat } from '../snapshot/format.js';
7
+ import { parseIgnoreRules } from '../snapshot/ignore.js';
8
+ import { BASELINE_REPORT_CHANGES, contentTypeOf, tooLarge } from './baseline.js';
9
+ const REFUSED = {
10
+ secret: 'The response holds a secret value, so its baseline was not written.',
11
+ malformed: 'The saved baseline cannot be read (malformed), so it was not replaced.',
12
+ 'not-a-file': 'The baseline file is not a regular file, so it was not replaced.',
13
+ unsaved: 'The request file is not on disk, so no baseline was written.',
14
+ 'write-failed': 'The baseline could not be written',
15
+ };
16
+ function refused(reason, detail) {
17
+ const assertion = {
18
+ type: 'baseline',
19
+ label: 'baseline not written',
20
+ outcome: 'errored',
21
+ message: detail === undefined ? REFUSED[reason] : `${REFUSED[reason]}: ${detail}`,
22
+ };
23
+ return { report: { status: 'refused', reason }, assertion };
24
+ }
25
+ const done = (check) => ({ kind: 'done', check });
26
+ /** A NUL, or U+FFFD where the decoder met bytes that are not UTF-8: the Snapshot tab keeps no such body either. */
27
+ const isText = (body) => !body.includes('\u0000') && !body.includes('�');
28
+ /**
29
+ * Own assertions first, then the golden read, then the comparison. Only a golden about to be
30
+ * written is checked for a secret and for text, so a matching golden is never refused.
31
+ */
32
+ export function planBaselineUpdate(input) {
33
+ const { read, subject } = input;
34
+ if (input.failed)
35
+ return done({ report: { status: 'skipped', reason: 'failed' } });
36
+ if (read.status === 'unreadable')
37
+ return done(refused(read.reason));
38
+ const body = subject.bodyText;
39
+ let report;
40
+ if (read.status === 'present') {
41
+ const old = read.golden;
42
+ if (tooLarge(old.body) || tooLarge(body)) {
43
+ // No semantic diff past the limit (#36); exact text decides.
44
+ if (old.body === body)
45
+ return done({ report: { status: 'matched' } });
46
+ report = { status: 'updated' };
47
+ }
48
+ else {
49
+ // The same calls `--baseline` and the Snapshot tab make.
50
+ const format = detectSnapshotFormat(old.body, old.contentType ?? contentTypeOf(subject));
51
+ const diff = diffSnapshot(old.body, body, { format, ignore: parseIgnoreRules(old.ignore.join('\n')) });
52
+ const shared = {
53
+ format: diff.format,
54
+ ignored: diff.ignored,
55
+ ...(diff.error !== undefined ? { error: diff.error } : {}),
56
+ };
57
+ if (diff.changes.length === 0)
58
+ return done({ report: { status: 'matched', ...shared } });
59
+ report = {
60
+ status: 'updated',
61
+ ...shared,
62
+ changes: diff.changes.slice(0, BASELINE_REPORT_CHANGES),
63
+ ...(diff.changes.length > BASELINE_REPORT_CHANGES ? { truncated: true } : {}),
64
+ };
65
+ }
66
+ }
67
+ else {
68
+ report = { status: 'created' };
69
+ }
70
+ if (input.containsKnownSecret?.(body) === true)
71
+ return done(refused('secret'));
72
+ if (!isText(body))
73
+ return done({ report: { status: 'skipped', reason: 'not-text' } });
74
+ const contentType = contentTypeOf(subject);
75
+ return {
76
+ kind: 'write',
77
+ report,
78
+ golden: {
79
+ ...(contentType !== undefined ? { contentType } : {}),
80
+ savedAt: input.now().toISOString(),
81
+ ignore: read.status === 'present' ? [...read.golden.ignore] : [],
82
+ body,
83
+ },
84
+ };
85
+ }
86
+ /** The check for a planned write, once the sink has answered. */
87
+ export function finishBaselineUpdate(report, outcome) {
88
+ if (outcome.status === 'written') {
89
+ return {
90
+ report: { ...report, file: outcome.file },
91
+ assertion: { type: 'baseline', label: `baseline ${report.status}`, outcome: 'passed' },
92
+ };
93
+ }
94
+ if (outcome.status === 'refused')
95
+ return refused(outcome.reason);
96
+ return refused('write-failed', outcome.message);
97
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The runner's `--baseline` check (#36): one response against the golden saved beside its request,
3
+ * compared as the desktop's Snapshot tab compares them. Pure; the run reads the golden.
4
+ */
5
+ import type { AssertionResult, AssertionSubject } from '../assert/model.js';
6
+ import type { SnapshotChange, SnapshotFormat } from '../snapshot/diff.js';
7
+ import type { GoldenRead } from '../snapshot/golden-file.js';
8
+ /** Past this many UTF-8 bytes on either side, no semantic diff is attempted (as the Snapshot tab). */
9
+ export declare const BASELINE_MAX_BYTES: number;
10
+ /** Changes kept in a result's `baseline.changes`. */
11
+ export declare const BASELINE_REPORT_CHANGES = 100;
12
+ /** Changes listed in the failed assertion's message. */
13
+ export declare const BASELINE_MESSAGE_CHANGES = 20;
14
+ /** The protocols a golden can be saved for. */
15
+ export declare const BASELINE_PROTOCOLS: ReadonlySet<string>;
16
+ export type BaselineStatus = 'matched' | 'differs' | 'missing' | 'unreadable' | 'too-large' | 'unsupported' | 'updated' | 'created' | 'skipped' | 'refused';
17
+ /** Why an update did not write: `skipped` for `failed` and `not-text`, `refused` for the rest. */
18
+ export type BaselineReason = 'failed' | 'not-text' | 'secret' | 'malformed' | 'not-a-file' | 'unsaved' | 'write-failed';
19
+ export interface BaselineReport {
20
+ readonly status: BaselineStatus;
21
+ readonly format?: SnapshotFormat;
22
+ readonly changes?: readonly SnapshotChange[];
23
+ readonly ignored?: number;
24
+ readonly truncated?: boolean;
25
+ readonly error?: string;
26
+ readonly reason?: BaselineReason;
27
+ /** The sidecar `--update-baseline` wrote, project-relative. */
28
+ readonly file?: string;
29
+ }
30
+ export interface BaselineCheck {
31
+ readonly report: BaselineReport;
32
+ readonly assertion?: AssertionResult;
33
+ /** Set only for a missing golden under `require`: the request errors with it. */
34
+ readonly error?: {
35
+ readonly code: 'baseline-missing';
36
+ readonly message: string;
37
+ };
38
+ }
39
+ export declare function tooLarge(text: string): boolean;
40
+ export declare function contentTypeOf(subject: AssertionSubject): string | undefined;
41
+ /** One response against the golden read for its request; `require` makes a missing golden an error. */
42
+ export declare function checkBaseline(golden: GoldenRead, subject: AssertionSubject, require: boolean): BaselineCheck;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The runner's `--baseline` check (#36): one response against the golden saved beside its request,
3
+ * compared as the desktop's Snapshot tab compares them. Pure; the run reads the golden.
4
+ */
5
+ import { diffSnapshot } from '../snapshot/diff.js';
6
+ import { detectSnapshotFormat } from '../snapshot/format.js';
7
+ import { parseIgnoreRules } from '../snapshot/ignore.js';
8
+ /** Past this many UTF-8 bytes on either side, no semantic diff is attempted (as the Snapshot tab). */
9
+ export const BASELINE_MAX_BYTES = 2 * 1024 * 1024;
10
+ /** Changes kept in a result's `baseline.changes`. */
11
+ export const BASELINE_REPORT_CHANGES = 100;
12
+ /** Changes listed in the failed assertion's message. */
13
+ export const BASELINE_MESSAGE_CHANGES = 20;
14
+ /** The protocols a golden can be saved for. */
15
+ export const BASELINE_PROTOCOLS = new Set(['soap', 'rest']);
16
+ const encoder = new TextEncoder();
17
+ export function tooLarge(text) {
18
+ // A UTF-16 code unit is at most 3 UTF-8 bytes, so only a borderline string needs encoding.
19
+ if (text.length > BASELINE_MAX_BYTES)
20
+ return true;
21
+ return text.length * 3 > BASELINE_MAX_BYTES && encoder.encode(text).length > BASELINE_MAX_BYTES;
22
+ }
23
+ export function contentTypeOf(subject) {
24
+ return subject.headers?.find(([name]) => name.toLowerCase() === 'content-type')?.[1];
25
+ }
26
+ function changeLine(change) {
27
+ if (change.kind === 'added')
28
+ return `added ${change.path}: ${change.actual ?? ''}`;
29
+ if (change.kind === 'removed')
30
+ return `removed ${change.path}: ${change.expected ?? ''}`;
31
+ return `changed ${change.path}: ${change.expected ?? ''} → ${change.actual ?? ''}`;
32
+ }
33
+ const errored = (status, message) => ({
34
+ report: { status },
35
+ assertion: { type: 'baseline', label: 'baseline', outcome: 'errored', message },
36
+ });
37
+ /** One response against the golden read for its request; `require` makes a missing golden an error. */
38
+ export function checkBaseline(golden, subject, require) {
39
+ if (golden.status === 'none') {
40
+ return require
41
+ ? {
42
+ report: { status: 'missing' },
43
+ error: { code: 'baseline-missing', message: 'No baseline is saved for this request.' },
44
+ }
45
+ : { report: { status: 'missing' } };
46
+ }
47
+ if (golden.status === 'unreadable') {
48
+ return errored('unreadable', `The saved baseline cannot be read (${golden.reason}).`);
49
+ }
50
+ const { body, contentType, ignore } = golden.golden;
51
+ if (tooLarge(body) || tooLarge(subject.bodyText)) {
52
+ return errored('too-large', 'Too large to compare semantically.');
53
+ }
54
+ // The same calls the Snapshot tab makes, so CI and the app agree.
55
+ const format = detectSnapshotFormat(body, contentType ?? contentTypeOf(subject));
56
+ const diff = diffSnapshot(body, subject.bodyText, { format, ignore: parseIgnoreRules(ignore.join('\n')) });
57
+ const shared = {
58
+ format: diff.format,
59
+ ignored: diff.ignored,
60
+ ...(diff.error !== undefined ? { error: diff.error } : {}),
61
+ };
62
+ if (diff.changes.length === 0) {
63
+ return {
64
+ report: { status: 'matched', ...shared },
65
+ assertion: {
66
+ type: 'baseline',
67
+ label: diff.ignored > 0 ? `matches the baseline (${diff.ignored} ignored)` : 'matches the baseline',
68
+ outcome: 'passed',
69
+ },
70
+ };
71
+ }
72
+ const count = diff.changes.length;
73
+ const lines = diff.changes.slice(0, BASELINE_MESSAGE_CHANGES).map(changeLine);
74
+ if (count > BASELINE_MESSAGE_CHANGES)
75
+ lines.push(`… and ${count - BASELINE_MESSAGE_CHANGES} more`);
76
+ // Every reporter prints the message, so the fallback note reaches them all (and the masker).
77
+ if (diff.error !== undefined)
78
+ lines.unshift(`compared as text: ${diff.error}`);
79
+ return {
80
+ report: {
81
+ status: 'differs',
82
+ ...shared,
83
+ changes: diff.changes.slice(0, BASELINE_REPORT_CHANGES),
84
+ ...(count > BASELINE_REPORT_CHANGES ? { truncated: true } : {}),
85
+ },
86
+ assertion: {
87
+ type: 'baseline',
88
+ label: `${count} ${count === 1 ? 'difference' : 'differences'} from the baseline`,
89
+ outcome: 'failed',
90
+ message: lines.join('\n'),
91
+ },
92
+ };
93
+ }