@wenathlan/saddle 1.8.17 → 2.0.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 (1005) hide show
  1. package/Dockerfile +1339 -0
  2. package/README.md +68 -22
  3. package/alternatives.ts +1218 -0
  4. package/biome.json +153 -0
  5. package/boards.json +1517 -0
  6. package/compute.ts +3144 -0
  7. package/cores.json +1801 -0
  8. package/dist/acquisition.d.ts +359 -0
  9. package/dist/acquisition.d.ts.map +1 -0
  10. package/dist/acquisition.js +629 -0
  11. package/dist/acquisition.js.map +1 -0
  12. package/dist/alternatives.d.ts +509 -0
  13. package/dist/alternatives.d.ts.map +1 -0
  14. package/dist/alternatives.js +951 -0
  15. package/dist/alternatives.js.map +1 -0
  16. package/dist/automation.d.ts +426 -0
  17. package/dist/automation.d.ts.map +1 -0
  18. package/dist/automation.js +561 -0
  19. package/dist/automation.js.map +1 -0
  20. package/dist/browser.d.ts +562 -0
  21. package/dist/browser.d.ts.map +1 -0
  22. package/dist/browser.js +1057 -0
  23. package/dist/browser.js.map +1 -0
  24. package/dist/capacitor.config.d.ts +13 -0
  25. package/dist/capacitor.config.d.ts.map +1 -0
  26. package/dist/capacitor.config.js +26 -0
  27. package/dist/capacitor.config.js.map +1 -0
  28. package/dist/cli.d.ts +17 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +111 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/communication.d.ts +192 -0
  33. package/dist/communication.d.ts.map +1 -0
  34. package/dist/communication.js +418 -0
  35. package/dist/communication.js.map +1 -0
  36. package/dist/compute.d.ts +1161 -0
  37. package/dist/compute.d.ts.map +1 -0
  38. package/dist/compute.js +2273 -0
  39. package/dist/compute.js.map +1 -0
  40. package/dist/distribution.d.ts +529 -0
  41. package/dist/distribution.d.ts.map +1 -0
  42. package/dist/distribution.js +811 -0
  43. package/dist/distribution.js.map +1 -0
  44. package/dist/execution.d.ts +530 -0
  45. package/dist/execution.d.ts.map +1 -0
  46. package/dist/execution.js +761 -0
  47. package/dist/execution.js.map +1 -0
  48. package/dist/format.d.ts +19 -0
  49. package/dist/format.d.ts.map +1 -0
  50. package/dist/format.js +60 -0
  51. package/dist/format.js.map +1 -0
  52. package/dist/foundation.d.ts +176 -0
  53. package/dist/foundation.d.ts.map +1 -0
  54. package/dist/foundation.js +309 -0
  55. package/dist/foundation.js.map +1 -0
  56. package/dist/index.d.ts +733 -122
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1018 -122
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration.d.ts +236 -0
  61. package/dist/integration.d.ts.map +1 -0
  62. package/dist/integration.js +236 -0
  63. package/dist/integration.js.map +1 -0
  64. package/dist/intelligence.d.ts +94 -0
  65. package/dist/intelligence.d.ts.map +1 -0
  66. package/dist/intelligence.js +145 -0
  67. package/dist/intelligence.js.map +1 -0
  68. package/dist/isolation.d.ts +129 -0
  69. package/dist/isolation.d.ts.map +1 -0
  70. package/dist/isolation.js +96 -0
  71. package/dist/isolation.js.map +1 -0
  72. package/dist/media.d.ts +344 -0
  73. package/dist/media.d.ts.map +1 -0
  74. package/dist/media.js +986 -0
  75. package/dist/media.js.map +1 -0
  76. package/dist/modes.d.ts +359 -0
  77. package/dist/modes.d.ts.map +1 -0
  78. package/dist/modes.js +134 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/{library/public.d.ts → operations.d.ts} +15 -1
  81. package/dist/operations.d.ts.map +1 -0
  82. package/dist/{library/public.js → operations.js} +18 -7
  83. package/dist/operations.js.map +1 -0
  84. package/dist/orchestrator.d.ts +1339 -0
  85. package/dist/orchestrator.d.ts.map +1 -0
  86. package/dist/orchestrator.js +4308 -0
  87. package/dist/orchestrator.js.map +1 -0
  88. package/dist/performance.d.ts +416 -0
  89. package/dist/performance.d.ts.map +1 -0
  90. package/dist/performance.js +827 -0
  91. package/dist/performance.js.map +1 -0
  92. package/dist/quantum.d.ts +810 -0
  93. package/dist/quantum.d.ts.map +1 -0
  94. package/dist/quantum.js +2073 -0
  95. package/dist/quantum.js.map +1 -0
  96. package/dist/render.d.ts +381 -0
  97. package/dist/render.d.ts.map +1 -0
  98. package/dist/render.js +1073 -0
  99. package/dist/render.js.map +1 -0
  100. package/dist/scheduler.d.ts +596 -0
  101. package/dist/scheduler.d.ts.map +1 -0
  102. package/dist/scheduler.js +1259 -0
  103. package/dist/scheduler.js.map +1 -0
  104. package/dist/security.d.ts +501 -0
  105. package/dist/security.d.ts.map +1 -0
  106. package/dist/security.js +1170 -0
  107. package/dist/security.js.map +1 -0
  108. package/dist/server.d.ts +21 -0
  109. package/dist/server.d.ts.map +1 -0
  110. package/dist/{server/node.js → server.js} +16 -2
  111. package/dist/server.js.map +1 -0
  112. package/dist/tiers.d.ts +1002 -0
  113. package/dist/tiers.d.ts.map +1 -0
  114. package/dist/tiers.js +2165 -0
  115. package/dist/tiers.js.map +1 -0
  116. package/dist/virtual.d.ts +641 -0
  117. package/dist/virtual.d.ts.map +1 -0
  118. package/dist/virtual.js +1285 -0
  119. package/dist/virtual.js.map +1 -0
  120. package/dist/virtualcpu.d.ts +316 -0
  121. package/dist/virtualcpu.d.ts.map +1 -0
  122. package/dist/virtualcpu.js +1180 -0
  123. package/dist/virtualcpu.js.map +1 -0
  124. package/dist/virtualgpu.d.ts +345 -0
  125. package/dist/virtualgpu.d.ts.map +1 -0
  126. package/dist/virtualgpu.js +1000 -0
  127. package/dist/virtualgpu.js.map +1 -0
  128. package/dist/virtualization.d.ts +607 -0
  129. package/dist/virtualization.d.ts.map +1 -0
  130. package/dist/virtualization.js +1187 -0
  131. package/dist/virtualization.js.map +1 -0
  132. package/dist/virtualmemory.d.ts +818 -0
  133. package/dist/virtualmemory.d.ts.map +1 -0
  134. package/dist/virtualmemory.js +1796 -0
  135. package/dist/virtualmemory.js.map +1 -0
  136. package/dist/webscrape.d.ts +720 -0
  137. package/dist/webscrape.d.ts.map +1 -0
  138. package/dist/webscrape.js +2697 -0
  139. package/dist/webscrape.js.map +1 -0
  140. package/docker.config +769 -0
  141. package/docs/CONVERSA.txt +1523 -0
  142. package/docs/alternatives.md +499 -0
  143. package/docs/architecture-1.8.19.md +76 -0
  144. package/docs/architecture-1.8.19.mmd +33 -0
  145. package/docs/architecture-1.8.19.png +0 -0
  146. package/docs/architecture.md +355 -0
  147. package/docs/artifactavailability.md +6 -0
  148. package/docs/brancharchive-2026-08-18.md +18 -0
  149. package/docs/browser.md +7 -0
  150. package/docs/consolidation.md +70 -0
  151. package/docs/e2ugh-engine.md +528 -0
  152. package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
  153. package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
  154. package/docs/hardware.md +342 -0
  155. package/docs/optimization.md +126 -0
  156. package/docs/performance.md +499 -0
  157. package/docs/planning.1.8.18.md +94 -0
  158. package/docs/planning.1.8.19.md +49 -0
  159. package/docs/releasenotes-1.8.17.md +6 -0
  160. package/docs/releasenotes-1.8.18.md +32 -0
  161. package/docs/releasenotes-1.8.19.md +35 -0
  162. package/docs/research-1.8.18-isolation.md +43 -0
  163. package/docs/research-1.8.19-virtual-browser.md +27 -0
  164. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  165. package/docs/security.md +454 -0
  166. package/docs/todo-1.8.16.md +56 -1
  167. package/docs/todo-1.8.18.md +164 -0
  168. package/docs/todo-1.8.19.md +241 -0
  169. package/docs/viability.md +777 -0
  170. package/docs/virtualization.md +335 -0
  171. package/docs/web-duplicatecleanup.md +9 -0
  172. package/docs/web-ideas.md +106 -0
  173. package/docs/workflowimprovements-2026-08-19.md +70 -0
  174. package/gpumonitor.cpp +1543 -0
  175. package/gpus.json +2408 -0
  176. package/index.ts +1478 -0
  177. package/media.ts +1337 -0
  178. package/mttg.config +1549 -0
  179. package/orchestrator.ts +5462 -0
  180. package/package.json +304 -55
  181. package/passage.config +1331 -0
  182. package/performance.ts +1049 -0
  183. package/processors.json +2217 -0
  184. package/qemu.config +1062 -0
  185. package/qemubridge.py +1340 -0
  186. package/quantum.ts +2393 -0
  187. package/render.ts +1325 -0
  188. package/scheduler.ts +1600 -0
  189. package/security.ts +1449 -0
  190. package/tiers.ts +2871 -0
  191. package/tsconfig.json +29 -0
  192. package/virtualcpu.ts +1273 -0
  193. package/virtualgpu.ts +1181 -0
  194. package/virtualhardware.c +1011 -0
  195. package/virtualhardware.json +739 -0
  196. package/virtualization.ts +1628 -0
  197. package/virtualizationcore.cpp +4635 -0
  198. package/virtualmemory.ts +2303 -0
  199. package/vm.config.json +1910 -0
  200. package/{extension → web/extension}/manifest.json +1 -1
  201. package/web/readme.md +382 -0
  202. package/web/tsconfig.json +25 -0
  203. package/dist/adapters/forge.d.ts +0 -17
  204. package/dist/adapters/forge.d.ts.map +0 -1
  205. package/dist/adapters/forge.js +0 -19
  206. package/dist/adapters/forge.js.map +0 -1
  207. package/dist/adapters/forgejo.d.ts +0 -49
  208. package/dist/adapters/forgejo.d.ts.map +0 -1
  209. package/dist/adapters/forgejo.js +0 -8
  210. package/dist/adapters/forgejo.js.map +0 -1
  211. package/dist/adapters/github.d.ts +0 -12
  212. package/dist/adapters/github.d.ts.map +0 -1
  213. package/dist/adapters/github.js +0 -20
  214. package/dist/adapters/github.js.map +0 -1
  215. package/dist/adapters/gitlab.d.ts +0 -17
  216. package/dist/adapters/gitlab.d.ts.map +0 -1
  217. package/dist/adapters/gitlab.js +0 -10
  218. package/dist/adapters/gitlab.js.map +0 -1
  219. package/dist/adapters/huggingface.d.ts +0 -17
  220. package/dist/adapters/huggingface.d.ts.map +0 -1
  221. package/dist/adapters/huggingface.js +0 -6
  222. package/dist/adapters/huggingface.js.map +0 -1
  223. package/dist/adapters/socket.d.ts +0 -11
  224. package/dist/adapters/socket.d.ts.map +0 -1
  225. package/dist/adapters/socket.js +0 -17
  226. package/dist/adapters/socket.js.map +0 -1
  227. package/dist/adapters/transport.d.ts +0 -7
  228. package/dist/adapters/transport.d.ts.map +0 -1
  229. package/dist/adapters/transport.js +0 -36
  230. package/dist/adapters/transport.js.map +0 -1
  231. package/dist/ai/chunk.d.ts +0 -2
  232. package/dist/ai/chunk.d.ts.map +0 -1
  233. package/dist/ai/chunk.js +0 -36
  234. package/dist/ai/chunk.js.map +0 -1
  235. package/dist/ai/llmstxt.d.ts +0 -6
  236. package/dist/ai/llmstxt.d.ts.map +0 -1
  237. package/dist/ai/llmstxt.js +0 -12
  238. package/dist/ai/llmstxt.js.map +0 -1
  239. package/dist/ai/provenance.d.ts +0 -22
  240. package/dist/ai/provenance.d.ts.map +0 -1
  241. package/dist/ai/provenance.js +0 -25
  242. package/dist/ai/provenance.js.map +0 -1
  243. package/dist/ai/rag.d.ts +0 -26
  244. package/dist/ai/rag.d.ts.map +0 -1
  245. package/dist/ai/rag.js +0 -22
  246. package/dist/ai/rag.js.map +0 -1
  247. package/dist/ai/tokens.d.ts +0 -15
  248. package/dist/ai/tokens.d.ts.map +0 -1
  249. package/dist/ai/tokens.js +0 -9
  250. package/dist/ai/tokens.js.map +0 -1
  251. package/dist/api/auth.d.ts +0 -16
  252. package/dist/api/auth.d.ts.map +0 -1
  253. package/dist/api/auth.js +0 -19
  254. package/dist/api/auth.js.map +0 -1
  255. package/dist/api/contracts.d.ts +0 -28
  256. package/dist/api/contracts.d.ts.map +0 -1
  257. package/dist/api/contracts.js +0 -14
  258. package/dist/api/contracts.js.map +0 -1
  259. package/dist/api/control.d.ts +0 -10
  260. package/dist/api/control.d.ts.map +0 -1
  261. package/dist/api/control.js +0 -35
  262. package/dist/api/control.js.map +0 -1
  263. package/dist/api/http.d.ts +0 -7
  264. package/dist/api/http.d.ts.map +0 -1
  265. package/dist/api/http.js +0 -12
  266. package/dist/api/http.js.map +0 -1
  267. package/dist/api/rate.d.ts +0 -28
  268. package/dist/api/rate.d.ts.map +0 -1
  269. package/dist/api/rate.js +0 -36
  270. package/dist/api/rate.js.map +0 -1
  271. package/dist/api/security.d.ts +0 -12
  272. package/dist/api/security.d.ts.map +0 -1
  273. package/dist/api/security.js +0 -56
  274. package/dist/api/security.js.map +0 -1
  275. package/dist/api/service.d.ts +0 -5
  276. package/dist/api/service.d.ts.map +0 -1
  277. package/dist/api/service.js +0 -70
  278. package/dist/api/service.js.map +0 -1
  279. package/dist/apps/registry.d.ts +0 -33
  280. package/dist/apps/registry.d.ts.map +0 -1
  281. package/dist/apps/registry.js +0 -24
  282. package/dist/apps/registry.js.map +0 -1
  283. package/dist/binary/archive.d.ts +0 -27
  284. package/dist/binary/archive.d.ts.map +0 -1
  285. package/dist/binary/archive.js +0 -46
  286. package/dist/binary/archive.js.map +0 -1
  287. package/dist/binary/build.d.ts +0 -29
  288. package/dist/binary/build.d.ts.map +0 -1
  289. package/dist/binary/build.js +0 -17
  290. package/dist/binary/build.js.map +0 -1
  291. package/dist/binary/transform.d.ts +0 -70
  292. package/dist/binary/transform.d.ts.map +0 -1
  293. package/dist/binary/transform.js +0 -105
  294. package/dist/binary/transform.js.map +0 -1
  295. package/dist/bot/adapter.d.ts +0 -5
  296. package/dist/bot/adapter.d.ts.map +0 -1
  297. package/dist/bot/adapter.js +0 -11
  298. package/dist/bot/adapter.js.map +0 -1
  299. package/dist/bot/bot.d.ts +0 -28
  300. package/dist/bot/bot.d.ts.map +0 -1
  301. package/dist/bot/bot.js +0 -52
  302. package/dist/bot/bot.js.map +0 -1
  303. package/dist/bot/commands.d.ts +0 -8
  304. package/dist/bot/commands.d.ts.map +0 -1
  305. package/dist/bot/commands.js +0 -19
  306. package/dist/bot/commands.js.map +0 -1
  307. package/dist/bot/permissions.d.ts +0 -13
  308. package/dist/bot/permissions.d.ts.map +0 -1
  309. package/dist/bot/permissions.js +0 -16
  310. package/dist/bot/permissions.js.map +0 -1
  311. package/dist/browser/actions.d.ts +0 -33
  312. package/dist/browser/actions.d.ts.map +0 -1
  313. package/dist/browser/actions.js +0 -44
  314. package/dist/browser/actions.js.map +0 -1
  315. package/dist/browser/agent.d.ts +0 -21
  316. package/dist/browser/agent.d.ts.map +0 -1
  317. package/dist/browser/agent.js +0 -13
  318. package/dist/browser/agent.js.map +0 -1
  319. package/dist/browser/context.d.ts +0 -43
  320. package/dist/browser/context.d.ts.map +0 -1
  321. package/dist/browser/context.js +0 -54
  322. package/dist/browser/context.js.map +0 -1
  323. package/dist/browser/fingerprint.d.ts +0 -4
  324. package/dist/browser/fingerprint.d.ts.map +0 -1
  325. package/dist/browser/fingerprint.js +0 -12
  326. package/dist/browser/fingerprint.js.map +0 -1
  327. package/dist/browser/index.d.ts +0 -11
  328. package/dist/browser/index.d.ts.map +0 -1
  329. package/dist/browser/index.js +0 -11
  330. package/dist/browser/index.js.map +0 -1
  331. package/dist/browser/playwright.d.ts +0 -11
  332. package/dist/browser/playwright.d.ts.map +0 -1
  333. package/dist/browser/playwright.js +0 -24
  334. package/dist/browser/playwright.js.map +0 -1
  335. package/dist/browser/recorder.d.ts +0 -21
  336. package/dist/browser/recorder.d.ts.map +0 -1
  337. package/dist/browser/recorder.js +0 -58
  338. package/dist/browser/recorder.js.map +0 -1
  339. package/dist/browser/session.d.ts +0 -14
  340. package/dist/browser/session.d.ts.map +0 -1
  341. package/dist/browser/session.js +0 -21
  342. package/dist/browser/session.js.map +0 -1
  343. package/dist/browser/snapshot.d.ts +0 -69
  344. package/dist/browser/snapshot.d.ts.map +0 -1
  345. package/dist/browser/snapshot.js +0 -133
  346. package/dist/browser/snapshot.js.map +0 -1
  347. package/dist/captcha/contract.d.ts +0 -35
  348. package/dist/captcha/contract.d.ts.map +0 -1
  349. package/dist/captcha/contract.js +0 -17
  350. package/dist/captcha/contract.js.map +0 -1
  351. package/dist/captcha/evidence.d.ts +0 -10
  352. package/dist/captcha/evidence.d.ts.map +0 -1
  353. package/dist/captcha/evidence.js +0 -9
  354. package/dist/captcha/evidence.js.map +0 -1
  355. package/dist/captcha/guard.d.ts +0 -23
  356. package/dist/captcha/guard.d.ts.map +0 -1
  357. package/dist/captcha/guard.js +0 -12
  358. package/dist/captcha/guard.js.map +0 -1
  359. package/dist/cli/main.d.ts +0 -4
  360. package/dist/cli/main.d.ts.map +0 -1
  361. package/dist/cli/main.js +0 -46
  362. package/dist/cli/main.js.map +0 -1
  363. package/dist/core/errors.d.ts +0 -84
  364. package/dist/core/errors.d.ts.map +0 -1
  365. package/dist/core/errors.js +0 -54
  366. package/dist/core/errors.js.map +0 -1
  367. package/dist/core/events.d.ts +0 -9
  368. package/dist/core/events.d.ts.map +0 -1
  369. package/dist/core/events.js +0 -21
  370. package/dist/core/events.js.map +0 -1
  371. package/dist/core/hash.d.ts +0 -10
  372. package/dist/core/hash.d.ts.map +0 -1
  373. package/dist/core/hash.js +0 -82
  374. package/dist/core/hash.js.map +0 -1
  375. package/dist/core/ids.d.ts +0 -10
  376. package/dist/core/ids.d.ts.map +0 -1
  377. package/dist/core/ids.js +0 -15
  378. package/dist/core/ids.js.map +0 -1
  379. package/dist/delivery/manifest.d.ts +0 -35
  380. package/dist/delivery/manifest.d.ts.map +0 -1
  381. package/dist/delivery/manifest.js +0 -68
  382. package/dist/delivery/manifest.js.map +0 -1
  383. package/dist/deploy/index.d.ts +0 -6
  384. package/dist/deploy/index.d.ts.map +0 -1
  385. package/dist/deploy/index.js +0 -6
  386. package/dist/deploy/index.js.map +0 -1
  387. package/dist/dispatch/resumable.d.ts +0 -102
  388. package/dist/dispatch/resumable.d.ts.map +0 -1
  389. package/dist/dispatch/resumable.js +0 -64
  390. package/dist/dispatch/resumable.js.map +0 -1
  391. package/dist/dispatch/workflow.d.ts +0 -6
  392. package/dist/dispatch/workflow.d.ts.map +0 -1
  393. package/dist/dispatch/workflow.js +0 -37
  394. package/dist/dispatch/workflow.js.map +0 -1
  395. package/dist/domain/artifacts.d.ts +0 -12
  396. package/dist/domain/artifacts.d.ts.map +0 -1
  397. package/dist/domain/artifacts.js +0 -14
  398. package/dist/domain/artifacts.js.map +0 -1
  399. package/dist/domain/jobs.d.ts +0 -12
  400. package/dist/domain/jobs.d.ts.map +0 -1
  401. package/dist/domain/jobs.js +0 -20
  402. package/dist/domain/jobs.js.map +0 -1
  403. package/dist/domain/providers.d.ts +0 -10
  404. package/dist/domain/providers.d.ts.map +0 -1
  405. package/dist/domain/providers.js +0 -8
  406. package/dist/domain/providers.js.map +0 -1
  407. package/dist/domain/runtime.d.ts +0 -14
  408. package/dist/domain/runtime.d.ts.map +0 -1
  409. package/dist/domain/runtime.js +0 -10
  410. package/dist/domain/runtime.js.map +0 -1
  411. package/dist/domain/sessions.d.ts +0 -12
  412. package/dist/domain/sessions.d.ts.map +0 -1
  413. package/dist/domain/sessions.js +0 -57
  414. package/dist/domain/sessions.js.map +0 -1
  415. package/dist/examples/localjob.d.ts +0 -2
  416. package/dist/examples/localjob.d.ts.map +0 -1
  417. package/dist/examples/localjob.js.map +0 -1
  418. package/dist/examples/publicapi.d.ts +0 -2
  419. package/dist/examples/publicapi.d.ts.map +0 -1
  420. package/dist/examples/publicapi.js.map +0 -1
  421. package/dist/extension/build.d.ts +0 -9
  422. package/dist/extension/build.d.ts.map +0 -1
  423. package/dist/extension/build.js +0 -85
  424. package/dist/extension/build.js.map +0 -1
  425. package/dist/extension/content.d.ts +0 -6
  426. package/dist/extension/content.d.ts.map +0 -1
  427. package/dist/extension/content.js +0 -135
  428. package/dist/extension/content.js.map +0 -1
  429. package/dist/extension/index.d.ts +0 -7
  430. package/dist/extension/index.d.ts.map +0 -1
  431. package/dist/extension/index.js +0 -7
  432. package/dist/extension/index.js.map +0 -1
  433. package/dist/extension/pagebridge.d.ts +0 -6
  434. package/dist/extension/pagebridge.d.ts.map +0 -1
  435. package/dist/extension/pagebridge.js +0 -42
  436. package/dist/extension/pagebridge.js.map +0 -1
  437. package/dist/extension/permissions.d.ts +0 -26
  438. package/dist/extension/permissions.d.ts.map +0 -1
  439. package/dist/extension/permissions.js +0 -28
  440. package/dist/extension/permissions.js.map +0 -1
  441. package/dist/extension/popup.d.ts +0 -5
  442. package/dist/extension/popup.d.ts.map +0 -1
  443. package/dist/extension/popup.js +0 -26
  444. package/dist/extension/popup.js.map +0 -1
  445. package/dist/extension/protocol.d.ts +0 -58
  446. package/dist/extension/protocol.d.ts.map +0 -1
  447. package/dist/extension/protocol.js +0 -101
  448. package/dist/extension/protocol.js.map +0 -1
  449. package/dist/extension/serviceworker.d.ts +0 -25
  450. package/dist/extension/serviceworker.d.ts.map +0 -1
  451. package/dist/extension/serviceworker.js +0 -102
  452. package/dist/extension/serviceworker.js.map +0 -1
  453. package/dist/extension/worker.d.ts +0 -28
  454. package/dist/extension/worker.d.ts.map +0 -1
  455. package/dist/extension/worker.js +0 -22
  456. package/dist/extension/worker.js.map +0 -1
  457. package/dist/format/check.d.ts +0 -8
  458. package/dist/format/check.d.ts.map +0 -1
  459. package/dist/format/check.js +0 -38
  460. package/dist/format/check.js.map +0 -1
  461. package/dist/library/public.d.ts.map +0 -1
  462. package/dist/library/public.js.map +0 -1
  463. package/dist/mcp/browser.d.ts +0 -9
  464. package/dist/mcp/browser.d.ts.map +0 -1
  465. package/dist/mcp/browser.js +0 -13
  466. package/dist/mcp/browser.js.map +0 -1
  467. package/dist/mcp/server.d.ts +0 -35
  468. package/dist/mcp/server.d.ts.map +0 -1
  469. package/dist/mcp/server.js +0 -40
  470. package/dist/mcp/server.js.map +0 -1
  471. package/dist/mcp/transport.d.ts +0 -7
  472. package/dist/mcp/transport.d.ts.map +0 -1
  473. package/dist/mcp/transport.js +0 -17
  474. package/dist/mcp/transport.js.map +0 -1
  475. package/dist/memory/bridge.d.ts +0 -14
  476. package/dist/memory/bridge.d.ts.map +0 -1
  477. package/dist/memory/bridge.js +0 -16
  478. package/dist/memory/bridge.js.map +0 -1
  479. package/dist/memory/engine.d.ts +0 -38
  480. package/dist/memory/engine.d.ts.map +0 -1
  481. package/dist/memory/engine.js +0 -109
  482. package/dist/memory/engine.js.map +0 -1
  483. package/dist/memory/modes.d.ts +0 -43
  484. package/dist/memory/modes.d.ts.map +0 -1
  485. package/dist/memory/modes.js +0 -66
  486. package/dist/memory/modes.js.map +0 -1
  487. package/dist/memory/objects.d.ts +0 -21
  488. package/dist/memory/objects.d.ts.map +0 -1
  489. package/dist/memory/objects.js +0 -20
  490. package/dist/memory/objects.js.map +0 -1
  491. package/dist/memory/planner.d.ts +0 -66
  492. package/dist/memory/planner.d.ts.map +0 -1
  493. package/dist/memory/planner.js +0 -108
  494. package/dist/memory/planner.js.map +0 -1
  495. package/dist/memory/targets.d.ts +0 -78
  496. package/dist/memory/targets.d.ts.map +0 -1
  497. package/dist/memory/targets.js +0 -29
  498. package/dist/memory/targets.js.map +0 -1
  499. package/dist/memory/transforms.d.ts +0 -19
  500. package/dist/memory/transforms.d.ts.map +0 -1
  501. package/dist/memory/transforms.js +0 -14
  502. package/dist/memory/transforms.js.map +0 -1
  503. package/dist/modes/matrix.d.ts +0 -23
  504. package/dist/modes/matrix.d.ts.map +0 -1
  505. package/dist/modes/matrix.js +0 -18
  506. package/dist/modes/matrix.js.map +0 -1
  507. package/dist/modes/modes.d.ts +0 -33
  508. package/dist/modes/modes.d.ts.map +0 -1
  509. package/dist/modes/modes.js +0 -15
  510. package/dist/modes/modes.js.map +0 -1
  511. package/dist/modes/resolve.d.ts +0 -96
  512. package/dist/modes/resolve.d.ts.map +0 -1
  513. package/dist/modes/resolve.js +0 -48
  514. package/dist/modes/resolve.js.map +0 -1
  515. package/dist/observability/metrics.d.ts +0 -14
  516. package/dist/observability/metrics.d.ts.map +0 -1
  517. package/dist/observability/metrics.js +0 -18
  518. package/dist/observability/metrics.js.map +0 -1
  519. package/dist/packager/manifest.d.ts +0 -66
  520. package/dist/packager/manifest.d.ts.map +0 -1
  521. package/dist/packager/manifest.js +0 -94
  522. package/dist/packager/manifest.js.map +0 -1
  523. package/dist/packager/publish.d.ts +0 -51
  524. package/dist/packager/publish.d.ts.map +0 -1
  525. package/dist/packager/publish.js +0 -18
  526. package/dist/packager/publish.js.map +0 -1
  527. package/dist/packager/targetcli.d.ts +0 -7
  528. package/dist/packager/targetcli.d.ts.map +0 -1
  529. package/dist/packager/targetcli.js +0 -22
  530. package/dist/packager/targetcli.js.map +0 -1
  531. package/dist/persistence/adapter.d.ts +0 -5
  532. package/dist/persistence/adapter.d.ts.map +0 -1
  533. package/dist/persistence/adapter.js +0 -11
  534. package/dist/persistence/adapter.js.map +0 -1
  535. package/dist/persistence/drizzle.d.ts +0 -2
  536. package/dist/persistence/drizzle.d.ts.map +0 -1
  537. package/dist/persistence/drizzle.js +0 -12
  538. package/dist/persistence/drizzle.js.map +0 -1
  539. package/dist/persistence/memory.d.ts +0 -2
  540. package/dist/persistence/memory.d.ts.map +0 -1
  541. package/dist/persistence/memory.js +0 -27
  542. package/dist/persistence/memory.js.map +0 -1
  543. package/dist/persistence/migrations.d.ts +0 -19
  544. package/dist/persistence/migrations.d.ts.map +0 -1
  545. package/dist/persistence/migrations.js +0 -13
  546. package/dist/persistence/migrations.js.map +0 -1
  547. package/dist/persistence/prisma.d.ts +0 -2
  548. package/dist/persistence/prisma.d.ts.map +0 -1
  549. package/dist/persistence/prisma.js +0 -25
  550. package/dist/persistence/prisma.js.map +0 -1
  551. package/dist/persistence/schema.d.ts +0 -63
  552. package/dist/persistence/schema.d.ts.map +0 -1
  553. package/dist/persistence/schema.js +0 -28
  554. package/dist/persistence/schema.js.map +0 -1
  555. package/dist/persistence/sql.d.ts +0 -3
  556. package/dist/persistence/sql.d.ts.map +0 -1
  557. package/dist/persistence/sql.js +0 -37
  558. package/dist/persistence/sql.js.map +0 -1
  559. package/dist/protocol/blocks.d.ts +0 -10
  560. package/dist/protocol/blocks.d.ts.map +0 -1
  561. package/dist/protocol/blocks.js +0 -26
  562. package/dist/protocol/blocks.js.map +0 -1
  563. package/dist/protocol/json.d.ts +0 -6
  564. package/dist/protocol/json.d.ts.map +0 -1
  565. package/dist/protocol/json.js +0 -6
  566. package/dist/protocol/json.js.map +0 -1
  567. package/dist/protocol/ndjson.d.ts +0 -3
  568. package/dist/protocol/ndjson.d.ts.map +0 -1
  569. package/dist/protocol/ndjson.js +0 -20
  570. package/dist/protocol/ndjson.js.map +0 -1
  571. package/dist/protocol/sse.d.ts +0 -7
  572. package/dist/protocol/sse.d.ts.map +0 -1
  573. package/dist/protocol/sse.js +0 -25
  574. package/dist/protocol/sse.js.map +0 -1
  575. package/dist/proxy/pool.d.ts +0 -9
  576. package/dist/proxy/pool.d.ts.map +0 -1
  577. package/dist/proxy/pool.js +0 -27
  578. package/dist/proxy/pool.js.map +0 -1
  579. package/dist/queue/idempotency.d.ts +0 -10
  580. package/dist/queue/idempotency.d.ts.map +0 -1
  581. package/dist/queue/idempotency.js +0 -13
  582. package/dist/queue/idempotency.js.map +0 -1
  583. package/dist/queue/persistent.d.ts +0 -14
  584. package/dist/queue/persistent.d.ts.map +0 -1
  585. package/dist/queue/persistent.js +0 -66
  586. package/dist/queue/persistent.js.map +0 -1
  587. package/dist/queue/queue.d.ts +0 -7
  588. package/dist/queue/queue.d.ts.map +0 -1
  589. package/dist/queue/queue.js +0 -55
  590. package/dist/queue/queue.js.map +0 -1
  591. package/dist/queue/saga.d.ts +0 -5
  592. package/dist/queue/saga.d.ts.map +0 -1
  593. package/dist/queue/saga.js +0 -20
  594. package/dist/queue/saga.js.map +0 -1
  595. package/dist/release/assets.d.ts +0 -144
  596. package/dist/release/assets.d.ts.map +0 -1
  597. package/dist/release/assets.js +0 -157
  598. package/dist/release/assets.js.map +0 -1
  599. package/dist/release/evidence.d.ts +0 -92
  600. package/dist/release/evidence.d.ts.map +0 -1
  601. package/dist/release/evidence.js +0 -148
  602. package/dist/release/evidence.js.map +0 -1
  603. package/dist/release/verify.d.ts +0 -12
  604. package/dist/release/verify.d.ts.map +0 -1
  605. package/dist/release/verify.js +0 -112
  606. package/dist/release/verify.js.map +0 -1
  607. package/dist/runners/chain.d.ts +0 -125
  608. package/dist/runners/chain.d.ts.map +0 -1
  609. package/dist/runners/chain.js +0 -95
  610. package/dist/runners/chain.js.map +0 -1
  611. package/dist/runners/health.d.ts +0 -36
  612. package/dist/runners/health.d.ts.map +0 -1
  613. package/dist/runners/health.js +0 -26
  614. package/dist/runners/health.js.map +0 -1
  615. package/dist/runners/heartbeat.d.ts +0 -23
  616. package/dist/runners/heartbeat.d.ts.map +0 -1
  617. package/dist/runners/heartbeat.js +0 -29
  618. package/dist/runners/heartbeat.js.map +0 -1
  619. package/dist/runners/inprocess.d.ts +0 -17
  620. package/dist/runners/inprocess.d.ts.map +0 -1
  621. package/dist/runners/inprocess.js +0 -20
  622. package/dist/runners/inprocess.js.map +0 -1
  623. package/dist/runners/scheduler.d.ts +0 -5
  624. package/dist/runners/scheduler.d.ts.map +0 -1
  625. package/dist/runners/scheduler.js +0 -19
  626. package/dist/runners/scheduler.js.map +0 -1
  627. package/dist/runtime/abort.d.ts +0 -8
  628. package/dist/runtime/abort.d.ts.map +0 -1
  629. package/dist/runtime/abort.js +0 -13
  630. package/dist/runtime/abort.js.map +0 -1
  631. package/dist/runtime/compatibility.d.ts +0 -37
  632. package/dist/runtime/compatibility.d.ts.map +0 -1
  633. package/dist/runtime/compatibility.js +0 -10
  634. package/dist/runtime/compatibility.js.map +0 -1
  635. package/dist/runtime/detect.d.ts +0 -13
  636. package/dist/runtime/detect.d.ts.map +0 -1
  637. package/dist/runtime/detect.js +0 -18
  638. package/dist/runtime/detect.js.map +0 -1
  639. package/dist/runtime/engine.d.ts +0 -20
  640. package/dist/runtime/engine.d.ts.map +0 -1
  641. package/dist/runtime/engine.js +0 -61
  642. package/dist/runtime/engine.js.map +0 -1
  643. package/dist/runtime/retry.d.ts +0 -19
  644. package/dist/runtime/retry.d.ts.map +0 -1
  645. package/dist/runtime/retry.js +0 -54
  646. package/dist/runtime/retry.js.map +0 -1
  647. package/dist/runtime/worker.d.ts +0 -10
  648. package/dist/runtime/worker.d.ts.map +0 -1
  649. package/dist/runtime/worker.js +0 -25
  650. package/dist/runtime/worker.js.map +0 -1
  651. package/dist/scrape/cache.d.ts +0 -45
  652. package/dist/scrape/cache.d.ts.map +0 -1
  653. package/dist/scrape/cache.js +0 -45
  654. package/dist/scrape/cache.js.map +0 -1
  655. package/dist/scrape/crawl.d.ts +0 -47
  656. package/dist/scrape/crawl.d.ts.map +0 -1
  657. package/dist/scrape/crawl.js +0 -114
  658. package/dist/scrape/crawl.js.map +0 -1
  659. package/dist/scrape/extract.d.ts +0 -63
  660. package/dist/scrape/extract.d.ts.map +0 -1
  661. package/dist/scrape/extract.js +0 -47
  662. package/dist/scrape/extract.js.map +0 -1
  663. package/dist/scrape/normalize.d.ts +0 -52
  664. package/dist/scrape/normalize.d.ts.map +0 -1
  665. package/dist/scrape/normalize.js +0 -102
  666. package/dist/scrape/normalize.js.map +0 -1
  667. package/dist/scrape/robots.d.ts +0 -37
  668. package/dist/scrape/robots.d.ts.map +0 -1
  669. package/dist/scrape/robots.js +0 -71
  670. package/dist/scrape/robots.js.map +0 -1
  671. package/dist/scrape/schema.d.ts +0 -23
  672. package/dist/scrape/schema.d.ts.map +0 -1
  673. package/dist/scrape/schema.js +0 -92
  674. package/dist/scrape/schema.js.map +0 -1
  675. package/dist/scrape/scraper.d.ts +0 -6
  676. package/dist/scrape/scraper.d.ts.map +0 -1
  677. package/dist/scrape/scraper.js +0 -46
  678. package/dist/scrape/scraper.js.map +0 -1
  679. package/dist/scrape/semantic.d.ts +0 -25
  680. package/dist/scrape/semantic.d.ts.map +0 -1
  681. package/dist/scrape/semantic.js +0 -27
  682. package/dist/scrape/semantic.js.map +0 -1
  683. package/dist/server/node.d.ts +0 -7
  684. package/dist/server/node.d.ts.map +0 -1
  685. package/dist/server/node.js.map +0 -1
  686. package/dist/sessions/file.d.ts +0 -25
  687. package/dist/sessions/file.d.ts.map +0 -1
  688. package/dist/sessions/file.js +0 -13
  689. package/dist/sessions/file.js.map +0 -1
  690. package/dist/sessions/replay.d.ts +0 -9
  691. package/dist/sessions/replay.d.ts.map +0 -1
  692. package/dist/sessions/replay.js +0 -70
  693. package/dist/sessions/replay.js.map +0 -1
  694. package/dist/sessions/store.d.ts +0 -25
  695. package/dist/sessions/store.d.ts.map +0 -1
  696. package/dist/sessions/store.js +0 -13
  697. package/dist/sessions/store.js.map +0 -1
  698. package/dist/storage/adapter.d.ts +0 -5
  699. package/dist/storage/adapter.d.ts.map +0 -1
  700. package/dist/storage/adapter.js +0 -11
  701. package/dist/storage/adapter.js.map +0 -1
  702. package/dist/storage/cache.d.ts +0 -23
  703. package/dist/storage/cache.d.ts.map +0 -1
  704. package/dist/storage/cache.js +0 -79
  705. package/dist/storage/cache.js.map +0 -1
  706. package/dist/storage/checksum.d.ts +0 -3
  707. package/dist/storage/checksum.d.ts.map +0 -1
  708. package/dist/storage/checksum.js +0 -19
  709. package/dist/storage/checksum.js.map +0 -1
  710. package/dist/storage/chunked.d.ts +0 -21
  711. package/dist/storage/chunked.d.ts.map +0 -1
  712. package/dist/storage/chunked.js +0 -67
  713. package/dist/storage/chunked.js.map +0 -1
  714. package/dist/storage/content.d.ts +0 -24
  715. package/dist/storage/content.d.ts.map +0 -1
  716. package/dist/storage/content.js +0 -44
  717. package/dist/storage/content.js.map +0 -1
  718. package/dist/storage/filehosting.d.ts +0 -2
  719. package/dist/storage/filehosting.d.ts.map +0 -1
  720. package/dist/storage/filehosting.js +0 -24
  721. package/dist/storage/filehosting.js.map +0 -1
  722. package/dist/storage/githubcontents.d.ts +0 -2
  723. package/dist/storage/githubcontents.d.ts.map +0 -1
  724. package/dist/storage/githubcontents.js +0 -29
  725. package/dist/storage/githubcontents.js.map +0 -1
  726. package/dist/storage/index.d.ts +0 -12
  727. package/dist/storage/index.d.ts.map +0 -1
  728. package/dist/storage/index.js +0 -12
  729. package/dist/storage/index.js.map +0 -1
  730. package/dist/storage/local.d.ts +0 -2
  731. package/dist/storage/local.d.ts.map +0 -1
  732. package/dist/storage/local.js +0 -72
  733. package/dist/storage/local.js.map +0 -1
  734. package/dist/storage/memory.d.ts +0 -6
  735. package/dist/storage/memory.d.ts.map +0 -1
  736. package/dist/storage/memory.js +0 -36
  737. package/dist/storage/memory.js.map +0 -1
  738. package/dist/storage/pool.d.ts +0 -95
  739. package/dist/storage/pool.d.ts.map +0 -1
  740. package/dist/storage/pool.js +0 -202
  741. package/dist/storage/pool.js.map +0 -1
  742. package/dist/storage/s3compatible.d.ts +0 -3
  743. package/dist/storage/s3compatible.d.ts.map +0 -1
  744. package/dist/storage/s3compatible.js +0 -70
  745. package/dist/storage/s3compatible.js.map +0 -1
  746. package/dist/storage/sync.d.ts +0 -47
  747. package/dist/storage/sync.d.ts.map +0 -1
  748. package/dist/storage/sync.js +0 -75
  749. package/dist/storage/sync.js.map +0 -1
  750. package/dist/surfaces/adapters.d.ts +0 -97
  751. package/dist/surfaces/adapters.d.ts.map +0 -1
  752. package/dist/surfaces/adapters.js +0 -50
  753. package/dist/surfaces/adapters.js.map +0 -1
  754. package/dist/surfaces/controls.d.ts +0 -18
  755. package/dist/surfaces/controls.d.ts.map +0 -1
  756. package/dist/surfaces/controls.js +0 -45
  757. package/dist/surfaces/controls.js.map +0 -1
  758. package/dist/surfaces/manifest.d.ts +0 -68
  759. package/dist/surfaces/manifest.d.ts.map +0 -1
  760. package/dist/surfaces/manifest.js +0 -42
  761. package/dist/surfaces/manifest.js.map +0 -1
  762. package/dist/surfaces/n8n.d.ts +0 -25
  763. package/dist/surfaces/n8n.d.ts.map +0 -1
  764. package/dist/surfaces/n8n.js +0 -31
  765. package/dist/surfaces/n8n.js.map +0 -1
  766. package/dist/surfaces/operations.d.ts +0 -32
  767. package/dist/surfaces/operations.d.ts.map +0 -1
  768. package/dist/surfaces/operations.js +0 -53
  769. package/dist/surfaces/operations.js.map +0 -1
  770. package/dist/surfaces/requirements.d.ts +0 -29
  771. package/dist/surfaces/requirements.d.ts.map +0 -1
  772. package/dist/surfaces/requirements.js +0 -50
  773. package/dist/surfaces/requirements.js.map +0 -1
  774. package/dist/surfaces/targets.d.ts +0 -196
  775. package/dist/surfaces/targets.d.ts.map +0 -1
  776. package/dist/surfaces/targets.js +0 -27
  777. package/dist/surfaces/targets.js.map +0 -1
  778. package/dist/webhook/delivery.d.ts +0 -18
  779. package/dist/webhook/delivery.d.ts.map +0 -1
  780. package/dist/webhook/delivery.js +0 -36
  781. package/dist/webhook/delivery.js.map +0 -1
  782. package/dist/webhook/receiver.d.ts +0 -26
  783. package/dist/webhook/receiver.d.ts.map +0 -1
  784. package/dist/webhook/receiver.js +0 -24
  785. package/dist/webhook/receiver.js.map +0 -1
  786. package/dist/webhook/signature.d.ts +0 -3
  787. package/dist/webhook/signature.d.ts.map +0 -1
  788. package/dist/webhook/signature.js +0 -7
  789. package/dist/webhook/signature.js.map +0 -1
  790. package/dist/workflow/manifest.d.ts +0 -22
  791. package/dist/workflow/manifest.d.ts.map +0 -1
  792. package/dist/workflow/manifest.js +0 -21
  793. package/dist/workflow/manifest.js.map +0 -1
  794. package/dist/workflow/registry.d.ts +0 -7
  795. package/dist/workflow/registry.d.ts.map +0 -1
  796. package/dist/workflow/registry.js +0 -18
  797. package/dist/workflow/registry.js.map +0 -1
  798. package/dist/workflow/templates.d.ts +0 -6
  799. package/dist/workflow/templates.d.ts.map +0 -1
  800. package/dist/workflow/templates.js +0 -18
  801. package/dist/workflow/templates.js.map +0 -1
  802. package/dist/workflow/triggers.d.ts +0 -64
  803. package/dist/workflow/triggers.d.ts.map +0 -1
  804. package/dist/workflow/triggers.js +0 -99
  805. package/dist/workflow/triggers.js.map +0 -1
  806. package/docs/logs/.gitkeep +0 -0
  807. package/docs/plans/00.index.md +0 -50
  808. package/docs/plans/01.architecture.md +0 -86
  809. package/docs/plans/02.research.computer.use.md +0 -58
  810. package/docs/plans/03.research.captcha.bypass.md +0 -68
  811. package/docs/plans/04.research.sandbox.ai.md +0 -52
  812. package/docs/plans/05.capture.platform.md +0 -57
  813. package/docs/plans/06.dependencies.md +0 -97
  814. package/docs/plans/07.captcha.test.page.md +0 -41
  815. package/docs/plans/08.production.infra.md +0 -70
  816. package/docs/plans/09.database.schema.md +0 -121
  817. package/docs/plans/10.cloudinary.storage.md +0 -57
  818. package/docs/plans/11.movement.logs.json.md +0 -72
  819. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  820. package/docs/plans/13.research.anti.detection.md +0 -898
  821. package/docs/plans/14.research.proxy.md +0 -1495
  822. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  823. package/docs/plans/16.research.crawling.md +0 -1417
  824. package/docs/plans/17.research.caching.md +0 -1610
  825. package/docs/plans/18.research.content.extraction.md +0 -1952
  826. package/docs/plans/19.research.errors.events.md +0 -1523
  827. package/docs/plans/20.research.zod.validation.md +0 -1350
  828. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  829. package/docs/plans/22.research.universal.runtime.md +0 -944
  830. package/docs/plans/23.research.ai.integration.md +0 -1465
  831. package/docs/plans/24.research.memory.persistence.md +0 -1979
  832. package/docs/plans/25.research.server.api.md +0 -342
  833. package/docs/plans/26.research.compilation.md +0 -249
  834. package/docs/plans/27.research.html.parsing.md +0 -251
  835. package/docs/plans/28.action.plan.md +0 -50
  836. package/docs/plans/29.api.reference.md +0 -174
  837. package/docs/plans/30.architecture.plan.md +0 -94
  838. package/docs/plans/31.auditoria.dados.md +0 -163
  839. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  840. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  841. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  842. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  843. package/docs/plans/36.computational.memory.md +0 -340
  844. package/docs/plans/37.deploystrategy.md +0 -394
  845. package/docs/plans/38.flow.md +0 -155
  846. package/docs/plans/39.multi.platform.bot.md +0 -252
  847. package/docs/plans/40.npm.publish.md +0 -250
  848. package/docs/plans/41.o.que.falta.md +0 -407
  849. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  850. package/docs/plans/43.plan.universal.architecture.md +0 -496
  851. package/docs/plans/44.reference.md +0 -100
  852. package/docs/plans/45.robotarchitecture.md +0 -237
  853. package/docs/plans/46.scdnintegration.md +0 -284
  854. package/docs/plans/47.multiforge.readme.md +0 -129
  855. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  856. package/docs/plans/49.third.party.infra.md +0 -12
  857. package/docs/plans/50.file.as.compute.md +0 -39
  858. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  859. package/docs/plans/52.manifesto.v8.md +0 -11
  860. package/docs/plans/58.cdn.list.md +0 -23
  861. package/docs/plans/59.sql.frameworks.md +0 -33
  862. package/docs/plans/60.sql.thirdparty.md +0 -26
  863. package/docs/plans/61.objective.multiforge.md +0 -63
  864. package/docs/plans/62.huggingface.upload.md +0 -26
  865. package/docs/plans/63.kaggle.upload.md +0 -24
  866. package/docs/plans/64.npm.storage.md +0 -30
  867. package/docs/plans/65.rclone.terabox.md +0 -32
  868. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  869. package/docs/plans/67.database.todo.md +0 -13
  870. package/docs/plans/68.deploy.packages.todo.md +0 -12
  871. package/docs/plans/69.report.human.operator.md +0 -133
  872. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  873. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  874. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  875. package/docs/plans/73.plan.scifi.repos.md +0 -125
  876. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  877. package/docs/plans/README.md +0 -489
  878. package/docs/plans/aggregate_platforms.mjs +0 -146
  879. package/docs/plans/examplesession.json +0 -36
  880. package/docs/plans/missing-facts.md +0 -192
  881. package/docs/plans/models.md +0 -64
  882. package/docs/plans/organize.cjs +0 -270
  883. package/docs/plans/platforms.md +0 -2887
  884. package/docs/plans/sites.md +0 -31322
  885. package/docs/sources/farm.py +0 -117
  886. package/docs/sources/html/saddle1.html +0 -132
  887. package/docs/sources/html/saddle2.html +0 -157
  888. package/docs/sources/html/saddle3.html +0 -119
  889. package/docs/sources/html/saddle4.html +0 -144
  890. package/docs/sources/html/saddle5.html +0 -72
  891. package/docs/sources/html/saddle6.html +0 -171
  892. package/docs/sources/html/saddle7.html +0 -236
  893. package/docs/sources/saddle.ts +0 -74
  894. package/docs/sources/schema.prisma +0 -88
  895. package/docs/sources/script.sh +0 -64
  896. package/docs/sources/workflows.yml +0 -458
  897. package/docs/talks1/_body.txt +0 -14
  898. package/docs/talks1/_index.md +0 -15
  899. package/docs/talks1/_screenshot.png +0 -0
  900. package/docs/talks1/assistant-01.md +0 -5
  901. package/docs/talks1/assistant-02.md +0 -5
  902. package/docs/talks1/assistant-03.md +0 -531
  903. package/docs/talks1/assistant-04.md +0 -26
  904. package/docs/talks1/assistant-05.md +0 -774
  905. package/docs/talks1/assistant-06.md +0 -1718
  906. package/docs/talks1/scrape-share.cjs +0 -185
  907. package/docs/talks1/scrape-share.ts +0 -183
  908. package/docs/talks1/user-01.md +0 -3
  909. package/docs/talks1/user-02.md +0 -3
  910. package/docs/talks1/user-03.md +0 -88
  911. package/docs/talks1/user-04.md +0 -3
  912. package/docs/talks1/user-05.md +0 -3
  913. package/docs/talks1/user-06.md +0 -88
  914. package/docs/talks1/user-07.md +0 -88
  915. package/docs/talks2/_body.txt +0 -14
  916. package/docs/talks2/_index.md +0 -16
  917. package/docs/talks2/_screenshot.png +0 -0
  918. package/docs/talks2/assistant-01.md +0 -5
  919. package/docs/talks2/assistant-02.md +0 -5
  920. package/docs/talks2/assistant-03.md +0 -424
  921. package/docs/talks2/assistant-04.md +0 -598
  922. package/docs/talks2/assistant-05.md +0 -1280
  923. package/docs/talks2/assistant-06.md +0 -1227
  924. package/docs/talks2/assistant-07.md +0 -1252
  925. package/docs/talks2/user-01.md +0 -3
  926. package/docs/talks2/user-02.md +0 -3
  927. package/docs/talks2/user-03.md +0 -88
  928. package/docs/talks2/user-04.md +0 -88
  929. package/docs/talks2/user-05.md +0 -88
  930. package/docs/talks2/user-06.md +0 -88
  931. package/docs/talks2/user-07.md +0 -3
  932. package/docs/talks3/_body.txt +0 -467
  933. package/docs/talks3/_index.md +0 -10
  934. package/docs/talks3/_screenshot.png +0 -0
  935. package/docs/talks3/assistant-01.md +0 -417
  936. package/docs/talks3/assistant-02.md +0 -417
  937. package/docs/talks3/assistant-03.md +0 -29
  938. package/docs/talks3/assistant-04.md +0 -727
  939. package/docs/talks3/user-01.md +0 -88
  940. package/docs/talks3/user-02.md +0 -88
  941. package/docs/talks3/user-03.md +0 -3
  942. package/docs/talks3/user-04.md +0 -3
  943. package/docs/talks4/_body.txt +0 -14
  944. package/docs/talks4/_index.md +0 -12
  945. package/docs/talks4/_screenshot.png +0 -0
  946. package/docs/talks4/assistant-01.md +0 -5
  947. package/docs/talks4/assistant-02.md +0 -5
  948. package/docs/talks4/assistant-03.md +0 -35
  949. package/docs/talks4/assistant-04.md +0 -512
  950. package/docs/talks4/assistant-05.md +0 -599
  951. package/docs/talks4/user-01.md +0 -3
  952. package/docs/talks4/user-02.md +0 -3
  953. package/docs/talks4/user-03.md +0 -88
  954. package/docs/talks4/user-04.md +0 -88
  955. package/docs/talks4/user-05.md +0 -7
  956. package/docs/talks5/_body.txt +0 -14
  957. package/docs/talks5/_index.md +0 -13
  958. package/docs/talks5/_screenshot.png +0 -0
  959. package/docs/talks5/assistant-01.md +0 -5
  960. package/docs/talks5/assistant-02.md +0 -5
  961. package/docs/talks5/assistant-03.md +0 -690
  962. package/docs/talks5/assistant-04.md +0 -758
  963. package/docs/talks5/assistant-05.md +0 -974
  964. package/docs/talks5/user-01.md +0 -3
  965. package/docs/talks5/user-02.md +0 -3
  966. package/docs/talks5/user-03.md +0 -105
  967. package/docs/talks5/user-04.md +0 -105
  968. package/docs/talks5/user-05.md +0 -63
  969. package/docs/talks5/user-06.md +0 -105
  970. package/docs/talks6/_body.txt +0 -14
  971. package/docs/talks6/_index.md +0 -9
  972. package/docs/talks6/_screenshot.png +0 -0
  973. package/docs/talks6/assistant-01.md +0 -5
  974. package/docs/talks6/assistant-02.md +0 -5
  975. package/docs/talks6/assistant-03.md +0 -1499
  976. package/docs/talks6/user-01.md +0 -3
  977. package/docs/talks6/user-02.md +0 -3
  978. package/docs/talks6/user-03.md +0 -88
  979. package/docs/talks6/user-04.md +0 -88
  980. package/docs/talks7/_body.txt +0 -14
  981. package/docs/talks7/_index.md +0 -10
  982. package/docs/talks7/_screenshot.png +0 -0
  983. package/docs/talks7/assistant-01.md +0 -5
  984. package/docs/talks7/assistant-02.md +0 -5
  985. package/docs/talks7/assistant-03.md +0 -523
  986. package/docs/talks7/assistant-04.md +0 -617
  987. package/docs/talks7/user-01.md +0 -3
  988. package/docs/talks7/user-02.md +0 -3
  989. package/docs/talks7/user-03.md +0 -105
  990. package/docs/talks7/user-04.md +0 -67
  991. package/docs/talks8/conversa1.txt +0 -1322
  992. package/docs/talks8/conversa2.txt +0 -237
  993. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  994. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  995. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  996. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  997. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  998. package/docs/talks9/README (2).md +0 -489
  999. package/docs/talks9/README.md +0 -198
  1000. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  1001. package/docs/talks9/conversa.txt +0 -544
  1002. package/docs/talks9/other (2).md +0 -39
  1003. package/docs/talks9/other.md +0 -57
  1004. package/docs/talks9/outro.txt +0 -24
  1005. /package/{extension/README.md → docs/extension.md} +0 -0
