sourcemonkey 0.0.0-stage → 0.5.0

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 (367) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -2
  3. package/dist/bytes.js +37 -0
  4. package/dist/channel-placeholder.js +5 -0
  5. package/dist/collection-scan.js +17 -0
  6. package/dist/collections.html +353 -0
  7. package/dist/compare.html +358 -0
  8. package/dist/composed-source.js +205 -0
  9. package/dist/connect-prompt.html +47 -0
  10. package/dist/debug/icons.html +211 -0
  11. package/dist/debug/storage.html +163 -0
  12. package/dist/debug-log.js +75 -0
  13. package/dist/diagnostic-location.js +64 -0
  14. package/dist/eval-hook.js +308 -0
  15. package/dist/extension/background.js +5263 -0
  16. package/dist/extension/channel.js +133 -0
  17. package/dist/extension/code-links.js +187 -0
  18. package/dist/extension/code-tabs.js +460 -0
  19. package/dist/extension/collection-dialog.js +619 -0
  20. package/dist/extension/collection-display.js +322 -0
  21. package/dist/extension/collections.js +2905 -0
  22. package/dist/extension/compare.js +867 -0
  23. package/dist/extension/concurrency.js +186 -0
  24. package/dist/extension/connect-grants.js +109 -0
  25. package/dist/extension/connect-prompt-page.js +70 -0
  26. package/dist/extension/connect-prompt.js +266 -0
  27. package/dist/extension/copy-button.js +63 -0
  28. package/dist/extension/copy-dialog.js +502 -0
  29. package/dist/extension/copy-preference.js +66 -0
  30. package/dist/extension/debug/icons.js +203 -0
  31. package/dist/extension/debug/storage.js +365 -0
  32. package/dist/extension/deep-link.js +77 -0
  33. package/dist/extension/delete-dialog.js +432 -0
  34. package/dist/extension/delete-icon.js +40 -0
  35. package/dist/extension/details-tooltips.js +66 -0
  36. package/dist/extension/directories.js +679 -0
  37. package/dist/extension/export-backup.js +407 -0
  38. package/dist/extension/export-dialog.js +142 -0
  39. package/dist/extension/file-access.js +74 -0
  40. package/dist/extension/file-changes.js +346 -0
  41. package/dist/extension/frame-info.js +85 -0
  42. package/dist/extension/github-provider.js +336 -0
  43. package/dist/extension/glyph.js +84 -0
  44. package/dist/extension/gm-bindings.js +601 -0
  45. package/dist/extension/gm-download.js +419 -0
  46. package/dist/extension/gm-menu.js +228 -0
  47. package/dist/extension/gm-notification.js +141 -0
  48. package/dist/extension/gm-originator-map.js +23 -0
  49. package/dist/extension/gm-tab-data.js +121 -0
  50. package/dist/extension/gm-tab.js +160 -0
  51. package/dist/extension/gm-url-change.js +111 -0
  52. package/dist/extension/gm-url-scheme.js +27 -0
  53. package/dist/extension/gm-values.js +176 -0
  54. package/dist/extension/gm-window-control.js +104 -0
  55. package/dist/extension/gm-xhr-headers.js +333 -0
  56. package/dist/extension/gm-xhr.js +584 -0
  57. package/dist/extension/injector.js +3145 -0
  58. package/dist/extension/install-capture.js +277 -0
  59. package/dist/extension/line-diff.js +233 -0
  60. package/dist/extension/local-copy.js +560 -0
  61. package/dist/extension/local-delete.js +276 -0
  62. package/dist/extension/location-kinds.js +108 -0
  63. package/dist/extension/log-format.js +158 -0
  64. package/dist/extension/managed-changes.js +361 -0
  65. package/dist/extension/managed-items.js +57 -0
  66. package/dist/extension/match-index.js +375 -0
  67. package/dist/extension/missing-scripts.js +66 -0
  68. package/dist/extension/more-menu.js +109 -0
  69. package/dist/extension/move-dialog.js +197 -0
  70. package/dist/extension/offscreen.js +37 -0
  71. package/dist/extension/options.js +504 -0
  72. package/dist/extension/page-heading.js +170 -0
  73. package/dist/extension/page-links.js +199 -0
  74. package/dist/extension/parse-check-client.js +70 -0
  75. package/dist/extension/parse-check.js +161 -0
  76. package/dist/extension/parse-sandbox-host.js +172 -0
  77. package/dist/extension/parse-sandbox.js +175 -0
  78. package/dist/extension/popup-commands-open.js +41 -0
  79. package/dist/extension/popup-view.js +387 -0
  80. package/dist/extension/popup.js +703 -0
  81. package/dist/extension/prism-userscript.js +53 -0
  82. package/dist/extension/refresh-error.js +136 -0
  83. package/dist/extension/refresh-targets.js +160 -0
  84. package/dist/extension/related-versions.js +1144 -0
  85. package/dist/extension/resize-observer-loop.js +19 -0
  86. package/dist/extension/row-cache.js +387 -0
  87. package/dist/extension/script-blobs.js +413 -0
  88. package/dist/extension/script-details.js +658 -0
  89. package/dist/extension/script-enablement.js +285 -0
  90. package/dist/extension/script-identity.js +310 -0
  91. package/dist/extension/script-keys.js +54 -0
  92. package/dist/extension/script-log-id.js +155 -0
  93. package/dist/extension/script-log.js +290 -0
  94. package/dist/extension/script-rejection.js +104 -0
  95. package/dist/extension/script-sites.js +158 -0
  96. package/dist/extension/script-store.js +3507 -0
  97. package/dist/extension/script-updater.js +991 -0
  98. package/dist/extension/script-url-hash.js +61 -0
  99. package/dist/extension/select-all.js +37 -0
  100. package/dist/extension/select-open-guard.js +90 -0
  101. package/dist/extension/site-icon.js +1261 -0
  102. package/dist/extension/sm-dev-link.js +302 -0
  103. package/dist/extension/solo-click.js +58 -0
  104. package/dist/extension/sticky-numbers.js +188 -0
  105. package/dist/extension/storage-breakdown.js +253 -0
  106. package/dist/extension/storage-scan.js +86 -0
  107. package/dist/extension/storage-usage.js +194 -0
  108. package/dist/extension/structural-keys.js +29 -0
  109. package/dist/extension/sw-teardown.js +36 -0
  110. package/dist/extension/tab-status.js +403 -0
  111. package/dist/extension/toolbar-summary.js +105 -0
  112. package/dist/extension/user-scripts-access.js +43 -0
  113. package/dist/extension/userscript.js +3672 -0
  114. package/dist/extension/value-store.js +204 -0
  115. package/dist/extension/version-probe-fetch.js +68 -0
  116. package/dist/extension/worker-client.js +109 -0
  117. package/dist/extension/worker-ops.js +171 -0
  118. package/dist/extension/zip-writer.js +24 -0
  119. package/dist/external-files.js +878 -0
  120. package/dist/file-loader.js +436 -0
  121. package/dist/file-locations.js +439 -0
  122. package/dist/generated-wrappers.js +5 -0
  123. package/dist/github-auth.js +148 -0
  124. package/dist/github-urls.js +46 -0
  125. package/dist/gm-api-catalog.js +217 -0
  126. package/dist/gm-connect.js +273 -0
  127. package/dist/gm-xhr-types.js +5 -0
  128. package/dist/http-read.js +142 -0
  129. package/dist/icons/icon-128.png +0 -0
  130. package/dist/icons/icon-16.png +0 -0
  131. package/dist/icons/icon-48.png +0 -0
  132. package/dist/local-file-overrides.js +558 -0
  133. package/dist/manifest.json +38 -0
  134. package/dist/markup-response.js +126 -0
  135. package/dist/match-targets.js +305 -0
  136. package/dist/menu-captions.js +22 -0
  137. package/dist/offscreen.html +39 -0
  138. package/dist/options.html +197 -0
  139. package/dist/parse-check-protocol.js +51 -0
  140. package/dist/parse-location.js +171 -0
  141. package/dist/parse-sandbox.html +56 -0
  142. package/dist/phase-timing.js +155 -0
  143. package/dist/popup.html +197 -0
  144. package/dist/public-suffixes.js +6957 -0
  145. package/dist/run-context.js +31 -0
  146. package/dist/runtime-messages.js +34 -0
  147. package/dist/sandboxed-page.js +35 -0
  148. package/dist/script-build.js +787 -0
  149. package/dist/script-display.js +383 -0
  150. package/dist/script-icon.js +43 -0
  151. package/dist/script-links.js +204 -0
  152. package/dist/script-source-url.js +214 -0
  153. package/dist/script-world.js +65 -0
  154. package/dist/sm-dev-protocol.js +84 -0
  155. package/dist/source-map.js +177 -0
  156. package/dist/stack-link.js +138 -0
  157. package/dist/styles.css +825 -0
  158. package/dist/unsafe-window-use.js +229 -0
  159. package/dist/url-match.js +734 -0
  160. package/dist/userscript-header.js +248 -0
  161. package/dist/userscript.html +1165 -0
  162. package/dist/vendor/fflate.LICENSE +21 -0
  163. package/dist/vendor/fflate.js +2692 -0
  164. package/dist/vendor/prism/prism-line-numbers.css +1 -0
  165. package/dist/vendor/prism/prism-line-numbers.js +1 -0
  166. package/dist/vendor/prism/prism.css +1 -0
  167. package/dist/vendor/prism/prism.js +1946 -0
  168. package/dist/version-compare.js +141 -0
  169. package/dist/version-probe.js +120 -0
  170. package/lib/build-info.json +1 -0
  171. package/lib/bytes.d.ts +3 -0
  172. package/lib/bytes.js +37 -0
  173. package/lib/channel-placeholder.d.ts +1 -0
  174. package/lib/channel-placeholder.js +5 -0
  175. package/lib/collection-scan.d.ts +8 -0
  176. package/lib/collection-scan.js +17 -0
  177. package/lib/composed-source.d.ts +28 -0
  178. package/lib/composed-source.js +205 -0
  179. package/lib/debug-log.d.ts +9 -0
  180. package/lib/debug-log.js +75 -0
  181. package/lib/diagnostic-location.d.ts +8 -0
  182. package/lib/diagnostic-location.js +64 -0
  183. package/lib/eval-hook.d.ts +34 -0
  184. package/lib/eval-hook.js +308 -0
  185. package/lib/external-files.d.ts +111 -0
  186. package/lib/external-files.js +878 -0
  187. package/lib/file-loader.d.ts +48 -0
  188. package/lib/file-loader.js +436 -0
  189. package/lib/file-locations.d.ts +44 -0
  190. package/lib/file-locations.js +439 -0
  191. package/lib/generated-wrappers.d.ts +11 -0
  192. package/lib/generated-wrappers.js +5 -0
  193. package/lib/github-auth.d.ts +12 -0
  194. package/lib/github-auth.js +148 -0
  195. package/lib/github-urls.d.ts +1 -0
  196. package/lib/github-urls.js +46 -0
  197. package/lib/gm-api-catalog.d.ts +24 -0
  198. package/lib/gm-api-catalog.js +217 -0
  199. package/lib/gm-connect.d.ts +34 -0
  200. package/lib/gm-connect.js +273 -0
  201. package/lib/gm-xhr-types.d.ts +68 -0
  202. package/lib/gm-xhr-types.js +5 -0
  203. package/lib/harness/browser-extensions.d.ts +73 -0
  204. package/lib/harness/browser-extensions.js +285 -0
  205. package/lib/harness/browser-lang.d.ts +20 -0
  206. package/lib/harness/browser-lang.js +86 -0
  207. package/lib/harness/browser-launch.d.ts +14 -0
  208. package/lib/harness/browser-launch.js +184 -0
  209. package/lib/harness/checks.d.ts +110 -0
  210. package/lib/harness/checks.js +321 -0
  211. package/lib/harness/cli.d.ts +2 -0
  212. package/lib/harness/cli.js +2259 -0
  213. package/lib/harness/command-args.d.ts +91 -0
  214. package/lib/harness/command-args.js +369 -0
  215. package/lib/harness/command-lines.d.ts +80 -0
  216. package/lib/harness/command-lines.js +180 -0
  217. package/lib/harness/command-list.d.ts +206 -0
  218. package/lib/harness/command-list.js +1475 -0
  219. package/lib/harness/console-commands.d.ts +463 -0
  220. package/lib/harness/console-commands.js +3216 -0
  221. package/lib/harness/download-watch.d.ts +21 -0
  222. package/lib/harness/download-watch.js +156 -0
  223. package/lib/harness/extension-backend.d.ts +41 -0
  224. package/lib/harness/extension-backend.js +100 -0
  225. package/lib/harness/extension-host.d.ts +112 -0
  226. package/lib/harness/extension-host.js +552 -0
  227. package/lib/harness/extension-launch.d.ts +67 -0
  228. package/lib/harness/extension-launch.js +285 -0
  229. package/lib/harness/extension-link.d.ts +315 -0
  230. package/lib/harness/extension-link.js +607 -0
  231. package/lib/harness/external-manager.d.ts +146 -0
  232. package/lib/harness/external-manager.js +414 -0
  233. package/lib/harness/fixture.d.ts +165 -0
  234. package/lib/harness/fixture.js +461 -0
  235. package/lib/harness/frame-sessions.d.ts +71 -0
  236. package/lib/harness/frame-sessions.js +248 -0
  237. package/lib/harness/frames.d.ts +68 -0
  238. package/lib/harness/frames.js +216 -0
  239. package/lib/harness/help-format.d.ts +17 -0
  240. package/lib/harness/help-format.js +127 -0
  241. package/lib/harness/host.d.ts +352 -0
  242. package/lib/harness/host.js +423 -0
  243. package/lib/harness/index.d.ts +8 -0
  244. package/lib/harness/index.js +10 -0
  245. package/lib/harness/input-file.d.ts +18 -0
  246. package/lib/harness/input-file.js +61 -0
  247. package/lib/harness/json-output.d.ts +565 -0
  248. package/lib/harness/json-output.js +71 -0
  249. package/lib/harness/manager-actions.d.ts +21 -0
  250. package/lib/harness/manager-actions.js +129 -0
  251. package/lib/harness/manager-commands.d.ts +142 -0
  252. package/lib/harness/manager-commands.js +1196 -0
  253. package/lib/harness/manager-fetch.d.ts +33 -0
  254. package/lib/harness/manager-fetch.js +239 -0
  255. package/lib/harness/managers.d.ts +24 -0
  256. package/lib/harness/managers.js +27 -0
  257. package/lib/harness/output-style.d.ts +125 -0
  258. package/lib/harness/output-style.js +322 -0
  259. package/lib/harness/page-commands.d.ts +134 -0
  260. package/lib/harness/page-commands.js +1141 -0
  261. package/lib/harness/page-output.d.ts +67 -0
  262. package/lib/harness/page-output.js +139 -0
  263. package/lib/harness/page-watch.d.ts +171 -0
  264. package/lib/harness/page-watch.js +607 -0
  265. package/lib/harness/parse-check-node.d.ts +3 -0
  266. package/lib/harness/parse-check-node.js +132 -0
  267. package/lib/harness/path-args.d.ts +22 -0
  268. package/lib/harness/path-args.js +148 -0
  269. package/lib/harness/playwright-chromium.d.ts +16 -0
  270. package/lib/harness/playwright-chromium.js +86 -0
  271. package/lib/harness/prepare.d.ts +168 -0
  272. package/lib/harness/prepare.js +364 -0
  273. package/lib/harness/prompt-editor.d.ts +17 -0
  274. package/lib/harness/prompt-editor.js +354 -0
  275. package/lib/harness/prompt-history.d.ts +13 -0
  276. package/lib/harness/prompt-history.js +89 -0
  277. package/lib/harness/rebuild-advice.d.ts +6 -0
  278. package/lib/harness/rebuild-advice.js +39 -0
  279. package/lib/harness/run-log.d.ts +47 -0
  280. package/lib/harness/run-log.js +140 -0
  281. package/lib/harness/run-logs.d.ts +132 -0
  282. package/lib/harness/run-logs.js +241 -0
  283. package/lib/harness/run.d.ts +194 -0
  284. package/lib/harness/run.js +1973 -0
  285. package/lib/harness/runs.d.ts +229 -0
  286. package/lib/harness/runs.js +726 -0
  287. package/lib/harness/save-html.d.ts +39 -0
  288. package/lib/harness/save-html.js +89 -0
  289. package/lib/harness/saved-pages.d.ts +120 -0
  290. package/lib/harness/saved-pages.js +275 -0
  291. package/lib/harness/script-mark.d.ts +17 -0
  292. package/lib/harness/script-mark.js +56 -0
  293. package/lib/harness/snapshot.d.ts +143 -0
  294. package/lib/harness/snapshot.js +474 -0
  295. package/lib/harness/stuck-tabs.d.ts +19 -0
  296. package/lib/harness/stuck-tabs.js +131 -0
  297. package/lib/harness/tab-refs.d.ts +20 -0
  298. package/lib/harness/tab-refs.js +80 -0
  299. package/lib/harness/tampermonkey.d.ts +71 -0
  300. package/lib/harness/tampermonkey.js +356 -0
  301. package/lib/harness/tm-ids.d.ts +18 -0
  302. package/lib/harness/tm-ids.js +88 -0
  303. package/lib/harness/violentmonkey.d.ts +34 -0
  304. package/lib/harness/violentmonkey.js +162 -0
  305. package/lib/harness/wait.d.ts +77 -0
  306. package/lib/harness/wait.js +458 -0
  307. package/lib/http-read.d.ts +30 -0
  308. package/lib/http-read.js +142 -0
  309. package/lib/local-file-overrides.d.ts +35 -0
  310. package/lib/local-file-overrides.js +558 -0
  311. package/lib/manifest.json +38 -0
  312. package/lib/markup-response.d.ts +11 -0
  313. package/lib/markup-response.js +126 -0
  314. package/lib/match-targets.d.ts +18 -0
  315. package/lib/match-targets.js +305 -0
  316. package/lib/menu-captions.d.ts +1 -0
  317. package/lib/menu-captions.js +22 -0
  318. package/lib/parse-check-protocol.d.ts +27 -0
  319. package/lib/parse-check-protocol.js +51 -0
  320. package/lib/parse-location.d.ts +12 -0
  321. package/lib/parse-location.js +171 -0
  322. package/lib/phase-timing.d.ts +12 -0
  323. package/lib/phase-timing.js +155 -0
  324. package/lib/public-suffixes.d.ts +1 -0
  325. package/lib/public-suffixes.js +6957 -0
  326. package/lib/run-context.d.ts +2 -0
  327. package/lib/run-context.js +31 -0
  328. package/lib/runtime-messages.d.ts +10 -0
  329. package/lib/runtime-messages.js +34 -0
  330. package/lib/sandboxed-page.d.ts +5 -0
  331. package/lib/sandboxed-page.js +35 -0
  332. package/lib/script-build.d.ts +111 -0
  333. package/lib/script-build.js +787 -0
  334. package/lib/script-display.d.ts +51 -0
  335. package/lib/script-display.js +383 -0
  336. package/lib/script-icon.d.ts +16 -0
  337. package/lib/script-icon.js +43 -0
  338. package/lib/script-links.d.ts +24 -0
  339. package/lib/script-links.js +204 -0
  340. package/lib/script-source-url.d.ts +8 -0
  341. package/lib/script-source-url.js +214 -0
  342. package/lib/script-world.d.ts +6 -0
  343. package/lib/script-world.js +65 -0
  344. package/lib/sm-dev-protocol.d.ts +251 -0
  345. package/lib/sm-dev-protocol.js +84 -0
  346. package/lib/source-map.d.ts +32 -0
  347. package/lib/source-map.js +177 -0
  348. package/lib/stack-link.d.ts +15 -0
  349. package/lib/stack-link.js +138 -0
  350. package/lib/unsafe-window-use.d.ts +1 -0
  351. package/lib/unsafe-window-use.js +229 -0
  352. package/lib/url-match.d.ts +40 -0
  353. package/lib/url-match.js +734 -0
  354. package/lib/userscript-header.d.ts +33 -0
  355. package/lib/userscript-header.js +248 -0
  356. package/lib/version-compare.d.ts +6 -0
  357. package/lib/version-compare.js +141 -0
  358. package/lib/version-probe.d.ts +17 -0
  359. package/lib/version-probe.js +120 -0
  360. package/package.json +55 -3
  361. package/skills/SourceMonkey-dev/SKILL.md +868 -0
  362. package/skills/SourceMonkey-dev/references/cdp.md +293 -0
  363. package/skills/SourceMonkey-dev/references/commands.md +297 -0
  364. package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
  365. package/skills/SourceMonkey-dev/references/specs.md +46 -0
  366. package/skills/SourceMonkey-friction/SKILL.md +103 -0
  367. package/skills/SourceMonkey-friction/references/template.md +59 -0
