@agentrhq/webcmd 0.1.1 → 0.1.2

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 (415) hide show
  1. package/README.md +317 -24
  2. package/dist/src/adapter-shadow.d.ts +11 -0
  3. package/dist/src/adapter-shadow.js +72 -0
  4. package/dist/src/adapter-shadow.test.d.ts +1 -0
  5. package/dist/src/adapter-shadow.test.js +49 -0
  6. package/dist/src/adapter-source.d.ts +11 -0
  7. package/dist/src/adapter-source.js +24 -0
  8. package/dist/src/adapter-source.test.d.ts +1 -0
  9. package/dist/src/adapter-source.test.js +29 -0
  10. package/dist/src/brand.d.ts +9 -0
  11. package/dist/src/brand.js +9 -0
  12. package/dist/src/brand.test.d.ts +1 -0
  13. package/dist/src/brand.test.js +15 -0
  14. package/dist/src/browser/analyze.d.ts +118 -0
  15. package/dist/src/browser/analyze.js +405 -0
  16. package/dist/src/browser/analyze.test.d.ts +1 -0
  17. package/dist/src/browser/analyze.test.js +209 -0
  18. package/dist/src/browser/article-extract.d.ts +57 -0
  19. package/dist/src/browser/article-extract.e2e.test.d.ts +1 -0
  20. package/dist/src/browser/article-extract.e2e.test.js +105 -0
  21. package/dist/src/browser/article-extract.js +169 -0
  22. package/dist/src/browser/article-extract.test.d.ts +1 -0
  23. package/dist/src/browser/article-extract.test.js +94 -0
  24. package/dist/src/browser/ax-snapshot.d.ts +37 -0
  25. package/dist/src/browser/ax-snapshot.js +217 -0
  26. package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
  27. package/dist/src/browser/ax-snapshot.test.js +91 -0
  28. package/dist/src/browser/base-page.d.ts +151 -0
  29. package/dist/src/browser/base-page.js +1060 -0
  30. package/dist/src/browser/base-page.test.d.ts +1 -0
  31. package/dist/src/browser/base-page.test.js +803 -0
  32. package/dist/src/browser/bridge-readiness.d.ts +14 -0
  33. package/dist/src/browser/bridge-readiness.js +24 -0
  34. package/dist/src/browser/bridge-readiness.test.d.ts +1 -0
  35. package/dist/src/browser/bridge-readiness.test.js +58 -0
  36. package/dist/src/browser/bridge.d.ts +26 -0
  37. package/dist/src/browser/bridge.js +58 -0
  38. package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
  39. package/dist/src/browser/cdp-click-fixture.test.js +87 -0
  40. package/dist/src/browser/cdp.d.ts +46 -0
  41. package/dist/src/browser/cdp.js +536 -0
  42. package/dist/src/browser/cdp.test.d.ts +1 -0
  43. package/dist/src/browser/cdp.test.js +79 -0
  44. package/dist/src/browser/compound.d.ts +59 -0
  45. package/dist/src/browser/compound.js +112 -0
  46. package/dist/src/browser/compound.test.d.ts +1 -0
  47. package/dist/src/browser/compound.test.js +175 -0
  48. package/dist/src/browser/config.d.ts +2 -0
  49. package/dist/src/browser/config.js +14 -0
  50. package/dist/src/browser/daemon-client.d.ts +32 -0
  51. package/dist/src/browser/daemon-client.js +135 -0
  52. package/dist/src/browser/daemon-client.test.d.ts +1 -0
  53. package/dist/src/browser/daemon-client.test.js +326 -0
  54. package/dist/src/browser/daemon-lifecycle.d.ts +37 -0
  55. package/dist/src/browser/daemon-lifecycle.js +147 -0
  56. package/dist/src/browser/daemon-transport.d.ts +54 -0
  57. package/dist/src/browser/daemon-transport.js +68 -0
  58. package/dist/src/browser/daemon-version.d.ts +4 -0
  59. package/dist/src/browser/daemon-version.js +12 -0
  60. package/dist/src/browser/dom-helpers.d.ts +41 -0
  61. package/dist/src/browser/dom-helpers.js +239 -0
  62. package/dist/src/browser/dom-helpers.test.d.ts +1 -0
  63. package/dist/src/browser/dom-helpers.test.js +106 -0
  64. package/dist/src/browser/dom-snapshot.d.ts +93 -0
  65. package/dist/src/browser/dom-snapshot.js +894 -0
  66. package/dist/src/browser/dom-snapshot.test.d.ts +11 -0
  67. package/dist/src/browser/dom-snapshot.test.js +313 -0
  68. package/dist/src/browser/errors.d.ts +38 -0
  69. package/dist/src/browser/errors.js +79 -0
  70. package/dist/src/browser/errors.test.d.ts +1 -0
  71. package/dist/src/browser/errors.test.js +60 -0
  72. package/dist/src/browser/extract.d.ts +69 -0
  73. package/dist/src/browser/extract.js +132 -0
  74. package/dist/src/browser/extract.test.d.ts +1 -0
  75. package/dist/src/browser/extract.test.js +129 -0
  76. package/dist/src/browser/find.d.ts +84 -0
  77. package/dist/src/browser/find.js +398 -0
  78. package/dist/src/browser/find.test.d.ts +1 -0
  79. package/dist/src/browser/find.test.js +180 -0
  80. package/dist/src/browser/html-tree.d.ts +75 -0
  81. package/dist/src/browser/html-tree.js +112 -0
  82. package/dist/src/browser/html-tree.test.d.ts +1 -0
  83. package/dist/src/browser/html-tree.test.js +181 -0
  84. package/dist/src/browser/index.d.ts +14 -0
  85. package/dist/src/browser/index.js +12 -0
  86. package/dist/src/browser/network-cache.d.ts +49 -0
  87. package/dist/src/browser/network-cache.js +78 -0
  88. package/dist/src/browser/network-cache.test.d.ts +1 -0
  89. package/dist/src/browser/network-cache.test.js +75 -0
  90. package/dist/src/browser/network-interceptor.d.ts +11 -0
  91. package/dist/src/browser/network-interceptor.js +11 -0
  92. package/dist/src/browser/network-key.d.ts +22 -0
  93. package/dist/src/browser/network-key.js +66 -0
  94. package/dist/src/browser/network-key.test.d.ts +1 -0
  95. package/dist/src/browser/network-key.test.js +49 -0
  96. package/dist/src/browser/page.d.ts +83 -0
  97. package/dist/src/browser/page.js +453 -0
  98. package/dist/src/browser/page.test.d.ts +1 -0
  99. package/dist/src/browser/page.test.js +406 -0
  100. package/dist/src/browser/profile.d.ts +14 -0
  101. package/dist/src/browser/profile.js +86 -0
  102. package/dist/src/browser/protocol.d.ts +63 -0
  103. package/dist/src/browser/protocol.js +1 -0
  104. package/dist/src/browser/runtime/local-cloak/actions.d.ts +3 -0
  105. package/dist/src/browser/runtime/local-cloak/actions.js +240 -0
  106. package/dist/src/browser/runtime/local-cloak/downloads.d.ts +3 -0
  107. package/dist/src/browser/runtime/local-cloak/downloads.js +28 -0
  108. package/dist/src/browser/runtime/local-cloak/network.d.ts +28 -0
  109. package/dist/src/browser/runtime/local-cloak/network.js +120 -0
  110. package/dist/src/browser/runtime/local-cloak/network.test.d.ts +1 -0
  111. package/dist/src/browser/runtime/local-cloak/network.test.js +124 -0
  112. package/dist/src/browser/runtime/local-cloak/profiles.d.ts +6 -0
  113. package/dist/src/browser/runtime/local-cloak/profiles.js +17 -0
  114. package/dist/src/browser/runtime/local-cloak/profiles.test.d.ts +1 -0
  115. package/dist/src/browser/runtime/local-cloak/profiles.test.js +19 -0
  116. package/dist/src/browser/runtime/local-cloak/provider.d.ts +15 -0
  117. package/dist/src/browser/runtime/local-cloak/provider.js +27 -0
  118. package/dist/src/browser/runtime/local-cloak/provider.test.d.ts +1 -0
  119. package/dist/src/browser/runtime/local-cloak/provider.test.js +244 -0
  120. package/dist/src/browser/runtime/local-cloak/session-manager.d.ts +77 -0
  121. package/dist/src/browser/runtime/local-cloak/session-manager.js +280 -0
  122. package/dist/src/browser/runtime/local-cloak/session-manager.test.d.ts +1 -0
  123. package/dist/src/browser/runtime/local-cloak/session-manager.test.js +92 -0
  124. package/dist/src/browser/runtime/provider.d.ts +9 -0
  125. package/dist/src/browser/runtime/provider.js +1 -0
  126. package/dist/src/browser/runtime/provider.test.d.ts +2 -0
  127. package/dist/src/browser/runtime/provider.test.js +49 -0
  128. package/dist/src/browser/shape-filter.d.ts +52 -0
  129. package/dist/src/browser/shape-filter.js +101 -0
  130. package/dist/src/browser/shape-filter.test.d.ts +1 -0
  131. package/dist/src/browser/shape-filter.test.js +101 -0
  132. package/dist/src/browser/shape.d.ts +23 -0
  133. package/dist/src/browser/shape.js +95 -0
  134. package/dist/src/browser/shape.test.d.ts +1 -0
  135. package/dist/src/browser/shape.test.js +82 -0
  136. package/dist/src/browser/stealth.d.ts +11 -0
  137. package/dist/src/browser/stealth.js +359 -0
  138. package/dist/src/browser/stealth.test.d.ts +1 -0
  139. package/dist/src/browser/stealth.test.js +134 -0
  140. package/dist/src/browser/tabs.d.ts +13 -0
  141. package/dist/src/browser/tabs.js +70 -0
  142. package/dist/src/browser/target-errors.d.ts +39 -0
  143. package/dist/src/browser/target-errors.js +45 -0
  144. package/dist/src/browser/target-errors.test.d.ts +1 -0
  145. package/dist/src/browser/target-errors.test.js +94 -0
  146. package/dist/src/browser/target-resolver.d.ts +158 -0
  147. package/dist/src/browser/target-resolver.js +570 -0
  148. package/dist/src/browser/target-resolver.test.d.ts +1 -0
  149. package/dist/src/browser/target-resolver.test.js +118 -0
  150. package/dist/src/browser/utils.d.ts +20 -0
  151. package/dist/src/browser/utils.js +64 -0
  152. package/dist/src/browser/utils.test.d.ts +1 -0
  153. package/dist/src/browser/utils.test.js +29 -0
  154. package/dist/src/browser/verify-fixture.d.ts +65 -0
  155. package/dist/src/browser/verify-fixture.js +318 -0
  156. package/dist/src/browser/verify-fixture.test.d.ts +1 -0
  157. package/dist/src/browser/verify-fixture.test.js +219 -0
  158. package/dist/src/browser/visual-refs.d.ts +11 -0
  159. package/dist/src/browser/visual-refs.js +108 -0
  160. package/dist/src/browser.test.d.ts +1 -0
  161. package/dist/src/browser.test.js +297 -0
  162. package/dist/src/build-manifest.d.ts +103 -0
  163. package/dist/src/build-manifest.js +363 -0
  164. package/dist/src/build-manifest.test.d.ts +1 -0
  165. package/dist/src/build-manifest.test.js +341 -0
  166. package/dist/src/capabilityRouting.d.ts +19 -0
  167. package/dist/src/capabilityRouting.js +56 -0
  168. package/dist/src/capabilityRouting.test.d.ts +1 -0
  169. package/dist/src/capabilityRouting.test.js +63 -0
  170. package/dist/src/cli-argv-preprocess.d.ts +63 -0
  171. package/dist/src/cli-argv-preprocess.js +303 -0
  172. package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
  173. package/dist/src/cli-argv-preprocess.test.js +304 -0
  174. package/dist/src/cli.d.ts +79 -0
  175. package/dist/src/cli.js +3350 -0
  176. package/dist/src/cli.test.d.ts +1 -0
  177. package/dist/src/cli.test.js +3041 -0
  178. package/dist/src/commanderAdapter.d.ts +21 -0
  179. package/dist/src/commanderAdapter.js +208 -0
  180. package/dist/src/commanderAdapter.test.d.ts +1 -0
  181. package/dist/src/commanderAdapter.test.js +352 -0
  182. package/dist/src/commands/auth.d.ts +40 -0
  183. package/dist/src/commands/auth.js +434 -0
  184. package/dist/src/commands/auth.test.d.ts +1 -0
  185. package/dist/src/commands/auth.test.js +252 -0
  186. package/dist/src/commands/daemon.d.ts +9 -0
  187. package/dist/src/commands/daemon.js +91 -0
  188. package/dist/src/commands/daemon.test.d.ts +1 -0
  189. package/dist/src/commands/daemon.test.js +293 -0
  190. package/dist/src/completion-fast.d.ts +22 -0
  191. package/dist/src/completion-fast.js +88 -0
  192. package/dist/src/completion-shared.d.ts +13 -0
  193. package/dist/src/completion-shared.js +61 -0
  194. package/dist/src/completion.d.ts +21 -0
  195. package/dist/src/completion.js +68 -0
  196. package/dist/src/completion.test.d.ts +1 -0
  197. package/dist/src/completion.test.js +24 -0
  198. package/dist/src/constants.d.ts +18 -0
  199. package/dist/src/constants.js +41 -0
  200. package/dist/src/convention-audit.d.ts +50 -0
  201. package/dist/src/convention-audit.js +553 -0
  202. package/dist/src/convention-audit.test.d.ts +1 -0
  203. package/dist/src/convention-audit.test.js +255 -0
  204. package/dist/src/daemon/server.d.ts +13 -0
  205. package/dist/src/daemon/server.js +185 -0
  206. package/dist/src/daemon/server.test.d.ts +1 -0
  207. package/dist/src/daemon/server.test.js +132 -0
  208. package/dist/src/daemon-utils.d.ts +18 -0
  209. package/dist/src/daemon-utils.js +37 -0
  210. package/dist/src/daemon.d.ts +1 -0
  211. package/dist/src/daemon.js +27 -0
  212. package/dist/src/daemon.test.d.ts +1 -0
  213. package/dist/src/daemon.test.js +60 -0
  214. package/dist/src/discovery.d.ts +46 -0
  215. package/dist/src/discovery.js +341 -0
  216. package/dist/src/doctor.d.ts +39 -0
  217. package/dist/src/doctor.js +168 -0
  218. package/dist/src/doctor.test.d.ts +1 -0
  219. package/dist/src/doctor.test.js +302 -0
  220. package/dist/src/download/article-download.d.ts +72 -0
  221. package/dist/src/download/article-download.js +305 -0
  222. package/dist/src/download/article-download.test.d.ts +1 -0
  223. package/dist/src/download/article-download.test.js +235 -0
  224. package/dist/src/download/index.d.ts +71 -0
  225. package/dist/src/download/index.js +363 -0
  226. package/dist/src/download/index.test.d.ts +1 -0
  227. package/dist/src/download/index.test.js +174 -0
  228. package/dist/src/download/media-download.d.ts +49 -0
  229. package/dist/src/download/media-download.js +127 -0
  230. package/dist/src/download/media-download.test.d.ts +1 -0
  231. package/dist/src/download/media-download.test.js +112 -0
  232. package/dist/src/download/progress.d.ts +36 -0
  233. package/dist/src/download/progress.js +120 -0
  234. package/dist/src/download/progress.test.d.ts +1 -0
  235. package/dist/src/download/progress.test.js +36 -0
  236. package/dist/src/electron-apps.d.ts +31 -0
  237. package/dist/src/electron-apps.js +91 -0
  238. package/dist/src/electron-apps.test.d.ts +1 -0
  239. package/dist/src/electron-apps.test.js +76 -0
  240. package/dist/src/engine.test.d.ts +1 -0
  241. package/dist/src/engine.test.js +312 -0
  242. package/dist/src/errors.d.ts +114 -0
  243. package/dist/src/errors.js +174 -0
  244. package/dist/src/errors.test.d.ts +1 -0
  245. package/dist/src/errors.test.js +109 -0
  246. package/dist/src/execution.d.ts +24 -0
  247. package/dist/src/execution.js +509 -0
  248. package/dist/src/execution.test.d.ts +1 -0
  249. package/dist/src/execution.test.js +645 -0
  250. package/dist/src/external.d.ts +49 -0
  251. package/dist/src/external.js +211 -0
  252. package/dist/src/external.test.d.ts +1 -0
  253. package/dist/src/external.test.js +110 -0
  254. package/dist/src/help.d.ts +88 -0
  255. package/dist/src/help.js +556 -0
  256. package/dist/src/help.test.d.ts +1 -0
  257. package/dist/src/help.test.js +58 -0
  258. package/dist/src/hooks.d.ts +46 -0
  259. package/dist/src/hooks.js +58 -0
  260. package/dist/src/hooks.test.d.ts +4 -0
  261. package/dist/src/hooks.test.js +92 -0
  262. package/dist/src/interceptor.d.ts +44 -0
  263. package/dist/src/interceptor.js +183 -0
  264. package/dist/src/interceptor.test.d.ts +4 -0
  265. package/dist/src/interceptor.test.js +81 -0
  266. package/dist/src/launcher.d.ts +41 -0
  267. package/dist/src/launcher.js +226 -0
  268. package/dist/src/launcher.test.d.ts +1 -0
  269. package/dist/src/launcher.test.js +153 -0
  270. package/dist/src/logger.d.ts +26 -0
  271. package/dist/src/logger.js +49 -0
  272. package/dist/src/main.d.ts +5 -0
  273. package/dist/src/main.js +177 -0
  274. package/dist/src/manifest-types.d.ts +43 -0
  275. package/dist/src/manifest-types.js +9 -0
  276. package/dist/src/node-network.d.ts +10 -0
  277. package/dist/src/node-network.js +174 -0
  278. package/dist/src/node-network.test.d.ts +1 -0
  279. package/dist/src/node-network.test.js +55 -0
  280. package/dist/src/observation/artifact.d.ts +16 -0
  281. package/dist/src/observation/artifact.js +260 -0
  282. package/dist/src/observation/artifact.test.d.ts +1 -0
  283. package/dist/src/observation/artifact.test.js +121 -0
  284. package/dist/src/observation/events.d.ts +89 -0
  285. package/dist/src/observation/events.js +1 -0
  286. package/dist/src/observation/index.d.ts +7 -0
  287. package/dist/src/observation/index.js +7 -0
  288. package/dist/src/observation/manager.d.ts +9 -0
  289. package/dist/src/observation/manager.js +27 -0
  290. package/dist/src/observation/manager.test.d.ts +1 -0
  291. package/dist/src/observation/manager.test.js +13 -0
  292. package/dist/src/observation/redaction.d.ts +11 -0
  293. package/dist/src/observation/redaction.js +81 -0
  294. package/dist/src/observation/redaction.test.d.ts +1 -0
  295. package/dist/src/observation/redaction.test.js +32 -0
  296. package/dist/src/observation/retention.d.ts +32 -0
  297. package/dist/src/observation/retention.js +160 -0
  298. package/dist/src/observation/retention.test.d.ts +1 -0
  299. package/dist/src/observation/retention.test.js +118 -0
  300. package/dist/src/observation/ring-buffer.d.ts +22 -0
  301. package/dist/src/observation/ring-buffer.js +45 -0
  302. package/dist/src/observation/ring-buffer.test.d.ts +1 -0
  303. package/dist/src/observation/ring-buffer.test.js +22 -0
  304. package/dist/src/observation/session.d.ts +25 -0
  305. package/dist/src/observation/session.js +50 -0
  306. package/dist/src/output.d.ts +14 -0
  307. package/dist/src/output.js +152 -0
  308. package/dist/src/output.test.d.ts +1 -0
  309. package/dist/src/output.test.js +53 -0
  310. package/dist/src/package-exports.test.d.ts +1 -0
  311. package/dist/src/package-exports.test.js +112 -0
  312. package/dist/src/package-paths.d.ts +8 -0
  313. package/dist/src/package-paths.js +41 -0
  314. package/dist/src/pipeline/executor.d.ts +11 -0
  315. package/dist/src/pipeline/executor.js +93 -0
  316. package/dist/src/pipeline/executor.test.d.ts +4 -0
  317. package/dist/src/pipeline/executor.test.js +182 -0
  318. package/dist/src/pipeline/index.d.ts +5 -0
  319. package/dist/src/pipeline/index.js +5 -0
  320. package/dist/src/pipeline/registry.d.ts +28 -0
  321. package/dist/src/pipeline/registry.js +55 -0
  322. package/dist/src/pipeline/steps/browser.d.ts +13 -0
  323. package/dist/src/pipeline/steps/browser.js +86 -0
  324. package/dist/src/pipeline/steps/download.d.ts +18 -0
  325. package/dist/src/pipeline/steps/download.js +252 -0
  326. package/dist/src/pipeline/steps/download.test.d.ts +1 -0
  327. package/dist/src/pipeline/steps/download.test.js +102 -0
  328. package/dist/src/pipeline/steps/fetch.d.ts +5 -0
  329. package/dist/src/pipeline/steps/fetch.js +122 -0
  330. package/dist/src/pipeline/steps/fetch.test.d.ts +1 -0
  331. package/dist/src/pipeline/steps/fetch.test.js +117 -0
  332. package/dist/src/pipeline/steps/intercept.d.ts +5 -0
  333. package/dist/src/pipeline/steps/intercept.js +50 -0
  334. package/dist/src/pipeline/steps/tap.d.ts +12 -0
  335. package/dist/src/pipeline/steps/tap.js +93 -0
  336. package/dist/src/pipeline/steps/transform.d.ts +9 -0
  337. package/dist/src/pipeline/steps/transform.js +70 -0
  338. package/dist/src/pipeline/template.d.ts +17 -0
  339. package/dist/src/pipeline/template.js +344 -0
  340. package/dist/src/pipeline/template.test.d.ts +4 -0
  341. package/dist/src/pipeline/template.test.js +197 -0
  342. package/dist/src/pipeline/transform.test.d.ts +4 -0
  343. package/dist/src/pipeline/transform.test.js +133 -0
  344. package/dist/src/plugin-manifest.d.ts +70 -0
  345. package/dist/src/plugin-manifest.js +160 -0
  346. package/dist/src/plugin-manifest.test.d.ts +4 -0
  347. package/dist/src/plugin-manifest.test.js +179 -0
  348. package/dist/src/plugin-scaffold.d.ts +28 -0
  349. package/dist/src/plugin-scaffold.js +143 -0
  350. package/dist/src/plugin-scaffold.test.d.ts +4 -0
  351. package/dist/src/plugin-scaffold.test.js +83 -0
  352. package/dist/src/plugin.d.ts +146 -0
  353. package/dist/src/plugin.js +1303 -0
  354. package/dist/src/plugin.test.d.ts +4 -0
  355. package/dist/src/plugin.test.js +1363 -0
  356. package/dist/src/registry-api.d.ts +13 -0
  357. package/dist/src/registry-api.js +10 -0
  358. package/dist/src/registry.d.ts +123 -0
  359. package/dist/src/registry.js +125 -0
  360. package/dist/src/registry.test.d.ts +4 -0
  361. package/dist/src/registry.test.js +209 -0
  362. package/dist/src/runtime-copy.test.d.ts +1 -0
  363. package/dist/src/runtime-copy.test.js +29 -0
  364. package/dist/src/runtime-detect.d.ts +31 -0
  365. package/dist/src/runtime-detect.js +47 -0
  366. package/dist/src/runtime-detect.test.d.ts +1 -0
  367. package/dist/src/runtime-detect.test.js +39 -0
  368. package/dist/src/runtime-identity.test.d.ts +1 -0
  369. package/dist/src/runtime-identity.test.js +18 -0
  370. package/dist/src/runtime.d.ts +47 -0
  371. package/dist/src/runtime.js +54 -0
  372. package/dist/src/scripts/framework.d.ts +7 -0
  373. package/dist/src/scripts/framework.js +25 -0
  374. package/dist/src/scripts/interact.d.ts +4 -0
  375. package/dist/src/scripts/interact.js +20 -0
  376. package/dist/src/scripts/store.d.ts +13 -0
  377. package/dist/src/scripts/store.js +48 -0
  378. package/dist/src/serialization.d.ts +42 -0
  379. package/dist/src/serialization.js +103 -0
  380. package/dist/src/serialization.test.d.ts +1 -0
  381. package/dist/src/serialization.test.js +78 -0
  382. package/dist/src/skills.d.ts +14 -0
  383. package/dist/src/skills.js +127 -0
  384. package/dist/src/skills.test.d.ts +1 -0
  385. package/dist/src/skills.test.js +71 -0
  386. package/dist/src/snapshotFormatter.d.ts +11 -0
  387. package/dist/src/snapshotFormatter.js +338 -0
  388. package/dist/src/snapshotFormatter.test.d.ts +7 -0
  389. package/dist/src/snapshotFormatter.test.js +521 -0
  390. package/dist/src/tui.d.ts +28 -0
  391. package/dist/src/tui.js +179 -0
  392. package/dist/src/tui.test.d.ts +1 -0
  393. package/dist/src/tui.test.js +19 -0
  394. package/dist/src/types.d.ts +236 -0
  395. package/dist/src/types.js +7 -0
  396. package/dist/src/update-check.d.ts +66 -0
  397. package/dist/src/update-check.js +206 -0
  398. package/dist/src/update-check.test.d.ts +1 -0
  399. package/dist/src/update-check.test.js +117 -0
  400. package/dist/src/utils.d.ts +57 -0
  401. package/dist/src/utils.js +152 -0
  402. package/dist/src/utils.test.d.ts +1 -0
  403. package/dist/src/utils.test.js +155 -0
  404. package/dist/src/validate.d.ts +21 -0
  405. package/dist/src/validate.js +130 -0
  406. package/dist/src/validate.test.d.ts +9 -0
  407. package/dist/src/validate.test.js +90 -0
  408. package/dist/src/verify.d.ts +26 -0
  409. package/dist/src/verify.js +67 -0
  410. package/dist/src/version.d.ts +4 -0
  411. package/dist/src/version.js +22 -0
  412. package/dist/src/weixin-download.test.d.ts +1 -0
  413. package/dist/src/weixin-download.test.js +45 -0
  414. package/package.json +4 -3
  415. package/scripts/check-package-bin.mjs +95 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Pipeline step: tap — declarative Store Action Bridge.