@@ -1,1523 +0,0 @@
1
- # Pesquisa: Error Handling e Event Emitter Patterns (2026)
2
-
3
- ## Sumário
4
-
5
- 1. [Custom Error Classes](#1-custom-error-classes)
6
- 2. [Error Hierarchies with Error Codes](#2-error-hierarchies-with-error-codes)
7
- 3. [Crawlee Error Pattern](#3-crawlee-error-pattern)
8
- 4. [Error Classification](#4-error-classification)
9
- 5. [Recovery Suggestions in Error Objects](#5-recovery-suggestions-in-error-objects)
10
- 6. [Typed EventEmitter in TypeScript](#6-typed-eventemitter-in-typescript)
11
- 7. [Best Packages](#7-best-packages)
12
- 8. [Lifecycle Hooks](#8-lifecycle-hooks)
13
- 9. [Middleware Pipelines](#9-middleware-pipelines)
14
- 10. [Plugin/Hook Systems](#10-pluginhook-systems)
15
- 11. [Tree-shaking](#11-tree-shaking)
16
-
17
- ---
18
-
19
- ## 1. Custom Error Classes
20
-
21
- ### The Problem with TypeScript Errors
22
-
23
- In TypeScript, when you extend `Error`, the prototype chain breaks. `instanceof` checks fail because TypeScript's transpilation of `extends Error` doesn't correctly set up the prototype. The fix is `Object.setPrototypeOf(this, ClassName.prototype)` in the constructor.
24
-
25
- ### Basic Pattern
26
-
27
- ```typescript
28
- class ScraperError extends Error {
29
- public readonly code: string;
30
- public readonly timestamp: Date;
31
-
32
- constructor(message: string, code: string = 'SCRAPER_ERROR') {
33
- super(message);
34
- this.name = this.constructor.name;
35
- this.code = code;
36
- this.timestamp = new Date();
37
-
38
- // Fix prototype chain for instanceof checks
39
- Object.setPrototypeOf(this, new.target.prototype);
40
-
41
- // Capture stack trace (V8 only, not available in all environments)
42
- if (Error.captureStackTrace) {
43
- Error.captureStackTrace(this, this.constructor);
44
- }
45
- }
46
- }
47
-
48
- // Now instanceof works correctly
49
- const err = new ScraperError('Connection failed');
50
- console.log(err instanceof ScraperError); // true
51
- console.log(err instanceof Error); // true
52
- ```
53
-
54
- ### With `new.target` vs Explicit Class
55
-
56
- `new.target` is dynamic and works with subclasses. If you need broader compatibility:
57
-
58
- ```typescript
59
- class ScraperError extends Error {
60
- constructor(message: string) {
61
- super(message);
62
- this.name = this.constructor.name;
63
- // Explicit class version (safer for older transpilers)
64
- Object.setPrototypeOf(this, ScraperError.prototype);
65
- }
66
- }
67
-
68
- class NetworkError extends ScraperError {
69
- constructor(message: string, public readonly url: string) {
70
- super(message);
71
- // Must re-set for each subclass in the chain
72
- Object.setPrototypeOf(this, NetworkError.prototype);
73
- }
74
- }
75
- ```
76
-
77
- ### Error Options Pattern
78
-
79
- ```typescript
80
- interface ScraperErrorOptions {
81
- code: string;
82
- cause?: unknown;
83
- retryable?: boolean;
84
- metadata?: Record<string, unknown>;
85
- }
86
-
87
- class ScraperError extends Error {
88
- public readonly code: string;
89
- public readonly retryable: boolean;
90
- public readonly metadata: Record<string, unknown>;
91
-
92
- constructor(
93
- message: string,
94
- options: ScraperErrorOptions = { code: 'SCRAPER_ERROR' }
95
- ) {
96
- super(message, { cause: options.cause });
97
- this.name = this.constructor.name;
98
- this.code = options.code;
99
- this.retryable = options.retryable ?? false;
100
- this.metadata = options.metadata ?? {};
101
- Object.setPrototypeOf(this, new.target.prototype);
102
- }
103
- }
104
- ```
105
-
106
- ### 2026 Best Practice: Error Cause Chain
107
-
108
- Use the `cause` property (native since ES2022) to chain errors without losing context:
109
-
110
- ```typescript
111
- async function fetchPage(url: string): Promise<string> {
112
- try {
113
- const res = await fetch(url);
114
- return await res.text();
115
- } catch (error) {
116
- throw new ScraperError(`Failed to fetch ${url}`, {
117
- code: 'FETCH_FAILED',
118
- retryable: true,
119
- cause: error,
120
- metadata: { url, timestamp: Date.now() }
121
- });
122
- }
123
- }
124
- ```
125
-
126
- ---
127
-
128
- ## 2. Error Hierarchies with Error Codes
129
-
130
- ### Enum-Based Error Codes
131
-
132
- ```typescript
133
- // Error codes as const enum for tree-shaking
134
- const ErrorCodes = {
135
- // Network errors (1xxx)
136
- NETWORK_TIMEOUT: 'E1001',
137
- NETWORK_CONNECTION_REFUSED: 'E1002',
138
- NETWORK_DNS_FAILURE: 'E1003',
139
- NETWORK_TLS_ERROR: 'E1004',
140
-
141
- // HTTP errors (2xxx)
142
- HTTP_RATE_LIMITED: 'E2001',
143
- HTTP_403: 'E2002',
144
- HTTP_404: 'E2003',
145
- HTTP_500: 'E2004',
146
- HTTP_503: 'E2005',
147
-
148
- // Browser errors (3xxx)
149
- BROWSER_LAUNCH_FAILED: 'E3001',
150
- BROWSER_CRASHED: 'E3002',
151
- BROWSER_TIMEOUT: 'E3003',
152
- BROWSER_NAVIGATION: 'E3004',
153
-
154
- // Scraping errors (4xxx)
155
- SELECTOR_NOT_FOUND: 'E4001',
156
- PARSING_FAILED: 'E4002',
157
- CAPTCHA_DETECTED: 'E4003',
158
- BOT_DETECTED: 'E4004',
159
-
160
- // Session errors (5xxx)
161
- SESSION_EXPIRED: 'E5001',
162
- SESSION_BLOCKED: 'E5002',
163
- COOKIES_INVALID: 'E5003',
164
-
165
- // Configuration errors (6xxx)
166
- CONFIG_INVALID: 'E6001',
167
- CONFIG_MISSING: 'E6002',
168
- } as const;
169
-
170
- type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes];
171
-
172
- // Metadata about each error code
173
- const ErrorMetadata: Record<ErrorCode, {
174
- description: string;
175
- retryable: boolean;
176
- severity: 'low' | 'medium' | 'high' | 'critical';
177
- defaultRetryDelay?: number;
178
- }> = {
179
- [ErrorCodes.NETWORK_TIMEOUT]: {
180
- description: 'Request timed out',
181
- retryable: true,
182
- severity: 'medium',
183
- defaultRetryDelay: 1000,
184
- },
185
- [ErrorCodes.HTTP_RATE_LIMITED]: {
186
- description: 'Server returned 429 Too Many Requests',
187
- retryable: true,
188
- severity: 'medium',
189
- defaultRetryDelay: 5000,
190
- },
191
- [ErrorCodes.BOT_DETECTED]: {
192
- description: 'Anti-bot protection triggered',
193
- retryable: false,
194
- severity: 'high',
195
- },
196
- [ErrorCodes.SELECTOR_NOT_FOUND]: {
197
- description: 'CSS selector matched no elements',
198
- retryable: false,
199
- severity: 'low',
200
- },
201
- } as const;
202
- ```
203
-
204
- ### Full Hierarchy Implementation
205
-
206
- ```typescript
207
- // Base error
208
- class ScraperError extends Error {
209
- public readonly code: ErrorCode;
210
- public readonly retryable: boolean;
211
- public readonly severity: 'low' | 'medium' | 'high' | 'critical';
212
- public readonly timestamp: number;
213
- public readonly metadata: Record<string, unknown>;
214
-
215
- constructor(
216
- message: string,
217
- options: {
218
- code: ErrorCode;
219
- cause?: unknown;
220
- metadata?: Record<string, unknown>;
221
- }
222
- ) {
223
- super(message, { cause: options.cause });
224
- this.name = this.constructor.name;
225
- this.code = options.code;
226
- this.timestamp = Date.now();
227
- this.metadata = options.metadata ?? {};
228
-
229
- const info = ErrorMetadata[options.code];
230
- this.retryable = info?.retryable ?? false;
231
- this.severity = info?.severity ?? 'medium';
232
-
233
- Object.setPrototypeOf(this, new.target.prototype);
234
- }
235
-
236
- toJSON() {
237
- return {
238
- name: this.name,
239
- message: this.message,
240
- code: this.code,
241
- retryable: this.retryable,
242
- severity: this.severity,
243
- timestamp: this.timestamp,
244
- metadata: this.metadata,
245
- stack: this.stack,
246
- };
247
- }
248
- }
249
-
250
- // Network errors
251
- class NetworkError extends ScraperError {
252
- public readonly url: string;
253
-
254
- constructor(message: string, url: string, options: { code: ErrorCode; cause?: unknown }) {
255
- super(message, { ...options, metadata: { ...options.metadata, url } });
256
- this.name = 'NetworkError';
257
- this.url = url;
258
- Object.setPrototypeOf(this, NetworkError.prototype);
259
- }
260
- }
261
-
262
- // HTTP errors
263
- class HttpError extends ScraperError {
264
- public readonly statusCode: number;
265
- public readonly headers: Record<string, string>;
266
-
267
- constructor(
268
- message: string,
269
- statusCode: number,
270
- headers: Record<string, string> = {},
271
- cause?: unknown
272
- ) {
273
- const code = mapHttpStatus(statusCode);
274
- super(message, { code, cause, metadata: { statusCode, headers } });
275
- this.name = 'HttpError';
276
- this.statusCode = statusCode;
277
- this.headers = headers;
278
- Object.setPrototypeOf(this, HttpError.prototype);
279
- }
280
- }
281
-
282
- function mapHttpStatus(status: number): ErrorCode {
283
- if (status === 429) return ErrorCodes.HTTP_RATE_LIMITED;
284
- if (status === 403) return ErrorCodes.HTTP_403;
285
- if (status === 404) return ErrorCodes.HTTP_404;
286
- if (status === 500) return ErrorCodes.HTTP_500;
287
- if (status === 503) return ErrorCodes.HTTP_503;
288
- return ErrorCodes.HTTP_500;
289
- }
290
-
291
- // Browser errors
292
- class BrowserError extends ScraperError {
293
- constructor(message: string, code: ErrorCode, cause?: unknown) {
294
- super(message, { code, cause });
295
- this.name = 'BrowserError';
296
- Object.setPrototypeOf(this, BrowserError.prototype);
297
- }
298
- }
299
-
300
- // Scraping errors
301
- class ScrapingError extends ScraperError {
302
- public readonly selector?: string;
303
- public readonly url: string;
304
-
305
- constructor(
306
- message: string,
307
- url: string,
308
- options: { code: ErrorCode; selector?: string; cause?: unknown }
309
- ) {
310
- super(message, {
311
- ...options,
312
- metadata: { ...options.metadata, url, selector: options.selector },
313
- });
314
- this.name = 'ScrapingError';
315
- this.url = url;
316
- this.selector = options.selector;
317
- Object.setPrototypeOf(this, ScrapingError.prototype);
318
- }
319
- }
320
- ```
321
-
322
- ---
323
-
324
- ## 3. Crawlee Error Pattern
325
-
326
- Crawlee (by Apify) defines a set of specialized error classes that communicate error intent to the framework. This pattern is highly reusable.
327
-
328
- ### Core Crawlee Errors
329
-
330
- ```typescript
331
- // From Crawlee's design philosophy:
332
-
333
- /**
334
- * NonRetryableError - Signals the crawler to stop immediately.
335
- * Use for: fatal configuration errors, invalid state, permanent failures.
336
- */
337
- class NonRetryableError extends Error {
338
- constructor(message: string, options?: { cause?: unknown }) {
339
- super(message, options);
340
- this.name = 'NonRetryableError';
341
- Object.setPrototypeOf(this, NonRetryableError.prototype);
342
- }
343
- }
344
-
345
- /**
346
- * CriticalError - Crash-level error. The crawler cannot recover.
347
- * Use for: browser crashed, out of memory, system-level failures.
348
- */
349
- class CriticalError extends Error {
350
- constructor(message: string, options?: { cause?: unknown }) {
351
- super(message, options);
352
- this.name = 'CriticalError';
353
- Object.setPrototypeOf(this, CriticalError.prototype);
354
- }
355
- }
356
-
357
- /**
358
- * RetryRequestError - Explicitly signals that the request should be retried.
359
- * Use for: transient failures you want to handle manually.
360
- */
361
- class RetryRequestError extends Error {
362
- public readonly retryDelay?: number;
363
- public readonly errorCode?: string;
364
-
365
- constructor(
366
- message: string,
367
- options?: {
368
- retryDelay?: number;
369
- errorCode?: string;
370
- cause?: unknown;
371
- }
372
- ) {
373
- super(message, options);
374
- this.name = 'RetryRequestError';
375
- this.retryDelay = options?.retryDelay;
376
- this.errorCode = options?.errorCode;
377
- Object.setPrototypeOf(this, RetryRequestError.prototype);
378
- }
379
- }
380
-
381
- /**
382
- * SessionError - Session-specific failure (blocked, expired).
383
- * Use for: cookie invalidation, IP bans, session rotation needed.
384
- */
385
- class SessionError extends Error {
386
- public readonly shouldRotateSession: boolean;
387
-
388
- constructor(
389
- message: string,
390
- options?: { shouldRotateSession?: boolean; cause?: unknown }
391
- ) {
392
- super(message, options);
393
- this.name = 'SessionError';
394
- this.shouldRotateSession = options?.shouldRotateSession ?? true;
395
- Object.setPrototypeOf(this, SessionError.prototype);
396
- }
397
- }
398
- ```
399
-
400
- ### Using Crawlee Errors in Practice
401
-
402
- ```typescript
403
- import { PlaywrightCrawler } from 'crawlee';
404
-
405
- const crawler = new PlaywrightCrawler({
406
- async requestHandler({ request, page, session }) {
407
- // Check for CAPTCHA → SessionError triggers rotation
408
- if (await page.$('#captcha')) {
409
- throw new SessionError('CAPTCHA detected', {
410
- shouldRotateSession: true,
411
- });
412
- }
413
-
414
- // Check for bot detection → NonRetryable stops the crawler
415
- if (await page.$('.access-denied')) {
416
- throw new NonRetryableError('Bot detected, IP is banned');
417
- }
418
-
419
- // Rate limiting → RetryRequestError with custom delay
420
- if (await page.$('.rate-limit')) {
421
- throw new RetryRequestError('Rate limited', {
422
- retryDelay: 30_000,
423
- errorCode: 'RATE_LIMITED',
424
- });
425
- }
426
-
427
- // Browser crash → CriticalError stops everything
428
- if (page.isClosed()) {
429
- throw new CriticalError('Page was closed unexpectedly');
430
- }
431
-
432
- // Normal scraping...
433
- const data = await page.evaluate(() => {
434
- return { title: document.title };
435
- });
436
-
437
- awaitcrawler.pushData(data);
438
- },
439
-
440
- async failedRequestHandler({ request, error }) {
441
- if (error instanceof NonRetryableError) {
442
- console.error(`FATAL: ${error.message} — skipping ${request.url}`);
443
- } else if (error instanceof SessionError) {
444
- console.warn(`Session issue on ${request.url}, rotating...`);
445
- } else {
446
- console.error(`Request failed: ${request.url}`, error);
447
- }
448
- },
449
- });
450
- ```
451
-
452
- ---
453
-
454
- ## 4. Error Classification
455
-
456
- ### Strategy Pattern for Retry Decisions
457
-
458
- ```typescript
459
- interface RetryPolicy {
460
- maxRetries: number;
461
- baseDelay: number;
462
- maxDelay: number;
463
- backoffMultiplier: number;
464
- retryableErrors: Set<ErrorCode>;
465
- nonRetryableErrors: Set<ErrorCode>;
466
- }
467
-
468
- const DEFAULT_RETRY_POLICY: RetryPolicy = {
469
- maxRetries: 3,
470
- baseDelay: 1000,
471
- maxDelay: 30_000,
472
- backoffMultiplier: 2,
473
- retryableErrors: new Set([
474
- ErrorCodes.NETWORK_TIMEOUT,
475
- ErrorCodes.NETWORK_CONNECTION_REFUSED,
476
- ErrorCodes.HTTP_RATE_LIMITED,
477
- ErrorCodes.HTTP_500,
478
- ErrorCodes.HTTP_503,
479
- ErrorCodes.BROWSER_CRASHED,
480
- ]),
481
- nonRetryableErrors: new Set([
482
- ErrorCodes.HTTP_404,
483
- ErrorCodes.BOT_DETECTED,
484
- ErrorCodes.CAPTCHA_DETECTED,
485
- ErrorCodes.CONFIG_INVALID,
486
- ]),
487
- };
488
-
489
- class ErrorClassifier {
490
- private policy: RetryPolicy;
491
-
492
- constructor(policy: RetryPolicy = DEFAULT_RETRY_POLICY) {
493
- this.policy = policy;
494
- }
495
-
496
- shouldRetry(error: ScraperError, attempt: number): boolean {
497
- if (attempt >= this.policy.maxRetries) return false;
498
- if (this.policy.nonRetryableErrors.has(error.code)) return false;
499
- if (this.policy.retryableErrors.has(error.code)) return true;
500
- return error.retryable;
501
- }
502
-
503
- getRetryDelay(error: ScraperError, attempt: number): number {
504
- const delay = this.policy.baseDelay * Math.pow(this.policy.backoffMultiplier, attempt);
505
- return Math.min(delay, this.policy.maxDelay);
506
- }
507
-
508
- classify(error: unknown): {
509
- retryable: boolean;
510
- severity: 'low' | 'medium' | 'high' | 'critical';
511
- suggestedAction: string;
512
- } {
513
- if (error instanceof ScraperError) {
514
- const retryable = this.shouldRetry(error, 0);
515
- return {
516
- retryable,
517
- severity: error.severity,
518
- suggestedAction: this.getSuggestedAction(error),
519
- };
520
- }
521
-
522
- // Unknown errors are generally retryable once
523
- return {
524
- retryable: true,
525
- severity: 'medium',
526
- suggestedAction: 'Unknown error, retry cautiously',
527
- };
528
- }
529
-
530
- private getSuggestedAction(error: ScraperError): string {
531
- const actions: Partial<Record<ErrorCode, string>> = {
532
- [ErrorCodes.NETWORK_TIMEOUT]: 'Increase timeout or reduce request rate',
533
- [ErrorCodes.HTTP_RATE_LIMITED]: 'Wait and retry with exponential backoff',
534
- [ErrorCodes.BOT_DETECTED]: 'Rotate proxy/user-agent, review request patterns',
535
- [ErrorCodes.CAPTCHA_DETECTED]: 'Use CAPTCHA solving service or skip URL',
536
- [ErrorCodes.SELECTOR_NOT_FOUND]: 'Verify selector, page structure may have changed',
537
- [ErrorCodes.BROWSER_CRASHED]: 'Restart browser pool, check memory limits',
538
- [ErrorCodes.SESSION_EXPIRED]: 'Refresh session cookies',
539
- };
540
- return actions[error.code] ?? 'Review error details';
541
- }
542
- }
543
- ```
544
-
545
- ---
546
-
547
- ## 5. Recovery Suggestions in Error Objects
548
-
549
- ### Structured Recovery Metadata
550
-
551
- ```typescript
552
- interface RecoverySuggestion {
553
- action: string;
554
- description: string;
555
- automated: boolean; // Can the framework do this automatically?
556
- fallback?: () => unknown;
557
- }
558
-
559
- class ScraperError extends Error {
560
- // ... (previous properties)
561
- public readonly recovery: RecoverySuggestion[];
562
-
563
- constructor(
564
- message: string,
565
- options: {
566
- code: ErrorCode;
567
- cause?: unknown;
568
- recovery?: RecoverySuggestion[];
569
- metadata?: Record<string, unknown>;
570
- }
571
- ) {
572
- super(message, { cause: options.cause });
573
- this.name = this.constructor.name;
574
- this.code = options.code;
575
- this.recovery = options.recovery ?? [];
576
- this.timestamp = Date.now();
577
- this.metadata = options.metadata ?? {};
578
- Object.setPrototypeOf(this, new.target.prototype);
579
- }
580
-
581
- /**
582
- * Get the first automated recovery action, if any.
583
- */
584
- getAutoRecovery(): RecoverySuggestion | undefined {
585
- return this.recovery.find(r => r.automated);
586
- }
587
-
588
- /**
589
- * Get all human-readable recovery instructions.
590
- */
591
- getRecoveryInstructions(): string[] {
592
- return this.recovery.map(r => `[${r.action}] ${r.description}`);
593
- }
594
- }
595
-
596
- // Factory function for common errors with recovery suggestions
597
- function createRateLimitError(
598
- url: string,
599
- retryAfter?: number
600
- ): ScraperError {
601
- const delay = retryAfter ?? 5000;
602
- return new ScraperError(`Rate limited by ${new URL(url).hostname}`, {
603
- code: ErrorCodes.HTTP_RATE_LIMITED,
604
- metadata: { url, retryAfter: delay },
605
- recovery: [
606
- {
607
- action: 'WAIT_AND_RETRY',
608
- description: `Wait ${delay}ms then retry the request`,
609
- automated: true,
610
- },
611
- {
612
- action: 'REDUCE_CONCURRENCY',
613
- description: 'Lower concurrent request count for this domain',
614
- automated: true,
615
- },
616
- {
617
- action: 'ROTATE_PROXY',
618
- description: 'Switch to a different proxy IP address',
619
- automated: true,
620
- fallback: () => ({ proxyChanged: true }),
621
- },
622
- {
623
- action: 'REVIEW_ROBOTS_TXT',
624
- description: 'Check if the site\'s robots.txt allows your crawl pattern',
625
- automated: false,
626
- },
627
- ],
628
- });
629
- }
630
-
631
- function createBotDetectedError(url: string): ScraperError {
632
- return new ScraperError(`Bot detection triggered on ${new URL(url).hostname}`, {
633
- code: ErrorCodes.BOT_DETECTED,
634
- metadata: { url },
635
- recovery: [
636
- {
637
- action: 'ROTATE_USER_AGENT',
638
- description: 'Switch to a different browser fingerprint',
639
- automated: true,
640
- },
641
- {
642
- action: 'ADD_HUMAN_DELAY',
643
- description: 'Insert random delays between actions',
644
- automated: true,
645
- },
646
- {
647
- action: 'STOP_CRAWLING',
648
- description: 'This site has strong bot protection, consider stopping',
649
- automated: false,
650
- },
651
- ],
652
- });
653
- }
654
- ```
655
-
656
- ### Error Handler Using Recovery
657
-
658
- ```typescript
659
- async function handleError(error: unknown): Promise<void> {
660
- if (error instanceof ScraperError) {
661
- console.error(`[${error.code}] ${error.message}`);
662
-
663
- // Log recovery suggestions
664
- const instructions = error.getRecoveryInstructions();
665
- if (instructions.length > 0) {
666
- console.log('Recovery suggestions:');
667
- instructions.forEach(i => console.log(` - ${i}`));
668
- }
669
-
670
- // Try automated recovery
671
- const autoRecovery = error.getAutoRecovery();
672
- if (autoRecovery?.fallback) {
673
- const result = autoRecovery.fallback();
674
- console.log(`Auto-recovery executed: ${autoRecovery.action}`, result);
675
- }
676
- } else {
677
- console.error('Unexpected error:', error);
678
- }
679
- }
680
- ```
681
-
682
- ---
683
-
684
- ## 6. Typed EventEmitter in TypeScript
685
-
686
- ### The Event Map Pattern
687
-
688
- The core idea: define an interface mapping event names to their payload types. This gives you full type safety — TypeScript knows what `on`, `emit`, and `once` accept and return.
689
-
690
- ```typescript
691
- // Define your event map
692
- interface ScraperEvents {
693
- // Event name → payload type
694
- 'request:start': { url: string; timestamp: number };
695
- 'request:success': { url: string; data: unknown; duration: number };
696
- 'request:error': { url: string; error: ScraperError };
697
- 'request:retry': { url: string; attempt: number; delay: number };
698
- 'batch:complete': { total: number; succeeded: number; failed: number };
699
- 'browser:launch': { browser: string; pid: number };
700
- 'browser:crash': { browser: string; error: string };
701
- 'session:rotate': { oldSession: string; newSession: string };
702
- }
703
- ```
704
-
705
- ### Hand-Rolled Typed Emitter
706
-
707
- ```typescript
708
- type EventMap = Record<string, unknown>;
709
-
710
- type EventKey<T extends EventMap> = string & keyof T;
711
- type EventCallback<T extends EventMap, K extends EventKey<T>> =
712
- (payload: T[K]) => void | Promise<void>;
713
-
714
- class TypedEmitter<T extends EventMap> {
715
- private listeners = new Map<string, Set<Function>>();
716
-
717
- on<K extends EventKey<T>>(
718
- event: K,
719
- callback: EventCallback<T, K>
720
- ): () => void {
721
- if (!this.listeners.has(event)) {
722
- this.listeners.set(event, new Set());
723
- }
724
- this.listeners.get(event)!.add(callback);
725
-
726
- // Return unsubscribe function
727
- return () => {
728
- this.listeners.get(event)?.delete(callback);
729
- };
730
- }
731
-
732
- once<K extends EventKey<T>>(event: K, callback: EventCallback<T, K>): () => void {
733
- const wrapped = ((payload: T[K]) => {
734
- this.off(event, wrapped as EventCallback<T, K>);
735
- return callback(payload);
736
- }) as EventCallback<T, K>;
737
- return this.on(event, wrapped);
738
- }
739
-
740
- off<K extends EventKey<T>>(event: K, callback: EventCallback<T, K>): void {
741
- this.listeners.get(event)?.delete(callback);
742
- }
743
-
744
- async emit<K extends EventKey<T>>(event: K, payload: T[K]): Promise<void> {
745
- const callbacks = this.listeners.get(event);
746
- if (!callbacks) return;
747
-
748
- for (const callback of callbacks) {
749
- try {
750
- await (callback as EventCallback<T, K>)(payload);
751
- } catch (error) {
752
- console.error(`Error in listener for "${event}":`, error);
753
- }
754
- }
755
- }
756
-
757
- removeAllListeners(event?: EventKey<T>): void {
758
- if (event) {
759
- this.listeners.delete(event);
760
- } else {
761
- this.listeners.clear();
762
- }
763
- }
764
-
765
- listenerCount(event: EventKey<T>): number {
766
- return this.listeners.get(event)?.size ?? 0;
767
- }
768
- }
769
-
770
- // Usage
771
- const emitter = new TypedEmitter<ScraperEvents>();
772
-
773
- // ✅ TypeScript knows payload is { url: string; timestamp: number }
774
- emitter.on('request:start', (payload) => {
775
- console.log(`Starting ${payload.url} at ${payload.timestamp}`);
776
- });
777
-
778
- // ✅ TypeScript error if you try wrong event name or wrong payload
779
- // emitter.on('request:start', (payload) => {
780
- // console.log(payload.data); // ❌ Error: 'data' does not exist
781
- // });
782
- ```
783
-
784
- ---
785
-
786
- ## 7. Best Packages
787
-
788
- ### emittery 2.0.0 (Recommended for Modern Projects)
789
-
790
- - **Async-first**: All handlers are awaited
791
- - **AbortSignal support**: Native integration with `AbortController`
792
- - **Symbol.dispose**: Supports the new `using` keyword (TC39 Explicit Resource Management)
793
- - **Type-safe**: Excellent TypeScript support
794
-
795
- ```typescript
796
- import Emittery from 'emittery';
797
-
798
- interface Events {
799
- data: { chunk: Buffer; source: string };
800
- error: { error: Error; recoverable: boolean };
801
- done: undefined;
802
- }
803
-
804
- const emitter = new Emittery<Events>();
805
-
806
- // Async iteration
807
- async function processEvents() {
808
- for await (const data of emitter.events('data')) {
809
- console.log(`Received ${data.chunk.length} bytes from ${data.source}`);
810
- }
811
- }
812
-
813
- // AbortSignal support
814
- const controller = new AbortController();
815
- emitter.on('data', async (data) => {
816
- await processChunk(data);
817
- }, { signal: controller.signal });
818
-
819
- // Symbol.dispose for `using` keyword
820
- {
821
- using _sub = emitter.on('error', (err) => console.error(err));
822
- // Automatically unsubscribed when scope exits
823
- }
824
- ```
825
-
826
- ### eventemitter3 5.0.4 (Fastest)
827
-
828
- - **Fastest**: Benchmarks 2-5x faster than Node's EventEmitter
829
- - **Tiny**: ~1KB minified
830
- - **No extra features**: Just fast events
831
-
832
- ```typescript
833
- import EventEmitter from 'eventemitter3';
834
-
835
- interface Events {
836
- 'data:chunk': Buffer;
837
- 'scrape:complete': { url: string; items: number };
838
- }
839
-
840
- const ee = new EventEmitter<Events>();
841
-
842
- // Same API as Node EventEmitter, but faster
843
- ee.on('data:chunk', (chunk) => {
844
- console.log(chunk.length);
845
- });
846
-
847
- ee.emit('scrape:complete', { url: 'https://example.com', items: 42 });
848
- ```
849
-
850
- ### mitt 3.0.1 (Smallest)
851
-
852
- - **200 bytes** gzipped
853
- - **No dependencies**
854
- - **Works everywhere**: Browser, Node, Deno, Bun
855
-
856
- ```typescript
857
- import mitt from 'mitt';
858
-
859
- interface Events {
860
- 'scrape:start': string;
861
- 'scrape:end': { url: string; duration: number };
862
- }
863
-
864
- const emitter = mitt<Events>();
865
-
866
- emitter.on('scrape:start', (url) => console.log(`Starting ${url}`));
867
- emitter.on('scrape:end', ({ url, duration }) => console.log(`${url}: ${duration}ms`));
868
-
869
- emitter.emit('scrape:start', 'https://example.com');
870
- ```
871
-
872
- ### Comparison Table
873
-
874
- | Feature | emittery 2.0 | eventemitter3 5.0 | mitt 3.0 |
875
- |---------|-------------|-------------------|----------|
876
- | Size (gzip) | ~3KB | ~1KB | ~200B |
877
- | Async handlers | ✅ Native | ❌ Manual | ❌ Manual |
878
- | AbortSignal | ✅ Built-in | ❌ No | ❌ No |
879
- | Symbol.dispose | ✅ Yes | ❌ No | ❌ No |
880
- | Type safety | ✅ Excellent | ✅ Good | ✅ Good |
881
- | Performance | Good | Best | Good |
882
- | Node.js | ✅ | ✅ | ✅ |
883
- | Browser | ✅ | ✅ | ✅ |
884
-
885
- **Recommendation**: Use `emittery` for new projects (best DX), `eventemitter3` for performance-critical paths, `mitt` for minimal bundles.
886
-
887
- ---
888
-
889
- ## 8. Lifecycle Hooks
890
-
891
- ### The Pattern
892
-
893
- Lifecycle hooks are named extension points where plugins or middleware can inject behavior. This pattern is used by `ky`, `ofetch`, and various scraping frameworks.
894
-
895
- ```typescript
896
- interface RequestLifecycle {
897
- beforeRequest: ((request: Request) => Request | Promise<Request>)[];
898
- afterResponse: ((response: Response, request: Request) => Response | Promise<Response>)[];
899
- beforeRetry: ((error: ScraperError, attempt: number) => void | Promise<void>)[];
900
- beforeError: ((error: ScraperError) => ScraperError | Promise<ScraperError>)[];
901
- }
902
-
903
- class RequestPipeline {
904
- private hooks: RequestLifecycle = {
905
- beforeRequest: [],
906
- afterResponse: [],
907
- beforeRetry: [],
908
- beforeError: [],
909
- };
910
-
911
- on<K extends keyof RequestLifecycle>(
912
- hook: K,
913
- callback: RequestLifecycle[K][number]
914
- ): () => void {
915
- this.hooks[hook].push(callback as never);
916
- return () => {
917
- const idx = this.hooks[hook].indexOf(callback as never);
918
- if (idx !== -1) this.hooks[hook].splice(idx, 1);
919
- };
920
- }
921
-
922
- async executeRequest(
923
- url: string,
924
- options: RequestInit = {}
925
- ): Promise<Response> {
926
- let request = new Request(url, options);
927
- let attempt = 0;
928
- const maxAttempts = 3;
929
-
930
- while (attempt < maxAttempts) {
931
- try {
932
- // beforeRequest hooks
933
- for (const hook of this.hooks.beforeRequest) {
934
- request = await hook(request);
935
- }
936
-
937
- const response = await fetch(request);
938
-
939
- // afterResponse hooks
940
- let processedResponse = response;
941
- for (const hook of this.hooks.afterResponse) {
942
- processedResponse = await hook(processedResponse, request);
943
- }
944
-
945
- if (!processedResponse.ok) {
946
- throw new HttpError(
947
- `HTTP ${processedResponse.status}`,
948
- processedResponse.status
949
- );
950
- }
951
-
952
- return processedResponse;
953
- } catch (error) {
954
- const scraperError = error instanceof ScraperError
955
- ? error
956
- : new ScraperError(String(error), {
957
- code: ErrorCodes.NETWORK_TIMEOUT,
958
- cause: error,
959
- });
960
-
961
- // beforeError hooks
962
- let finalError = scraperError;
963
- for (const hook of this.hooks.beforeError) {
964
- finalError = await hook(finalError);
965
- }
966
-
967
- if (finalError.retryable && attempt < maxAttempts - 1) {
968
- // beforeRetry hooks
969
- for (const hook of this.hooks.beforeRetry) {
970
- await hook(finalError, attempt);
971
- }
972
- attempt++;
973
- await new Promise(r => setTimeout(r, 1000 * attempt));
974
- continue;
975
- }
976
-
977
- throw finalError;
978
- }
979
- }
980
-
981
- throw new ScraperError('Max retries exceeded', {
982
- code: ErrorCodes.NETWORK_TIMEOUT,
983
- });
984
- }
985
- }
986
- ```
987
-
988
- ### ky-Style Plugin API
989
-
990
- ```typescript
991
- // ky-style hooks (simplified)
992
- interface KyOptions {
993
- hooks?: {
994
- beforeRequest?: ((request: Request) => Request | Promise<Request>)[];
995
- afterResponse?: ((response: Response) => Response | Promise<Response>)[];
996
- beforeRetry?: ((error: Error, retryCount: number) => void | Promise<void>)[];
997
- beforeError?: ((error: HTTPError) => HTTPError | Promise<HTTPError>)[];
998
- };
999
- }
1000
-
1001
- // Usage with ky
1002
- import ky from 'ky';
1003
-
1004
- const api = ky.create({
1005
- hooks: {
1006
- beforeRequest: [
1007
- (request) => {
1008
- request.headers.set('Authorization', `Bearer ${getToken()}`);
1009
- return request;
1010
- },
1011
- ],
1012
- afterResponse: [
1013
- (response) => {
1014
- if (response.status === 401) {
1015
- refreshToken();
1016
- }
1017
- return response;
1018
- },
1019
- ],
1020
- beforeRetry: [
1021
- (error, retryCount) => {
1022
- console.log(`Retry #${retryCount} after ${error.message}`);
1023
- },
1024
- ],
1025
- },
1026
- });
1027
- ```
1028
-
1029
- ### ofetch Pattern
1030
-
1031
- ```typescript
1032
- import { ofetch } from 'ofetch';
1033
-
1034
- const fetcher = ofetch.create({
1035
- baseURL: 'https://api.example.com',
1036
- headers: { 'User-Agent': 'MyScraper/1.0' },
1037
-
1038
- // Retry configuration
1039
- retry: 3,
1040
- retryDelay: 1000,
1041
- backoff: (attempt) => Math.pow(2, attempt) * 1000,
1042
-
1043
- // Hook
1044
- onResponse({ response }) {
1045
- console.log(`Response: ${response.status}`);
1046
- },
1047
- onRequestError({ error }) {
1048
- console.error(`Request failed: ${error.message}`);
1049
- },
1050
- });
1051
- ```
1052
-
1053
- ---
1054
-
1055
- ## 9. Middleware Pipelines
1056
-
1057
- ### Koa-Style Onion Model
1058
-
1059
- The onion model wraps the core handler in layers. Each middleware can run code before and after the core, forming a concentric structure like onion layers.
1060
-
1061
- ```typescript
1062
- type Middleware<TContext> = (
1063
- context: TContext,
1064
- next: () => Promise<void>
1065
- ) => Promise<void>;
1066
-
1067
- class MiddlewarePipeline<TContext> {
1068
- private middlewares: Middleware<TContext>[] = [];
1069
-
1070
- use(middleware: Middleware<TContext>): this {
1071
- this.middlewares.push(middleware);
1072
- return this;
1073
- }
1074
-
1075
- async execute(context: TContext): Promise<TContext> {
1076
- // Build the onion: each middleware wraps the next
1077
- let index = this.middlewares.length;
1078
-
1079
- const dispatch = async (i: number): Promise<void> => {
1080
- if (i < this.middlewares.length) {
1081
- const middleware = this.middlewares[i];
1082
- await middleware(context, () => dispatch(i + 1));
1083
- }
1084
- };
1085
-
1086
- await dispatch(0);
1087
- return context;
1088
- }
1089
- }
1090
-
1091
- // Usage
1092
- interface ScrapeContext {
1093
- url: string;
1094
- html?: string;
1095
- data?: unknown;
1096
- error?: ScraperError;
1097
- metadata: Record<string, unknown>;
1098
- }
1099
-
1100
- const pipeline = new MiddlewarePipeline<ScrapeContext>();
1101
-
1102
- // Logging middleware
1103
- pipeline.use(async (ctx, next) => {
1104
- const start = Date.now();
1105
- console.log(`→ ${ctx.url}`);
1106
- await next();
1107
- const duration = Date.now() - start;
1108
- console.log(`← ${ctx.url} (${duration}ms)`);
1109
- });
1110
-
1111
- // User-Agent middleware
1112
- pipeline.use(async (ctx, next) => {
1113
- // Modify request before
1114
- ctx.metadata.userAgent = 'Mozilla/5.0 ...';
1115
- await next();
1116
- // Process response after
1117
- if (ctx.html) {
1118
- console.log(`Fetched ${ctx.html.length} bytes`);
1119
- }
1120
- });
1121
-
1122
- // Error handling middleware
1123
- pipeline.use(async (ctx, next) => {
1124
- try {
1125
- await next();
1126
- } catch (error) {
1127
- ctx.error = error instanceof ScraperError
1128
- ? error
1129
- : new ScraperError(String(error), { code: ErrorCodes.NETWORK_TIMEOUT });
1130
- console.error(`Error on ${ctx.url}: ${ctx.error.message}`);
1131
- }
1132
- });
1133
-
1134
- // Core handler (the innermost layer)
1135
- pipeline.use(async (ctx, next) => {
1136
- const res = await fetch(ctx.url, {
1137
- headers: { 'User-Agent': ctx.metadata.userAgent as string },
1138
- });
1139
- ctx.html = await res.text();
1140
- await next();
1141
- });
1142
-
1143
- // Execute
1144
- const context: ScrapeContext = {
1145
- url: 'https://example.com',
1146
- metadata: {},
1147
- };
1148
- await pipeline.execute(context);
1149
- ```
1150
-
1151
- ### Express-Style Flat Middleware
1152
-
1153
- ```typescript
1154
- type FlatMiddleware<T> = (item: T, next: () => Promise<void>) => Promise<void>;
1155
-
1156
- class FlatPipeline<T> {
1157
- private middlewares: FlatMiddleware<T>[] = [];
1158
-
1159
- use(middleware: FlatMiddleware<T>): this {
1160
- this.middlewares.push(middleware);
1161
- return this;
1162
- }
1163
-
1164
- async execute(item: T): Promise<T> {
1165
- let index = 0;
1166
-
1167
- const next = async (): Promise<void> => {
1168
- if (index < this.middlewares.length) {
1169
- const middleware = this.middlewares[index++];
1170
- await middleware(item, next);
1171
- }
1172
- };
1173
-
1174
- await next();
1175
- return item;
1176
- }
1177
- }
1178
- ```
1179
-
1180
- ### Interceptor Pattern (Axios-Style)
1181
-
1182
- ```typescript
1183
- interface Interceptor<T> {
1184
- onFulfilled: (value: T) => T | Promise<T>;
1185
- onRejected?: (error: unknown) => T | Promise<T>;
1186
- }
1187
-
1188
- class InterceptorManager<T> {
1189
- private interceptors: Interceptor<T>[] = [];
1190
-
1191
- use(
1192
- onFulfilled: (value: T) => T | Promise<T>,
1193
- onRejected?: (error: unknown) => T | Promise<T>
1194
- ): number {
1195
- this.interceptors.push({ onFulfilled, onRejected });
1196
- return this.interceptors.length - 1;
1197
- }
1198
-
1199
- eject(id: number): void {
1200
- this.interceptors.splice(id, 1);
1201
- }
1202
-
1203
- async run(value: T): Promise<T> {
1204
- let result = value;
1205
- for (const interceptor of this.interceptors) {
1206
- try {
1207
- result = await interceptor.onFulfilled(result);
1208
- } catch (error) {
1209
- if (interceptor.onRejected) {
1210
- result = await interceptor.onRejected(error);
1211
- } else {
1212
- throw error;
1213
- }
1214
- }
1215
- }
1216
- return result;
1217
- }
1218
- }
1219
-
1220
- // Usage
1221
- const requestInterceptors = new InterceptorManager<Request>();
1222
- const responseInterceptors = new InterceptorManager<Response>();
1223
-
1224
- requestInterceptors.use(
1225
- (request) => {
1226
- request.headers.set('X-Request-ID', crypto.randomUUID());
1227
- return request;
1228
- }
1229
- );
1230
-
1231
- responseInterceptors.use(
1232
- (response) => {
1233
- console.log(`Status: ${response.status}`);
1234
- return response;
1235
- },
1236
- (error) => {
1237
- console.error('Response error:', error);
1238
- throw error;
1239
- }
1240
- );
1241
- ```
1242
-
1243
- ---
1244
-
1245
- ## 10. Plugin/Hook Systems
1246
-
1247
- ### HookRegistry with Typed Events
1248
-
1249
- ```typescript
1250
- type HookHandler<T = void> = (context: T) => T | Promise<T>;
1251
-
1252
- class HookRegistry<TEventMap extends Record<string, unknown>> {
1253
- private hooks = new Map<string, Set<HookHandler<any>>>();
1254
- private priorities = new Map<string, Map<HookHandler<any>, number>>();
1255
-
1256
- /**
1257
- * Register a hook handler with optional priority (lower = runs first).
1258
- */
1259
- on<K extends keyof TEventMap & string>(
1260
- event: K,
1261
- handler: HookHandler<TEventMap[K]>,
1262
- priority: number = 10
1263
- ): () => void {
1264
- if (!this.hooks.has(event)) {
1265
- this.hooks.set(event, new Set());
1266
- this.priorities.set(event, new Map());
1267
- }
1268
-
1269
- this.hooks.get(event)!.add(handler);
1270
- this.priorities.get(event)!.set(handler, priority);
1271
-
1272
- return () => {
1273
- this.hooks.get(event)?.delete(handler);
1274
- this.priorities.get(event)?.delete(handler);
1275
- };
1276
- }
1277
-
1278
- /**
1279
- * Execute all handlers for an event, in priority order.
1280
- * Each handler receives the result of the previous one.
1281
- */
1282
- async trigger<K extends keyof TEventMap & string>(
1283
- event: K,
1284
- initial: TEventMap[K]
1285
- ): Promise<TEventMap[K]> {
1286
- const handlers = this.hooks.get(event);
1287
- if (!handlers || handlers.size === 0) return initial;
1288
-
1289
- // Sort by priority
1290
- const sorted = [...handlers].sort((a, b) => {
1291
- const pa = this.priorities.get(event)!.get(a) ?? 10;
1292
- const pb = this.priorities.get(event)!.get(b) ?? 10;
1293
- return pa - pb;
1294
- });
1295
-
1296
- let result = initial;
1297
- for (const handler of sorted) {
1298
- try {
1299
- result = await handler(result);
1300
- } catch (error) {
1301
- console.error(`Hook "${event}" handler failed:`, error);
1302
- }
1303
- }
1304
-
1305
- return result;
1306
- }
1307
-
1308
- /**
1309
- * Execute all handlers for an event (fire-and-forget style).
1310
- */
1311
- async notify<K extends keyof TEventMap & string>(
1312
- event: K,
1313
- payload: TEventMap[K]
1314
- ): Promise<void> {
1315
- const handlers = this.hooks.get(event);
1316
- if (!handlers) return;
1317
-
1318
- for (const handler of handlers) {
1319
- try {
1320
- await handler(payload);
1321
- } catch (error) {
1322
- console.error(`Notification handler for "${event}" failed:`, error);
1323
- }
1324
- }
1325
- }
1326
-
1327
- /**
1328
- * Remove all hooks, optionally for a specific event.
1329
- */
1330
- clear(event?: keyof TEventMap & string): void {
1331
- if (event) {
1332
- this.hooks.delete(event);
1333
- this.priorities.delete(event);
1334
- } else {
1335
- this.hooks.clear();
1336
- this.priorities.clear();
1337
- }
1338
- }
1339
- }
1340
-
1341
- // Define event types
1342
- interface CrawlerHooks {
1343
- 'request:before': { url: string; options: RequestInit };
1344
- 'request:after': { url: string; response: Response };
1345
- 'parse:before': { url: string; html: string };
1346
- 'parse:after': { url: string; data: unknown };
1347
- 'error': { url: string; error: ScraperError };
1348
- }
1349
-
1350
- // Usage
1351
- const hooks = new HookRegistry<CrawlerHooks>();
1352
-
1353
- // Register hooks with priorities
1354
- hooks.on('request:before', async (ctx) => {
1355
- ctx.options.headers = { ...ctx.options.headers, 'User-Agent': 'Bot/1.0' };
1356
- return ctx;
1357
- }, 1); // Priority 1 (runs first)
1358
-
1359
- hooks.on('request:before', async (ctx) => {
1360
- console.log(`Fetching ${ctx.url}`);
1361
- return ctx;
1362
- }, 10); // Priority 10 (runs second)
1363
-
1364
- // Plugin system using HookRegistry
1365
- class RateLimitPlugin {
1366
- private requestCounts = new Map<string, number>();
1367
-
1368
- register(hooks: HookRegistry<CrawlerHooks>): void {
1369
- hooks.on('request:before', async (ctx) => {
1370
- const domain = new URL(ctx.url).hostname;
1371
- const count = this.requestCounts.get(domain) ?? 0;
1372
-
1373
- if (count >= 10) {
1374
- await new Promise(r => setTimeout(r, 1000));
1375
- this.requestCounts.set(domain, 0);
1376
- }
1377
-
1378
- this.requestCounts.set(domain, count + 1);
1379
- return ctx;
1380
- }, 5);
1381
- }
1382
- }
1383
-
1384
- // Plugin usage
1385
- const rateLimitPlugin = new RateLimitPlugin();
1386
- rateLimitPlugin.register(hooks);
1387
- ```
1388
-
1389
- ---
1390
-
1391
- ## 11. Tree-shaking
1392
-
1393
- ### Principles
1394
-
1395
- Tree-shaking removes unused code at build time. For your error classes and utilities to be tree-shakeable:
1396
-
1397
- 1. **ESM-only**: Use `export`/`import`, never `module.exports`
1398
- 2. **Named exports**: Avoid default exports (bundlers can't rename them)
1399
- 3. **No side effects**: Mark package as side-effect-free
1400
- 4. **Avoid namespace re-exports**: Don't do `export * as utils from './utils'`
1401
-
1402
- ### package.json Configuration
1403
-
1404
- ```json
1405
- {
1406
- "type": "module",
1407
- "sideEffects": false,
1408
- "exports": {
1409
- ".": {
1410
- "import": "./dist/index.mjs",
1411
- "types": "./dist/index.d.ts"
1412
- },
1413
- "./errors": {
1414
- "import": "./dist/errors.mjs",
1415
- "types": "./dist/errors.d.ts"
1416
- },
1417
- "./events": {
1418
- "import": "./dist/events.mjs",
1419
- "types": "./dist/events.d.ts"
1420
- }
1421
- }
1422
- }
1423
- ```
1424
-
1425
- ### ESM-Only Module Structure
1426
-
1427
- ```typescript
1428
- // src/errors/index.ts — Named exports only!
1429
- export { ScraperError } from './scraper-error.js';
1430
- export { NetworkError } from './network-error.js';
1431
- export { HttpError } from './http-error.js';
1432
- export { BrowserError } from './browser-error.js';
1433
- export { ScrapingError } from './scraping-error.js';
1434
- export { ErrorCodes } from './error-codes.js';
1435
- export { ErrorClassifier } from './error-classifier.js';
1436
-
1437
- // ❌ DON'T: Default export
1438
- // export default { ScraperError, NetworkError };
1439
-
1440
- // ❌ DON'T: Namespace re-export
1441
- // import * as errors from './errors';
1442
- // export { errors };
1443
-
1444
- // ✅ DO: Named exports (tree-shakeable)
1445
- // import { ScraperError, NetworkError } from '@myscrape/errors';
1446
- ```
1447
-
1448
- ### Avoiding Side Effects
1449
-
1450
- ```typescript
1451
- // ❌ BAD: Side effects in module scope
1452
- export class ScraperError extends Error { /* ... */ }
1453
- const globalRegistry = new ErrorRegistry(); // Side effect!
1454
- globalRegistry.register(ScraperError);
1455
-
1456
- // ✅ GOOD: Pure exports, side effects only on explicit call
1457
- export class ScraperError extends Error { /* ... */ }
1458
- export function createRegistry(): ErrorRegistry {
1459
- return new ErrorRegistry();
1460
- }
1461
-
1462
- // ✅ GOOD: Lazy initialization
1463
- let _registry: ErrorRegistry | null = null;
1464
- export function getRegistry(): ErrorRegistry {
1465
- if (!_registry) {
1466
- _registry = new ErrorRegistry();
1467
- }
1468
- return _registry;
1469
- }
1470
- ```
1471
-
1472
- ### tsconfig.json for ESM
1473
-
1474
- ```json
1475
- {
1476
- "compilerOptions": {
1477
- "target": "ES2022",
1478
- "module": "NodeNext",
1479
- "moduleResolution": "NodeNext",
1480
- "declaration": true,
1481
- "declarationMap": true,
1482
- "sourceMap": true,
1483
- "outDir": "./dist",
1484
- "rootDir": "./src",
1485
- "strict": true,
1486
- "esModuleInterop": true,
1487
- "skipLibCheck": true,
1488
- "forceConsistentCasingInFileNames": true
1489
- },
1490
- "include": ["src/**/*"],
1491
- "exclude": ["node_modules", "dist", "**/*.test.ts"]
1492
- }
1493
- ```
1494
-
1495
- ### Bundle Analysis
1496
-
1497
- ```bash
1498
- # Analyze bundle size
1499
- npx @next/bundle-analyzer
1500
-
1501
- # Or use source-map-explorer
1502
- npx source-map-explorer dist/index.mjs
1503
-
1504
- # Check what's included
1505
- npx esbuild src/index.ts --bundle --analyze
1506
- ```
1507
-
1508
- ---
1509
-
1510
- ## Summary: Quick Reference
1511
-
1512
- | Pattern | When to Use | Key Package |
1513
- |---------|-------------|-------------|
1514
- | Custom errors with `Object.setPrototypeOf` | Any TypeScript project | Built-in |
1515
- | Error codes (enum) | Large projects needing error taxonomy | Built-in |
1516
- | Crawlee error classes | Crawling frameworks | crawlee |
1517
- | Error classifier | Retry logic | Custom |
1518
- | Recovery suggestions | Self-healing systems | Custom |
1519
- | TypedEmitter | Event-driven scrapers | emittery / eventemitter3 |
1520
- | Lifecycle hooks | HTTP clients, scrapers | Custom / ky / ofetch |
1521
- | Middleware pipelines | Request processing chains | Custom |
1522
- | HookRegistry | Plugin systems | Custom |
1523
- | Tree-shaking | Production bundles | tsconfig + package.json |