@@ -0,0 +1,88 @@
1
+ // The E-numbers sm-dev gives Tampermonkey's scripts, whose own ids are
2
+ // uuids: one file in sm-dev's cache, `tampermonkey-ids.json`, mapping
3
+ // each uuid to its number. A uuid is unique across browsers, so one
4
+ // file serves them all. A number stays with its uuid for a week after
5
+ // sm-dev last saw it, as SourceMonkey keeps its numbers after a
6
+ // removal. See docs/sm-dev-tampermonkey.md.
7
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
8
+ import path from 'node:path';
9
+ import { managerCacheDir } from './manager-fetch.js';
10
+ const KEEP_MS = 7 * 24 * 60 * 60 * 1000;
11
+ // `SM_DEV_TM_IDS` moves it, as the tests do, to keep their scripts'
12
+ // numbers out of the person's own file.
13
+ function file() {
14
+ return process.env.SM_DEV_TM_IDS?.trim() || path.join(path.dirname(managerCacheDir()), 'tampermonkey-ids.json');
15
+ }
16
+ function load() {
17
+ try {
18
+ const saved = JSON.parse(readFileSync(file(), 'utf8'));
19
+ if (typeof saved.next === 'number' && saved.ids && typeof saved.ids === 'object')
20
+ return saved;
21
+ }
22
+ catch {
23
+ // None yet, or unreadable: numbering starts again.
24
+ }
25
+ return { next: 1, ids: {} };
26
+ }
27
+ /** The numbers of Tampermonkey's scripts, by uuid, read from and kept in sm-dev's cache. */
28
+ export class TmIds {
29
+ saved = load();
30
+ byNumber = new Map();
31
+ constructor() {
32
+ this.index();
33
+ }
34
+ index() {
35
+ this.byNumber.clear();
36
+ for (const [uuid, { n }] of Object.entries(this.saved.ids))
37
+ this.byNumber.set(n, uuid);
38
+ }
39
+ /**
40
+ * The numbers of `uuids`, the scripts installed now, giving each new
41
+ * one the next number. Saves the file when anything changed, read
42
+ * again first so another sm-dev's numbers aren't lost.
43
+ */
44
+ numbersOf(uuids) {
45
+ const now = Date.now();
46
+ this.saved = load();
47
+ let changed = false;
48
+ for (const uuid of uuids) {
49
+ const known = this.saved.ids[uuid];
50
+ if (known) {
51
+ // Kept in step only once a day: a save per listing isn't needed.
52
+ if (now - known.seen > 24 * 60 * 60 * 1000) {
53
+ known.seen = now;
54
+ changed = true;
55
+ }
56
+ continue;
57
+ }
58
+ this.saved.ids[uuid] = { n: this.saved.next++, seen: now };
59
+ changed = true;
60
+ }
61
+ for (const [uuid, { seen }] of Object.entries(this.saved.ids)) {
62
+ if (now - seen > KEEP_MS && !uuids.includes(uuid)) {
63
+ delete this.saved.ids[uuid];
64
+ changed = true;
65
+ }
66
+ }
67
+ if (changed)
68
+ this.save();
69
+ this.index();
70
+ return new Map(uuids.map((uuid) => [uuid, this.saved.ids[uuid].n]));
71
+ }
72
+ /** The number of `uuid`, when it has one. */
73
+ numberOf(uuid) {
74
+ return this.saved.ids[uuid]?.n;
75
+ }
76
+ /** The uuid number `n` was given, when it's still kept. */
77
+ uuidOf(n) {
78
+ return this.byNumber.get(n);
79
+ }
80
+ save() {
81
+ const to = file();
82
+ mkdirSync(path.dirname(to), { recursive: true });
83
+ // Whole or not at all, for another sm-dev reading it meanwhile.
84
+ const tmp = `${to}.${process.pid}.tmp`;
85
+ writeFileSync(tmp, `${JSON.stringify(this.saved)}\n`);
86
+ renameSync(tmp, to);
87
+ }
88
+ }
@@ -0,0 +1,34 @@
1
+ import type { ExternalManager, ExternalScript, InstallOptions } from './external-manager.js';
2
+ /** Violentmonkey in one browser, over a hidden page of its own until `close`. */
3
+ export declare class Violentmonkey implements ExternalManager {
4
+ private readonly page;
5
+ readonly extensionId: string;
6
+ readonly version: string;
7
+ readonly name: "violentmonkey";
8
+ readonly label: string;
9
+ private constructor();
10
+ /**
11
+ * Connects to VM in the browser at `endpoint`. Throws saying why when
12
+ * it isn't installed and enabled there. `browserArg`: the flags
13
+ * that name the browser in the advice (see `browserArg` in run.ts).
14
+ */
15
+ static open(endpoint: string, browserArg?: string): Promise<Violentmonkey>;
16
+ /** Makes one call. Its failure names the call and VM's version. */
17
+ call<R>(cmd: string, data?: unknown): Promise<R>;
18
+ scripts(): Promise<ExternalScript[]>;
19
+ texts(ids: number[]): Promise<Map<number, string>>;
20
+ install(code: string, options?: InstallOptions): Promise<{
21
+ id: number;
22
+ isNew: boolean;
23
+ }>;
24
+ setEnabled(id: number, enabled: boolean): Promise<void>;
25
+ uninstall(id: number): Promise<void>;
26
+ remove(ids: number[]): Promise<void>;
27
+ applied(): Promise<boolean>;
28
+ setApplied(on: boolean): Promise<void>;
29
+ allowFilePages(): Promise<boolean>;
30
+ scriptIdOf(url: string): number | undefined;
31
+ get scriptUrlPrefix(): string;
32
+ close(): Promise<void>;
33
+ private options;
34
+ }
@@ -0,0 +1,162 @@
1
+ // Violentmonkey (VM), driven by the messages its own pages send its
2
+ // background: `{cmd, data}` through `chrome.runtime.sendMessage`, from
3
+ // a hidden page of VM's own (its options page), since VM answers no
4
+ // other sender. Not a published API: what each call takes and gives is
5
+ // listed in docs/sm-dev-violentmonkey.md, which the version check
6
+ // (tests/vm-api/vm-api.spec.ts) tries against a fetched VM.
7
+ import { installedManagers, openHiddenPage } from './browser-extensions.js';
8
+ import { MANAGERS } from './managers.js';
9
+ import { quoted } from './output-style.js';
10
+ // The page the calls are sent from, as VM's manifest names it.
11
+ const OPTIONS_PAGE = 'options/index.html';
12
+ // Chrome's words when nothing answered a message: VM has no such call.
13
+ const NO_ANSWER = /message port closed|Receiving end does not exist/i;
14
+ /** Violentmonkey in one browser, over a hidden page of its own until `close`. */
15
+ export class Violentmonkey {
16
+ page;
17
+ extensionId;
18
+ version;
19
+ name = 'violentmonkey';
20
+ label = MANAGERS.violentmonkey.label;
21
+ constructor(page, extensionId, version) {
22
+ this.page = page;
23
+ this.extensionId = extensionId;
24
+ this.version = version;
25
+ }
26
+ /**
27
+ * Connects to VM in the browser at `endpoint`. Throws saying why when
28
+ * it isn't installed and enabled there. `browserArg`: the flags
29
+ * that name the browser in the advice (see `browserArg` in run.ts).
30
+ */
31
+ static async open(endpoint, browserArg = '') {
32
+ const label = MANAGERS.violentmonkey.label;
33
+ const copies = (await installedManagers(endpoint)).filter((m) => m.manager === 'violentmonkey');
34
+ const copy = copies.find((m) => m.enabled);
35
+ if (!copy) {
36
+ throw new Error(`${label} is ${copies.length > 0 ? 'turned off' : 'not installed'} in this browser. Use ${quoted(`sm-dev${browserArg} --manager vm manager ${copies.length > 0 ? 'enable' : 'install'}`)}.`);
37
+ }
38
+ let page;
39
+ try {
40
+ // Once loaded: a call made while the page's own scripts start can
41
+ // get its answer wrapped (`[result]`), as VM's pages get theirs.
42
+ page = await openHiddenPage(endpoint, `chrome-extension://${copy.id}/${OPTIONS_PAGE}`, 'document.readyState === "complete" && typeof chrome?.runtime?.sendMessage === "function"');
43
+ }
44
+ catch (err) {
45
+ throw new Error(`${label} ${copy.version}'s options page could not be opened: ${err.message}`, { cause: err });
46
+ }
47
+ return new Violentmonkey(page, copy.id, copy.version);
48
+ }
49
+ /** Makes one call. Its failure names the call and VM's version. */
50
+ async call(cmd, data) {
51
+ try {
52
+ return await this.page.evaluate(`chrome.runtime.sendMessage(${JSON.stringify({ cmd, data })})`);
53
+ }
54
+ catch (err) {
55
+ const why = err.message.replace(/^Error: /, '');
56
+ if (NO_ANSWER.test(why)) {
57
+ throw new Error(`${this.label} ${this.version} doesn't answer its ${cmd} call, which sm-dev uses. This version may have changed it.`, { cause: err });
58
+ }
59
+ // A refusal, or the browser not answering: VM's own error says which.
60
+ throw new Error(`${this.label} ${this.version}'s ${cmd} call failed: ${why}`, { cause: err });
61
+ }
62
+ }
63
+ async scripts() {
64
+ const data = await this.call('GetData', {});
65
+ if (!Array.isArray(data?.scripts))
66
+ throw new Error(`${this.label} ${this.version}'s GetData call gave no script list, which sm-dev reads. This version may have changed it.`);
67
+ return data.scripts.filter((s) => !s.config.removed).map((s) => scriptOf(s));
68
+ }
69
+ async texts(ids) {
70
+ if (ids.length === 0)
71
+ return new Map();
72
+ const codes = await this.call('GetScriptCode', ids);
73
+ return new Map(ids.flatMap((id) => (typeof codes?.[id] === 'string' ? [[id, codes[id]]] : [])));
74
+ }
75
+ async install(code, options = {}) {
76
+ const result = await this.call('ParseScript', {
77
+ code,
78
+ ...(options.id !== undefined ? { id: options.id } : {}),
79
+ ...(options.url !== undefined ? { url: options.url } : {}),
80
+ // VM would check its install URL for updates.
81
+ ...(options.local ? { config: { shouldUpdate: 0 } } : {}),
82
+ // Present, even empty, so VM waits for what it fetches itself
83
+ // before answering, rather than leaving it in flight.
84
+ require: options.files?.requires ?? {},
85
+ cache: Object.fromEntries(Object.entries(options.files?.resources ?? {}).map(([url, f]) => [url, `${f.contentType},${f.base64}`])),
86
+ bumpDate: true,
87
+ });
88
+ const id = result?.where?.id;
89
+ if (typeof id !== 'number')
90
+ throw new Error(`${this.label} ${this.version}'s ParseScript call gave no script id. This version may have changed it.`);
91
+ return { id, isNew: result.isNew === true };
92
+ }
93
+ async setEnabled(id, enabled) {
94
+ await this.call('UpdateScriptInfo', { id, config: { enabled: enabled ? 1 : 0 } });
95
+ }
96
+ async uninstall(id) {
97
+ await this.call('MarkRemoved', { id, removed: true });
98
+ }
99
+ async remove(ids) {
100
+ if (ids.length === 0)
101
+ return;
102
+ // VM removes for good only what's in its recycle bin.
103
+ for (const id of ids)
104
+ await this.call('MarkRemoved', { id, removed: true });
105
+ await this.call('RemoveScripts', ids);
106
+ }
107
+ async applied() {
108
+ return (await this.options()).isApplied !== false;
109
+ }
110
+ async setApplied(on) {
111
+ await this.call('SetOptions', { isApplied: on });
112
+ }
113
+ async allowFilePages() {
114
+ const { blacklist } = await this.options();
115
+ if (typeof blacklist !== 'string')
116
+ return false;
117
+ // Its default holds only this rule, one rule a line.
118
+ const lines = blacklist.split('\n');
119
+ const kept = lines.filter((line) => line.trim() !== 'file://*/*');
120
+ if (kept.length === lines.length)
121
+ return false;
122
+ await this.call('SetOptions', { blacklist: kept.join('\n') });
123
+ return true;
124
+ }
125
+ scriptIdOf(url) {
126
+ // `chrome-extension://<id>/<name>.user.js#<script id>`, as a frame's
127
+ // URL or in a stack's text.
128
+ const id = new RegExp(`chrome-extension://${this.extensionId}/[^\\s#]*\\.user\\.js#(\\d+)(?!\\d)`).exec(url);
129
+ return id ? Number(id[1]) : undefined;
130
+ }
131
+ get scriptUrlPrefix() {
132
+ return `chrome-extension://${this.extensionId}/`;
133
+ }
134
+ close() {
135
+ return this.page.close();
136
+ }
137
+ async options() {
138
+ return await this.call('GetAllOptions') ?? {};
139
+ }
140
+ }
141
+ function scriptOf(s) {
142
+ const { meta } = s;
143
+ return {
144
+ id: s.props.id,
145
+ name: meta.name ?? `#${s.props.id}`,
146
+ ...(meta.namespace ? { namespace: meta.namespace } : {}),
147
+ ...(meta.version ? { version: meta.version } : {}),
148
+ ...(meta.description ? { description: meta.description } : {}),
149
+ ...(meta.author ? { author: meta.author } : {}),
150
+ enabled: Boolean(s.config.enabled),
151
+ match: meta.match ?? [],
152
+ include: meta.include ?? [],
153
+ exclude: meta.exclude ?? [],
154
+ excludeMatch: meta.excludeMatch ?? [],
155
+ ...(meta.runAt ? { runAt: meta.runAt } : {}),
156
+ grants: meta.grant ?? [],
157
+ requires: meta.require ?? [],
158
+ resources: Object.entries(meta.resources ?? {}).map(([name, url]) => ({ name, url })),
159
+ ...(s.custom.lastInstallURL ? { installUrl: s.custom.lastInstallURL } : {}),
160
+ ...(s.props.lastUpdated ?? s.props.lastModified ? { updatedAt: s.props.lastUpdated ?? s.props.lastModified } : {}),
161
+ };
162
+ }
@@ -0,0 +1,77 @@
1
+ import type { Page } from '@playwright/test';
2
+ import type { ConsoleContext, ControlledTab } from './console-commands.js';
3
+ import type { HarnessHost } from './host.js';
4
+ import type { ParsedArgs } from './command-args.js';
5
+ /** How long a wait lasts before it says what is still busy. */
6
+ export declare const SETTLE_TIMEOUT_MS = 5000;
7
+ export type SettleOutcome = {
8
+ settled: true;
9
+ }
10
+ /** Still busy at the deadline: what with, as the message lists it. */
11
+ | {
12
+ settled: false;
13
+ busy: string[];
14
+ }
15
+ /** A dialog opened, which stops the page until it is answered. */
16
+ | {
17
+ settled: false;
18
+ dialog: true;
19
+ }
20
+ /** The tab closed. */
21
+ | {
22
+ settled: false;
23
+ closed: true;
24
+ };
25
+ /** Waits for `tab` to settle, up to `timeoutMs`. */
26
+ export declare function settleTab(tab: ControlledTab, host: HarnessHost, timeoutMs?: number): Promise<SettleOutcome>;
27
+ /**
28
+ * After a load, an action or `start`: each tab settling, all at once.
29
+ * One that doesn't in time is said, without failing anything, since
30
+ * what came before worked. A dialog or a closed tab says so elsewhere,
31
+ * and a tab whose load already gave up (`stalled`) isn't waited on
32
+ * again.
33
+ */
34
+ export declare function settleTabs(host: HarnessHost, tabs: ControlledTab[], out: (line: string) => void, timeoutMs?: number): Promise<void>;
35
+ /** How long a load (`open`, `reload`, the tabs `start` opens) may take. */
36
+ export declare const LOAD_TIMEOUT_MS = 30000;
37
+ /**
38
+ * A command's `--timeout-seconds` in ms, for each wait it does in place
39
+ * of that wait's default: undefined when not given, null (said why)
40
+ * when not a number of seconds.
41
+ */
42
+ export declare function timeoutFlagMs(flags: Record<string, string | true>, out: (line: string) => void): number | undefined | null;
43
+ /** A navigation whose page didn't finish loading in time. */
44
+ export declare class PageNotLoaded extends Error {
45
+ }
46
+ /**
47
+ * Runs a navigation (`page.goto`, `page.reload`) until the new page
48
+ * has loaded. A page that stops its own load with `window.stop()`
49
+ * counts as loaded: its readyState goes to complete, but it never
50
+ * fires `load`, which a plain `goto` waits for until it times out.
51
+ * Rejects with the navigation's own error, or when the page doesn't
52
+ * load in time.
53
+ */
54
+ export declare function loadPage(page: Page, navigate: (opts: {
55
+ waitUntil: 'commit';
56
+ timeout: number;
57
+ }) => Promise<unknown>, timeoutMs?: number): Promise<void>;
58
+ /** The message when `tab` didn't settle in time, as every wait says it. */
59
+ export declare function notSettledMessage(tab: {
60
+ n: number;
61
+ }, timeoutMs: number, busy: string[]): string;
62
+ /**
63
+ * `wait`: until a tab settles, an element appears or goes, or an output
64
+ * line shows up; or a plain delay. `parsed`: its words, as its syntax
65
+ * reads them (command-args.ts). False when it gave up or was invalid,
66
+ * so a line of several commands stops there.
67
+ */
68
+ export declare function waitFor(ctx: ConsoleContext, parsed: ParsedArgs): Promise<boolean>;
69
+ /**
70
+ * A plain delay as typed, `100ms` or `5s` (`1.5s` too), in milliseconds;
71
+ * null for anything else.
72
+ */
73
+ export declare function parseDelay(text: string): number | null;
74
+ /** A duration as the messages say it: `5s`, `0.3s`. */
75
+ export declare function seconds(ms: number): string;
76
+ /** `work`'s result, or `timeout` once `ms` has passed. */
77
+ export declare function within<T>(work: Promise<T>, ms: number): Promise<T | 'timeout'>;