3
+ *
4
+ * Generates a self-contained IIFE that:
5
+ * 1. Injects fetch + XHR dual interception proxy
6
+ * 2. Finds the Pinia/Vuex store and calls the action
7
+ * 3. Captures the response matching the URL pattern
8
+ * 4. Auto-cleans up interception in finally block
9
+ * 5. Returns the captured data (optionally sub-selected)
10
+ */
11
+ import { render } from '../template.js';
12
+ import { generateTapInterceptorJs } from '../../interceptor.js';
13
+ import { CliError } from '../../errors.js';
14
+ export async function stepTap(page, params, data, args) {
15
+ const cfg = typeof params === 'object' && params !== null ? params : {};
16
+ const storeName = String(render(cfg.store ?? '', { args, data }));
17
+ const actionName = String(render(cfg.action ?? '', { args, data }));
18
+ const capturePattern = String(render(cfg.capture ?? '', { args, data }));
19
+ const timeout = cfg.timeout ?? 5;
20
+ const selectPath = cfg.select ? String(render(cfg.select, { args, data })) : null;
21
+ const framework = cfg.framework ?? null;
22
+ const actionArgs = cfg.args ?? [];
23
+ if (!storeName || !actionName)
24
+ throw new CliError('TAP_MISSING_PARAMS', 'tap: store and action are required');
25
+ // Build select chain for the captured response
26
+ const selectChain = selectPath
27
+ ? selectPath.split('.').map((p) => `?.[${JSON.stringify(p)}]`).join('')
28
+ : '';
29
+ // Serialize action arguments
30
+ const actionArgsRendered = actionArgs.map((a) => {
31
+ const rendered = render(a, { args, data });
32
+ return JSON.stringify(rendered);
33
+ });
34
+ const actionCall = actionArgsRendered.length
35
+ ? `store[${JSON.stringify(actionName)}](${actionArgsRendered.join(', ')})`
36
+ : `store[${JSON.stringify(actionName)}]()`;
37
+ // Use shared interceptor generator for fetch/XHR patching
38
+ const tap = generateTapInterceptorJs(JSON.stringify(capturePattern));
39
+ const js = `
40
+ async () => {
41
+ // ── 1. Setup capture proxy (fetch + XHR dual interception) ──
42
+ ${tap.setupVar}
43
+ ${tap.fetchPatch}
44
+ ${tap.xhrPatch}
45
+
46
+ try {
47
+ // ── 2. Find store ──
48
+ let store = null;
49
+ const storeName = ${JSON.stringify(storeName)};
50
+ const fw = ${JSON.stringify(framework)};
51
+
52
+ const app = document.querySelector('#app');
53
+ if (!fw || fw === 'pinia') {
54
+ try {
55
+ const pinia = app?.__vue_app__?.config?.globalProperties?.$pinia;
56
+ if (pinia?._s) store = pinia._s.get(storeName);
57
+ } catch {}
58
+ }
59
+ if (!store && (!fw || fw === 'vuex')) {
60
+ try {
61
+ const vuexStore = app?.__vue_app__?.config?.globalProperties?.$store
62
+ ?? app?.__vue__?.$store;
63
+ if (vuexStore) {
64
+ store = { [${JSON.stringify(actionName)}]: (...a) => vuexStore.dispatch(storeName + '/' + ${JSON.stringify(actionName)}, ...a) };
65
+ }
66
+ } catch {}
67
+ }
68
+
69
+ if (!store) return { error: 'Store not found: ' + storeName, hint: 'Page may not be fully loaded or store name may be incorrect' };
70
+ if (typeof store[${JSON.stringify(actionName)}] !== 'function') {
71
+ return { error: 'Action not found: ' + ${JSON.stringify(actionName)} + ' on store ' + storeName,
72
+ hint: 'Available: ' + Object.keys(store).filter(k => typeof store[k] === 'function' && !k.startsWith('$') && !k.startsWith('_')).join(', ') };
73
+ }
74
+
75
+ // ── 3. Call store action ──
76
+ await ${actionCall};
77
+
78
+ // ── 4. Wait for network response ──
79
+ if (!${tap.capturedVar}) {
80
+ const timeoutPromise = new Promise(r => setTimeout(r, ${timeout} * 1000));
81
+ await Promise.race([${tap.promiseVar}, timeoutPromise]);
82
+ }
83
+ } finally {
84
+ // ── 5. Always restore originals ──
85
+ ${tap.restorePatch}
86
+ }
87
+
88
+ if (!${tap.capturedVar}) return { error: 'No matching response captured for pattern: ' + capturePattern };
89
+ return ${tap.capturedVar}${selectChain} ?? ${tap.capturedVar};
90
+ }
91
+ `;
92
+ return page.evaluate(js);
93
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Pipeline steps: data transforms — select, map, filter, sort, limit.
3
+ */
4
+ import type { IPage } from '../../types.js';
5
+ export declare function stepSelect(_page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
6
+ export declare function stepMap(_page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
7
+ export declare function stepFilter(_page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
8
+ export declare function stepSort(_page: IPage | null, params: unknown, data: unknown, _args: Record<string, unknown>): Promise<unknown>;
9
+ export declare function stepLimit(_page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Pipeline steps: data transforms — select, map, filter, sort, limit.
3
+ */
4
+ import { render, evalExpr } from '../template.js';
5
+ import { isRecord } from '../../utils.js';
6
+ export async function stepSelect(_page, params, data, args) {
7
+ const pathStr = String(render(params, { args, data }));
8
+ if (data && typeof data === 'object') {
9
+ let current = data;
10
+ for (const part of pathStr.split('.')) {
11
+ if (isRecord(current))
12
+ current = current[part];
13
+ else if (Array.isArray(current) && /^\d+$/.test(part))
14
+ current = current[parseInt(part, 10)];
15
+ else
16
+ return null;
17
+ }
18
+ return current;
19
+ }
20
+ return data;
21
+ }
22
+ export async function stepMap(_page, params, data, args) {
23
+ if (!data || typeof data !== 'object')
24
+ return data;
25
+ let source = data;
26
+ // Support inline select: { map: { select: 'path', key: '${{ item.x }}' } }
27
+ if (isRecord(params) && 'select' in params) {
28
+ source = await stepSelect(null, params.select, data, args);
29
+ }
30
+ if (!source || typeof source !== 'object')
31
+ return source;
32
+ let items = Array.isArray(source) ? source : [source];
33
+ if (isRecord(source) && Array.isArray(source.data))
34
+ items = source.data;
35
+ const result = [];
36
+ const templateParams = isRecord(params) ? params : {};
37
+ for (let i = 0; i < items.length; i++) {
38
+ const item = items[i];
39
+ const row = {};
40
+ for (const [key, template] of Object.entries(templateParams)) {
41
+ if (key === 'select')
42
+ continue;
43
+ row[key] = render(template, { args, data: source, root: data, item, index: i });
44
+ }
45
+ result.push(row);
46
+ }
47
+ return result;
48
+ }
49
+ export async function stepFilter(_page, params, data, args) {
50
+ if (!Array.isArray(data))
51
+ return data;
52
+ return data.filter((item, i) => evalExpr(String(params), { args, item, index: i }));
53
+ }
54
+ export async function stepSort(_page, params, data, _args) {
55
+ if (!Array.isArray(data))
56
+ return data;
57
+ const key = isRecord(params) ? String(params.by ?? '') : String(params);
58
+ const reverse = isRecord(params) ? params.order === 'desc' : false;
59
+ return [...data].sort((a, b) => {
60
+ const left = isRecord(a) ? a[key] : undefined;
61
+ const right = isRecord(b) ? b[key] : undefined;
62
+ const cmp = String(left ?? '').localeCompare(String(right ?? ''), undefined, { numeric: true });
63
+ return reverse ? -cmp : cmp;
64
+ });
65
+ }
66
+ export async function stepLimit(_page, params, data, args) {
67
+ if (!Array.isArray(data))
68
+ return data;
69
+ return data.slice(0, Number(render(params, { args, data })));
70
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Pipeline template engine: ${{ ... }} expression rendering.
3
+ */
4
+ export interface RenderContext {
5
+ args?: Record<string, unknown>;
6
+ data?: unknown;
7
+ root?: unknown;
8
+ item?: unknown;
9
+ index?: number;
10
+ }
11
+ export declare function render(template: unknown, ctx: RenderContext): unknown;
12
+ export declare function evalExpr(expr: string, ctx: RenderContext): unknown;
13
+ export declare function resolvePath(pathStr: string, ctx: RenderContext): unknown;
14
+ /**
15
+ * Normalize JavaScript source for browser evaluate() calls.
16
+ */
17
+ export declare function normalizeEvaluateSource(source: string): string;
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Pipeline template engine: ${{ ... }} expression rendering.
3
+ */
4
+ import vm from 'node:vm';
5
+ import { isRecord } from '../utils.js';
6
+ import { log } from '../logger.js';
7
+ export function render(template, ctx) {
8
+ if (typeof template !== 'string')
9
+ return template;
10
+ const trimmed = template.trim();
11
+ // Full expression: entire string is a single ${{ ... }}
12
+ // Use [^}] to prevent matching across }} boundaries (e.g. "${{ a }}-${{ b }}")
13
+ const fullMatch = trimmed.match(/^\$\{\{\s*([^}]*(?:\}[^}][^}]*)*)\s*\}\}$/);
14
+ if (fullMatch && !trimmed.includes('}}-') && !trimmed.includes('}}${{'))
15
+ return evalExpr(fullMatch[1].trim(), ctx);
16
+ // Check if the entire string is a single expression (no other text around it)
17
+ const singleExpr = trimmed.match(/^\$\{\{\s*([\s\S]*?)\s*\}\}$/);
18
+ if (singleExpr) {
19
+ // Verify it's truly a single expression (no other ${{ inside)
20
+ const inner = singleExpr[1];
21
+ if (!inner.includes('${{'))
22
+ return evalExpr(inner.trim(), ctx);
23
+ }
24
+ return template.replace(/\$\{\{\s*(.*?)\s*\}\}/g, (_m, expr) => String(evalExpr(expr.trim(), ctx)));
25
+ }
26
+ export function evalExpr(expr, ctx) {
27
+ const args = ctx.args ?? {};
28
+ const item = ctx.item ?? {};
29
+ const data = ctx.data;
30
+ const root = ctx.root;
31
+ const index = ctx.index ?? 0;
32
+ // ── Pipe filters: expr | filter1(arg) | filter2 ──
33
+ // Split on single | (not ||) so "item.a || item.b | upper" works correctly.
34
+ const pipeSegments = expr.split(/(?<!\|)\|(?!\|)/).map(s => s.trim());
35
+ if (pipeSegments.length > 1) {
36
+ let result = evalExpr(pipeSegments[0], ctx);
37
+ for (let i = 1; i < pipeSegments.length; i++) {
38
+ result = applyFilter(pipeSegments[i], result);
39
+ }
40
+ return result;
41
+ }
42
+ // Fast path: quoted string literal — skip VM overhead
43
+ const strLit = expr.match(/^(['"])(.*)\1$/);
44
+ if (strLit)
45
+ return strLit[2];
46
+ // Fast path: numeric literal
47
+ if (/^\d+(\.\d+)?$/.test(expr))
48
+ return Number(expr);
49
+ // Try resolving as a simple dotted path (item.foo.bar, args.limit, index)
50
+ const resolved = resolvePath(expr, { args, item, data, root, index });
51
+ if (resolved !== null && resolved !== undefined)
52
+ return resolved;
53
+ // Fallback: evaluate as JS in a sandboxed VM.
54
+ // Handles ||, ??, arithmetic, ternary, method calls, etc. natively.
55
+ return evalJsExpr(expr, { args, item, data, root, index });
56
+ }
57
+ /**
58
+ * Apply a named filter to a value.
59
+ * Supported filters:
60
+ * default(val), join(sep), upper, lower, truncate(n), trim,
61
+ * replace(old,new), keys, length, first, last, json
62
+ */
63
+ function applyFilter(filterExpr, value) {
64
+ const match = filterExpr.match(/^(\w+)(?:\((.+)\))?$/);
65
+ if (!match)
66
+ return value;
67
+ const [, name, rawArgs] = match;
68
+ const filterArg = rawArgs?.replace(/^['"]|['"]$/g, '') ?? '';
69
+ switch (name) {
70
+ case 'default': {
71
+ if (value === null || value === undefined || value === '') {
72
+ const intVal = parseInt(filterArg, 10);
73
+ if (!Number.isNaN(intVal) && String(intVal) === filterArg.trim())
74
+ return intVal;
75
+ return filterArg;
76
+ }
77
+ return value;
78
+ }
79
+ case 'join':
80
+ return Array.isArray(value) ? value.join(filterArg || ', ') : value;
81
+ case 'upper':
82
+ return typeof value === 'string' ? value.toUpperCase() : value;
83
+ case 'lower':
84
+ return typeof value === 'string' ? value.toLowerCase() : value;
85
+ case 'trim':
86
+ return typeof value === 'string' ? value.trim() : value;
87
+ case 'truncate': {
88
+ const n = parseInt(filterArg, 10) || 50;
89
+ return typeof value === 'string' && value.length > n ? `${value.slice(0, n)}...` : value;
90
+ }
91
+ case 'replace': {
92
+ if (typeof value !== 'string')
93
+ return value;
94
+ const parts = rawArgs?.split(',').map(s => s.trim().replace(/^['"]|['"]$/g, '')) ?? [];
95
+ return parts.length >= 2 ? value.replaceAll(parts[0], parts[1]) : value;
96
+ }
97
+ case 'keys':
98
+ return value && typeof value === 'object' ? Object.keys(value) : value;
99
+ case 'length':
100
+ return Array.isArray(value) ? value.length : typeof value === 'string' ? value.length : value;
101
+ case 'first':
102
+ return Array.isArray(value) ? value[0] : value;
103
+ case 'last':
104
+ return Array.isArray(value) ? value[value.length - 1] : value;
105
+ case 'json':
106
+ return JSON.stringify(value ?? null);
107
+ case 'slugify':
108
+ // Convert to URL-safe slug
109
+ return typeof value === 'string'
110
+ ? value
111
+ .toLowerCase()
112
+ .replace(/[^\p{L}\p{N}]+/gu, '-')
113
+ .replace(/^-|-$/g, '')
114
+ : value;
115
+ case 'sanitize':
116
+ // Remove invalid filename characters
117
+ return typeof value === 'string'
118
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional - strips C0 control chars from filenames
119
+ ? value.replace(/[<>:"/\\|?*\x00-\x1f]/g, '_')
120
+ : value;
121
+ case 'ext': {
122
+ // Extract file extension from URL or path
123
+ if (typeof value !== 'string')
124
+ return value;
125
+ const lastDot = value.lastIndexOf('.');
126
+ const lastSlash = Math.max(value.lastIndexOf('/'), value.lastIndexOf('\\'));
127
+ return lastDot > lastSlash ? value.slice(lastDot) : '';
128
+ }
129
+ case 'basename': {
130
+ // Extract filename from URL or path
131
+ if (typeof value !== 'string')
132
+ return value;
133
+ const parts = value.split(/[/\\]/);
134
+ return parts[parts.length - 1] || value;
135
+ }
136
+ case 'urlencode':
137
+ return typeof value === 'string' ? encodeURIComponent(value) : value;
138
+ case 'urldecode':
139
+ return typeof value === 'string' ? decodeURIComponent(value) : value;
140
+ default:
141
+ return value;
142
+ }
143
+ }
144
+ export function resolvePath(pathStr, ctx) {
145
+ const args = ctx.args ?? {};
146
+ const item = ctx.item ?? {};
147
+ const data = ctx.data;
148
+ const root = ctx.root;
149
+ const index = ctx.index ?? 0;
150
+ const parts = pathStr.split('.');
151
+ const rootName = parts[0];
152
+ let obj;
153
+ let rest;
154
+ if (rootName === 'args') {
155
+ obj = args;
156
+ rest = parts.slice(1);
157
+ }
158
+ else if (rootName === 'item') {
159
+ obj = item;
160
+ rest = parts.slice(1);
161
+ }
162
+ else if (rootName === 'data') {
163
+ obj = data;
164
+ rest = parts.slice(1);
165
+ }
166
+ else if (rootName === 'root') {
167
+ obj = root;
168
+ rest = parts.slice(1);
169
+ }
170
+ else if (rootName === 'index')
171
+ return index;
172
+ else {
173
+ obj = item;
174
+ rest = parts;
175
+ }
176
+ for (const part of rest) {
177
+ if (isRecord(obj))
178
+ obj = obj[part];
179
+ else if (Array.isArray(obj) && /^\d+$/.test(part))
180
+ obj = obj[parseInt(part, 10)];
181
+ else
182
+ return null;
183
+ }
184
+ return obj;
185
+ }
186
+ /**
187
+ * Evaluate arbitrary JS expressions as a last-resort fallback.
188
+ * Runs inside a `node:vm` sandbox with dynamic code generation disabled.
189
+ *
190
+ * Compiled functions are cached by expression string to avoid re-creating
191
+ * VM contexts on every invocation — critical for loops where the same
192
+ * expression is evaluated hundreds of times.
193
+ */
194
+ const FORBIDDEN_EXPR_PATTERNS = /\b(constructor|__proto__|prototype|globalThis|process|require|import|eval)\b/;
195
+ /**
196
+ * Deep-copy plain data to sever prototype chains, preventing sandbox escape
197
+ * via `args.constructor.constructor('return process')()` etc.
198
+ *
199
+ * Uses a WeakMap cache keyed by object reference: when the same object
200
+ * (e.g. `args` or `data`) is passed repeatedly across loop iterations,
201
+ * the expensive JSON round-trip is performed only once. The WeakMap
202
+ * lets entries be GC'd when the source object is no longer referenced.
203
+ */
204
+ /**
205
+ * Cache serialized JSON strings (not parsed objects) by source reference.
206
+ * Caching the parsed object would be unsafe: the VM sandbox could mutate it,
207
+ * and the polluted version would leak to subsequent calls. By caching the
208
+ * string and returning a fresh JSON.parse() each time, every evaluation gets
209
+ * its own clean deep-copy while still avoiding redundant JSON.stringify()
210
+ * for the same unchanged source object across loop iterations.
211
+ */
212
+ const _sanitizeCache = new WeakMap();
213
+ function sanitizeContext(obj) {
214
+ if (obj === null || obj === undefined)
215
+ return obj;
216
+ if (typeof obj !== 'object' && typeof obj !== 'function')
217
+ return obj;
218
+ const objRef = obj;
219
+ const cached = _sanitizeCache.get(objRef);
220
+ if (cached !== undefined)
221
+ return JSON.parse(cached);
222
+ try {
223
+ // BigInt is non-serializable by default but is the most common cause of
224
+ // sanitizeContext failures (e.g. GraphQL 64-bit IDs). Coerce to string
225
+ // so callers see the value instead of a silent {}.
226
+ const jsonStr = JSON.stringify(obj, (_key, value) => typeof value === 'bigint' ? value.toString() : value);
227
+ _sanitizeCache.set(objRef, jsonStr);
228
+ return JSON.parse(jsonStr);
229
+ }
230
+ catch (err) {
231
+ log.warn(`[pipeline/template] sanitizeContext failed: ${err instanceof Error ? err.message : String(err)}. ` +
232
+ `Returning {} for this branch. Likely cause: circular reference, Symbol, or other non-serializable value in pipeline context.`);
233
+ return {};
234
+ }
235
+ }
236
+ /** LRU-bounded cache for compiled VM scripts — prevents unbounded memory growth. */
237
+ const MAX_VM_CACHE_SIZE = 256;
238
+ const _vmCache = new Map();
239
+ function getOrCompileScript(expr) {
240
+ let script = _vmCache.get(expr);
241
+ if (script)
242
+ return script;
243
+ // Evict oldest entry when cache is full
244
+ if (_vmCache.size >= MAX_VM_CACHE_SIZE) {
245
+ const firstKey = _vmCache.keys().next().value;
246
+ if (firstKey !== undefined)
247
+ _vmCache.delete(firstKey);
248
+ }
249
+ script = new vm.Script(`(${expr})`);
250
+ _vmCache.set(expr, script);
251
+ return script;
252
+ }
253
+ /**
254
+ * Reusable VM sandbox context.
255
+ *
256
+ * vm.createContext() is expensive (~0.3ms per call) because it creates a new
257
+ * V8 context with its own global object. In pipeline loops (map/filter over
258
+ * hundreds of items), this adds up to significant overhead.
259
+ *
260
+ * Instead, we create the context once and mutate the sandbox properties
261
+ * before each evaluation. This is safe because:
262
+ * 1. Sandbox properties are sanitized (deep-copied) before assignment
263
+ * 2. Scripts run with a 50ms timeout
264
+ * 3. codeGeneration is disabled (no eval/Function inside the sandbox)
265
+ */
266
+ let _reusableSandbox = null;
267
+ let _reusableContext = null;
268
+ function getReusableContext() {
269
+ if (_reusableSandbox && _reusableContext) {
270
+ return { sandbox: _reusableSandbox, context: _reusableContext };
271
+ }
272
+ _reusableSandbox = {
273
+ args: {},
274
+ item: {},
275
+ data: null,
276
+ root: null,
277
+ index: 0,
278
+ encodeURIComponent,
279
+ decodeURIComponent,
280
+ JSON,
281
+ Math,
282
+ Number,
283
+ String,
284
+ Boolean,
285
+ Array,
286
+ Date,
287
+ };
288
+ _reusableContext = vm.createContext(_reusableSandbox, {
289
+ codeGeneration: { strings: false, wasm: false },
290
+ });
291
+ return { sandbox: _reusableSandbox, context: _reusableContext };
292
+ }
293
+ /** Properties that are part of the sandbox's initial shape and safe to keep. */
294
+ const SANDBOX_WHITELIST = new Set([
295
+ 'args', 'item', 'data', 'root', 'index',
296
+ 'encodeURIComponent', 'decodeURIComponent',
297
+ 'JSON', 'Math', 'Number', 'String', 'Boolean', 'Array', 'Date',
298
+ ]);
299
+ function evalJsExpr(expr, ctx) {
300
+ // Guard against absurdly long expressions that could indicate injection.
301
+ if (expr.length > 2000)
302
+ return undefined;
303
+ // Block obvious sandbox escape attempts.
304
+ if (FORBIDDEN_EXPR_PATTERNS.test(expr))
305
+ return undefined;
306
+ try {
307
+ const script = getOrCompileScript(expr);
308
+ const { sandbox, context } = getReusableContext();
309
+ // Clean non-whitelisted properties that a previous script may have added.
310
+ // Without this, `${{ x = 42 }}` would leak `x` into subsequent evaluations.
311
+ for (const key of Object.keys(sandbox)) {
312
+ if (!SANDBOX_WHITELIST.has(key)) {
313
+ delete sandbox[key];
314
+ }
315
+ }
316
+ // Update mutable sandbox properties — sanitizeContext severs prototype chains.
317
+ sandbox.args = sanitizeContext(ctx.args ?? {});
318
+ sandbox.item = sanitizeContext(ctx.item ?? {});
319
+ sandbox.data = sanitizeContext(ctx.data);
320
+ sandbox.root = sanitizeContext(ctx.root);
321
+ sandbox.index = ctx.index ?? 0;
322
+ return script.runInContext(context, { timeout: 50 });
323
+ }
324
+ catch {
325
+ return undefined;
326
+ }
327
+ }
328
+ /**
329
+ * Normalize JavaScript source for browser evaluate() calls.
330
+ */
331
+ export function normalizeEvaluateSource(source) {
332
+ const stripped = source.trim();
333
+ if (!stripped)
334
+ return '() => undefined';
335
+ if (stripped.startsWith('(') && stripped.endsWith(')()'))
336
+ return `() => (${stripped})`;
337
+ if (/^(async\s+)?\([^)]*\)\s*=>/.test(stripped))
338
+ return stripped;
339
+ if (/^(async\s+)?[A-Za-z_][A-Za-z0-9_]*\s*=>/.test(stripped))
340
+ return stripped;
341
+ if (stripped.startsWith('function ') || stripped.startsWith('async function '))
342
+ return stripped;
343
+ return `() => (${stripped})`;
344
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Tests for the pipeline template engine: render, evalExpr, resolvePath.
3
+ */
4
+ export {};