groundswell 0.0.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (554) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -9
  3. package/dist/cache/cache-key.d.ts +86 -0
  4. package/dist/cache/cache-key.d.ts.map +1 -0
  5. package/dist/cache/cache-key.js +204 -0
  6. package/dist/cache/cache-key.js.map +1 -0
  7. package/dist/cache/cache.d.ts +104 -0
  8. package/dist/cache/cache.d.ts.map +1 -0
  9. package/dist/cache/cache.js +179 -0
  10. package/dist/cache/cache.js.map +1 -0
  11. package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
  12. package/dist/cache/index.d.ts.map +1 -0
  13. package/dist/cache/index.js +6 -0
  14. package/dist/cache/index.js.map +1 -0
  15. package/dist/core/agent.d.ts +203 -0
  16. package/dist/core/agent.d.ts.map +1 -0
  17. package/dist/core/agent.js +833 -0
  18. package/dist/core/agent.js.map +1 -0
  19. package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
  20. package/dist/core/context.d.ts.map +1 -0
  21. package/dist/core/context.js +80 -0
  22. package/dist/core/context.js.map +1 -0
  23. package/dist/core/event-tree.d.ts +72 -0
  24. package/dist/core/event-tree.d.ts.map +1 -0
  25. package/dist/core/event-tree.js +211 -0
  26. package/dist/core/event-tree.js.map +1 -0
  27. package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
  28. package/dist/core/factory.d.ts.map +1 -0
  29. package/dist/core/factory.js +110 -0
  30. package/dist/core/factory.js.map +1 -0
  31. package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/index.js +9 -0
  34. package/dist/core/index.js.map +1 -0
  35. package/dist/core/logger.d.ts +50 -0
  36. package/dist/core/logger.d.ts.map +1 -0
  37. package/dist/core/logger.js +91 -0
  38. package/dist/core/logger.js.map +1 -0
  39. package/dist/core/mcp-handler.d.ts +127 -0
  40. package/dist/core/mcp-handler.d.ts.map +1 -0
  41. package/dist/core/mcp-handler.js +323 -0
  42. package/dist/core/mcp-handler.js.map +1 -0
  43. package/dist/core/prompt.d.ts +80 -0
  44. package/dist/core/prompt.d.ts.map +1 -0
  45. package/dist/core/prompt.js +120 -0
  46. package/dist/core/prompt.js.map +1 -0
  47. package/dist/core/workflow-context.d.ts +61 -0
  48. package/dist/core/workflow-context.d.ts.map +1 -0
  49. package/dist/core/workflow-context.js +358 -0
  50. package/dist/core/workflow-context.js.map +1 -0
  51. package/dist/core/workflow.d.ts +543 -0
  52. package/dist/core/workflow.d.ts.map +1 -0
  53. package/dist/core/workflow.js +986 -0
  54. package/dist/core/workflow.js.map +1 -0
  55. package/dist/debugger/event-replayer.d.ts +422 -0
  56. package/dist/debugger/event-replayer.d.ts.map +1 -0
  57. package/dist/debugger/event-replayer.js +639 -0
  58. package/dist/debugger/event-replayer.js.map +1 -0
  59. package/dist/debugger/index.d.ts +2 -0
  60. package/dist/debugger/index.d.ts.map +1 -0
  61. package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
  62. package/dist/debugger/index.js.map +1 -0
  63. package/dist/debugger/tree-debugger.d.ts +240 -0
  64. package/dist/debugger/tree-debugger.d.ts.map +1 -0
  65. package/dist/debugger/tree-debugger.js +620 -0
  66. package/dist/debugger/tree-debugger.js.map +1 -0
  67. package/dist/decorators/index.d.ts +4 -0
  68. package/dist/decorators/index.d.ts.map +1 -0
  69. package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
  70. package/dist/decorators/index.js.map +1 -0
  71. package/dist/decorators/observed-state.d.ts +32 -0
  72. package/dist/decorators/observed-state.d.ts.map +1 -0
  73. package/dist/decorators/observed-state.js +79 -0
  74. package/dist/decorators/observed-state.js.map +1 -0
  75. package/dist/decorators/step.d.ts +15 -0
  76. package/dist/decorators/step.d.ts.map +1 -0
  77. package/dist/decorators/step.js +192 -0
  78. package/dist/decorators/step.js.map +1 -0
  79. package/dist/decorators/task.d.ts +50 -0
  80. package/dist/decorators/task.d.ts.map +1 -0
  81. package/dist/decorators/task.js +118 -0
  82. package/dist/decorators/task.js.map +1 -0
  83. package/dist/examples/index.d.ts +3 -0
  84. package/dist/examples/index.d.ts.map +1 -0
  85. package/{src/examples/index.ts → dist/examples/index.js} +1 -0
  86. package/dist/examples/index.js.map +1 -0
  87. package/dist/examples/tdd-orchestrator.d.ts +15 -0
  88. package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
  89. package/dist/examples/tdd-orchestrator.js +121 -0
  90. package/dist/examples/tdd-orchestrator.js.map +1 -0
  91. package/dist/examples/test-cycle-workflow.d.ts +14 -0
  92. package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
  93. package/dist/examples/test-cycle-workflow.js +116 -0
  94. package/dist/examples/test-cycle-workflow.js.map +1 -0
  95. package/dist/harnesses/claude-code-harness.d.ts +391 -0
  96. package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
  97. package/dist/harnesses/claude-code-harness.js +1076 -0
  98. package/dist/harnesses/claude-code-harness.js.map +1 -0
  99. package/dist/harnesses/harness-registry.d.ts +440 -0
  100. package/dist/harnesses/harness-registry.d.ts.map +1 -0
  101. package/dist/harnesses/harness-registry.js +543 -0
  102. package/dist/harnesses/harness-registry.js.map +1 -0
  103. package/dist/harnesses/index.d.ts +12 -0
  104. package/dist/harnesses/index.d.ts.map +1 -0
  105. package/dist/harnesses/index.js +11 -0
  106. package/dist/harnesses/index.js.map +1 -0
  107. package/dist/harnesses/pi-harness.d.ts +219 -0
  108. package/dist/harnesses/pi-harness.d.ts.map +1 -0
  109. package/dist/harnesses/pi-harness.js +676 -0
  110. package/dist/harnesses/pi-harness.js.map +1 -0
  111. package/dist/harnesses/pi-schema-converter.d.ts +24 -0
  112. package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
  113. package/dist/harnesses/pi-schema-converter.js +81 -0
  114. package/dist/harnesses/pi-schema-converter.js.map +1 -0
  115. package/dist/harnesses/register-defaults.d.ts +24 -0
  116. package/dist/harnesses/register-defaults.d.ts.map +1 -0
  117. package/dist/harnesses/register-defaults.js +40 -0
  118. package/dist/harnesses/register-defaults.js.map +1 -0
  119. package/dist/harnesses/session-store.d.ts +201 -0
  120. package/dist/harnesses/session-store.d.ts.map +1 -0
  121. package/dist/harnesses/session-store.js +254 -0
  122. package/dist/harnesses/session-store.js.map +1 -0
  123. package/dist/index.d.ts +37 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +57 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/reflection/index.d.ts +5 -0
  128. package/dist/reflection/index.d.ts.map +1 -0
  129. package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
  130. package/dist/reflection/index.js.map +1 -0
  131. package/dist/reflection/reflection.d.ts +84 -0
  132. package/dist/reflection/reflection.d.ts.map +1 -0
  133. package/dist/reflection/reflection.js +344 -0
  134. package/dist/reflection/reflection.js.map +1 -0
  135. package/dist/tools/index.d.ts +6 -0
  136. package/dist/tools/index.d.ts.map +1 -0
  137. package/dist/tools/index.js +11 -0
  138. package/dist/tools/index.js.map +1 -0
  139. package/dist/tools/introspection.d.ts +165 -0
  140. package/dist/tools/introspection.d.ts.map +1 -0
  141. package/dist/tools/introspection.js +324 -0
  142. package/dist/tools/introspection.js.map +1 -0
  143. package/dist/types/agent.d.ts +1317 -0
  144. package/dist/types/agent.d.ts.map +1 -0
  145. package/dist/types/agent.js +423 -0
  146. package/dist/types/agent.js.map +1 -0
  147. package/dist/types/decorators.d.ts +40 -0
  148. package/dist/types/decorators.d.ts.map +1 -0
  149. package/dist/types/decorators.js +2 -0
  150. package/dist/types/decorators.js.map +1 -0
  151. package/dist/types/error-strategy.d.ts +13 -0
  152. package/dist/types/error-strategy.d.ts.map +1 -0
  153. package/dist/types/error-strategy.js +2 -0
  154. package/dist/types/error-strategy.js.map +1 -0
  155. package/dist/types/error.d.ts +20 -0
  156. package/dist/types/error.d.ts.map +1 -0
  157. package/dist/types/error.js +2 -0
  158. package/dist/types/error.js.map +1 -0
  159. package/dist/types/events.d.ts +113 -0
  160. package/dist/types/events.d.ts.map +1 -0
  161. package/dist/types/events.js +2 -0
  162. package/dist/types/events.js.map +1 -0
  163. package/dist/types/harnesses.d.ts +474 -0
  164. package/dist/types/harnesses.d.ts.map +1 -0
  165. package/dist/types/harnesses.js +2 -0
  166. package/dist/types/harnesses.js.map +1 -0
  167. package/dist/types/index.d.ts +23 -0
  168. package/dist/types/index.d.ts.map +1 -0
  169. package/dist/types/index.js +8 -0
  170. package/dist/types/index.js.map +1 -0
  171. package/dist/types/logging.d.ts +24 -0
  172. package/dist/types/logging.d.ts.map +1 -0
  173. package/dist/types/logging.js +2 -0
  174. package/dist/types/logging.js.map +1 -0
  175. package/dist/types/observer.d.ts +18 -0
  176. package/dist/types/observer.d.ts.map +1 -0
  177. package/dist/types/observer.js +2 -0
  178. package/dist/types/observer.js.map +1 -0
  179. package/dist/types/prompt.d.ts +31 -0
  180. package/dist/types/prompt.d.ts.map +1 -0
  181. package/dist/types/prompt.js +6 -0
  182. package/dist/types/prompt.js.map +1 -0
  183. package/dist/types/providers.d.ts +691 -0
  184. package/dist/types/providers.d.ts.map +1 -0
  185. package/dist/types/providers.js +14 -0
  186. package/dist/types/providers.js.map +1 -0
  187. package/dist/types/reflection.d.ts +96 -0
  188. package/dist/types/reflection.d.ts.map +1 -0
  189. package/dist/types/reflection.js +24 -0
  190. package/dist/types/reflection.js.map +1 -0
  191. package/dist/types/restart.d.ts +132 -0
  192. package/dist/types/restart.d.ts.map +1 -0
  193. package/dist/types/restart.js +2 -0
  194. package/dist/types/restart.js.map +1 -0
  195. package/dist/types/sdk-primitives.d.ts +118 -0
  196. package/dist/types/sdk-primitives.d.ts.map +1 -0
  197. package/dist/types/sdk-primitives.js +6 -0
  198. package/dist/types/sdk-primitives.js.map +1 -0
  199. package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
  200. package/dist/types/snapshot.d.ts.map +1 -0
  201. package/dist/types/snapshot.js +2 -0
  202. package/dist/types/snapshot.js.map +1 -0
  203. package/dist/types/streaming.d.ts +194 -0
  204. package/dist/types/streaming.d.ts.map +1 -0
  205. package/dist/types/streaming.js +67 -0
  206. package/dist/types/streaming.js.map +1 -0
  207. package/dist/types/workflow-context.d.ts +275 -0
  208. package/dist/types/workflow-context.d.ts.map +1 -0
  209. package/dist/types/workflow-context.js +8 -0
  210. package/dist/types/workflow-context.js.map +1 -0
  211. package/dist/types/workflow.d.ts +30 -0
  212. package/dist/types/workflow.d.ts.map +1 -0
  213. package/dist/types/workflow.js +2 -0
  214. package/dist/types/workflow.js.map +1 -0
  215. package/dist/utils/agent-validation.d.ts +88 -0
  216. package/dist/utils/agent-validation.d.ts.map +1 -0
  217. package/dist/utils/agent-validation.js +87 -0
  218. package/dist/utils/agent-validation.js.map +1 -0
  219. package/dist/utils/delay.d.ts +7 -0
  220. package/dist/utils/delay.d.ts.map +1 -0
  221. package/dist/utils/delay.js +9 -0
  222. package/dist/utils/delay.js.map +1 -0
  223. package/dist/utils/harness-config.d.ts +180 -0
  224. package/dist/utils/harness-config.d.ts.map +1 -0
  225. package/dist/utils/harness-config.js +311 -0
  226. package/dist/utils/harness-config.js.map +1 -0
  227. package/dist/utils/id.d.ts +6 -0
  228. package/dist/utils/id.d.ts.map +1 -0
  229. package/dist/utils/id.js +12 -0
  230. package/dist/utils/id.js.map +1 -0
  231. package/dist/utils/index.d.ts +13 -0
  232. package/dist/utils/index.d.ts.map +1 -0
  233. package/dist/utils/index.js +11 -0
  234. package/dist/utils/index.js.map +1 -0
  235. package/dist/utils/model-spec.d.ts +110 -0
  236. package/dist/utils/model-spec.d.ts.map +1 -0
  237. package/dist/utils/model-spec.js +149 -0
  238. package/dist/utils/model-spec.js.map +1 -0
  239. package/dist/utils/observable.d.ts +54 -0
  240. package/dist/utils/observable.d.ts.map +1 -0
  241. package/dist/utils/observable.js +82 -0
  242. package/dist/utils/observable.js.map +1 -0
  243. package/dist/utils/provider-config.d.ts +10 -0
  244. package/dist/utils/provider-config.d.ts.map +1 -0
  245. package/dist/utils/provider-config.js +10 -0
  246. package/dist/utils/provider-config.js.map +1 -0
  247. package/dist/utils/restart-analysis.d.ts +202 -0
  248. package/dist/utils/restart-analysis.d.ts.map +1 -0
  249. package/dist/utils/restart-analysis.js +426 -0
  250. package/dist/utils/restart-analysis.js.map +1 -0
  251. package/dist/utils/session-serialization.d.ts +118 -0
  252. package/dist/utils/session-serialization.d.ts.map +1 -0
  253. package/dist/utils/session-serialization.js +217 -0
  254. package/dist/utils/session-serialization.js.map +1 -0
  255. package/dist/utils/workflow-error-utils.d.ts +22 -0
  256. package/dist/utils/workflow-error-utils.d.ts.map +1 -0
  257. package/dist/utils/workflow-error-utils.js +45 -0
  258. package/dist/utils/workflow-error-utils.js.map +1 -0
  259. package/package.json +34 -5
  260. package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
  261. package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
  262. package/.claude/commands/task-breakdown.md +0 -94
  263. package/.claude/settings.local.json +0 -9
  264. package/.claude/system_prompts/task-breakdown.md +0 -101
  265. package/CHANGELOG.md +0 -188
  266. package/PRD.md +0 -543
  267. package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
  268. package/PRPs/PRDs/002-agent-prompt.md +0 -390
  269. package/PRPs/PRDs/003-agent-prompt.md +0 -943
  270. package/PRPs/PRDs/004-agent-prompt.md +0 -1136
  271. package/PRPs/PRDs/tasks-001.json +0 -492
  272. package/PRPs/README.md +0 -83
  273. package/PRPs/templates/prp_base.md +0 -222
  274. package/docs/agent.md +0 -422
  275. package/docs/prompt.md +0 -419
  276. package/docs/workflow.md +0 -600
  277. package/examples/README.md +0 -258
  278. package/examples/examples/01-basic-workflow.ts +0 -100
  279. package/examples/examples/02-decorator-options.ts +0 -217
  280. package/examples/examples/03-parent-child.ts +0 -241
  281. package/examples/examples/04-observers-debugger.ts +0 -340
  282. package/examples/examples/05-error-handling.ts +0 -387
  283. package/examples/examples/06-concurrent-tasks.ts +0 -352
  284. package/examples/examples/07-agent-loops.ts +0 -432
  285. package/examples/examples/08-sdk-features.ts +0 -667
  286. package/examples/examples/09-reflection.ts +0 -573
  287. package/examples/examples/10-introspection.ts +0 -550
  288. package/examples/examples/11-reparenting-workflows.ts +0 -269
  289. package/examples/index.ts +0 -147
  290. package/examples/utils/helpers.ts +0 -57
  291. package/package-lock.json +0 -2398
  292. package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
  293. package/plan/001_d3bb02af4886/backlog.json +0 -867
  294. package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
  295. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
  296. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
  297. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
  298. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
  299. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
  300. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
  301. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
  302. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
  303. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
  304. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
  305. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
  306. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
  307. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
  308. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
  309. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
  310. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
  311. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
  312. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
  313. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
  314. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
  315. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
  316. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
  317. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
  318. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
  319. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
  320. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
  321. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
  322. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
  323. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
  324. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
  325. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
  326. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
  327. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
  328. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
  329. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
  330. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
  331. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
  332. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
  333. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
  334. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
  335. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
  336. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
  337. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
  338. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
  339. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
  340. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
  341. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
  342. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
  343. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
  344. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
  345. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
  346. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
  347. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
  348. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
  349. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
  350. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
  351. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
  352. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
  353. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
  354. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
  355. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
  356. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
  357. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
  358. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
  359. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
  360. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
  361. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
  362. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
  363. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
  364. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
  365. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
  366. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
  367. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
  368. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
  369. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
  370. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
  371. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
  372. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
  373. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
  374. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
  375. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
  376. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
  377. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
  378. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
  379. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
  380. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
  381. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
  382. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
  383. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
  384. package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
  385. package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
  386. package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
  387. package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
  388. package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
  389. package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
  390. package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
  391. package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
  392. package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
  393. package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
  394. package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
  395. package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
  396. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
  397. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
  398. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
  399. package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
  400. package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
  401. package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
  402. package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
  403. package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
  404. package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
  405. package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
  406. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
  407. package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
  408. package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
  409. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
  410. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
  411. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
  412. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
  413. package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
  414. package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
  415. package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
  416. package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
  417. package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
  418. package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
  419. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
  420. package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
  421. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
  422. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
  423. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
  424. package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
  425. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
  426. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
  427. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
  428. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
  429. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
  430. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
  431. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
  432. package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
  433. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
  434. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
  435. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
  436. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
  437. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
  438. package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
  439. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
  440. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
  441. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
  442. package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
  443. package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
  444. package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
  445. package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
  446. package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
  447. package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
  448. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
  449. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
  450. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
  451. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
  452. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
  453. package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
  454. package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
  455. package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
  456. package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
  457. package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
  458. package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
  459. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
  460. package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
  461. package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
  462. package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
  463. package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
  464. package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
  465. package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
  466. package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
  467. package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
  468. package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
  469. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
  470. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
  471. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
  472. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
  473. package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
  474. package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
  475. package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
  476. package/scripts/generate-llms-full.ts +0 -206
  477. package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
  478. package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
  479. package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
  480. package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
  481. package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
  482. package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
  483. package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
  484. package/src/__tests__/adversarial/edge-case.test.ts +0 -703
  485. package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
  486. package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
  487. package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
  488. package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
  489. package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
  490. package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
  491. package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
  492. package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
  493. package/src/__tests__/helpers/index.ts +0 -18
  494. package/src/__tests__/helpers/tree-verification.ts +0 -257
  495. package/src/__tests__/integration/agent-workflow.test.ts +0 -256
  496. package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
  497. package/src/__tests__/integration/observer-logging.test.ts +0 -643
  498. package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
  499. package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
  500. package/src/__tests__/unit/agent.test.ts +0 -169
  501. package/src/__tests__/unit/cache-key.test.ts +0 -182
  502. package/src/__tests__/unit/cache.test.ts +0 -172
  503. package/src/__tests__/unit/context.test.ts +0 -217
  504. package/src/__tests__/unit/decorators.test.ts +0 -100
  505. package/src/__tests__/unit/introspection-tools.test.ts +0 -277
  506. package/src/__tests__/unit/logger.test.ts +0 -293
  507. package/src/__tests__/unit/observable.test.ts +0 -321
  508. package/src/__tests__/unit/prompt.test.ts +0 -135
  509. package/src/__tests__/unit/reflection.test.ts +0 -210
  510. package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
  511. package/src/__tests__/unit/tree-debugger.test.ts +0 -85
  512. package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
  513. package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
  514. package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
  515. package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
  516. package/src/__tests__/unit/workflow.test.ts +0 -357
  517. package/src/cache/cache-key.ts +0 -244
  518. package/src/cache/cache.ts +0 -236
  519. package/src/core/agent.ts +0 -593
  520. package/src/core/event-tree.ts +0 -260
  521. package/src/core/logger.ts +0 -112
  522. package/src/core/mcp-handler.ts +0 -184
  523. package/src/core/prompt.ts +0 -150
  524. package/src/core/workflow-context.ts +0 -351
  525. package/src/core/workflow.ts +0 -540
  526. package/src/debugger/tree-debugger.ts +0 -255
  527. package/src/decorators/observed-state.ts +0 -95
  528. package/src/decorators/step.ts +0 -139
  529. package/src/decorators/task.ts +0 -159
  530. package/src/examples/tdd-orchestrator.ts +0 -65
  531. package/src/examples/test-cycle-workflow.ts +0 -64
  532. package/src/index.ts +0 -142
  533. package/src/reflection/reflection.ts +0 -407
  534. package/src/tools/index.ts +0 -36
  535. package/src/tools/introspection.ts +0 -464
  536. package/src/types/agent.ts +0 -90
  537. package/src/types/decorators.ts +0 -32
  538. package/src/types/error-strategy.ts +0 -13
  539. package/src/types/error.ts +0 -20
  540. package/src/types/events.ts +0 -75
  541. package/src/types/index.ts +0 -55
  542. package/src/types/logging.ts +0 -24
  543. package/src/types/observer.ts +0 -18
  544. package/src/types/prompt.ts +0 -40
  545. package/src/types/reflection.ts +0 -117
  546. package/src/types/sdk-primitives.ts +0 -128
  547. package/src/types/workflow-context.ts +0 -163
  548. package/src/types/workflow.ts +0 -37
  549. package/src/utils/id.ts +0 -11
  550. package/src/utils/index.ts +0 -4
  551. package/src/utils/observable.ts +0 -106
  552. package/src/utils/workflow-error-utils.ts +0 -56
  553. package/tsconfig.json +0 -22
  554. package/vitest.config.ts +0 -16
@@ -1,1170 +0,0 @@
1
- # Error Logging Best Practices for TypeScript/JavaScript Applications
2
-
3
- **Research Date:** 2026-01-12
4
- **Focus Areas:** Observer pattern error handling, logger context propagation, structured logging patterns, TypeScript-specific considerations
5
-
6
- ---
7
-
8
- ## Table of Contents
9
-
10
- 1. [Observer Pattern Error Handling Best Practices](#1-observer-pattern-error-handling-best-practices)
11
- 2. [Logger Context Propagation Through Callback Chains](#2-logger-context-propagation-through-callback-chains)
12
- 3. [Replacing console.error with Structured Logging](#3-replacing-consoleerror-with-structured-logging)
13
- 4. [TypeScript-Specific Considerations](#4-typescript-specific-considerations)
14
- 5. [Recommended Libraries and Tools](#5-recommended-libraries-and-tools)
15
- 6. [Implementation Examples](#6-implementation-examples)
16
-
17
- ---
18
-
19
- ## 1. Observer Pattern Error Handling Best Practices
20
-
21
- ### 1.1 Core Principles
22
-
23
- **Error Isolation**
24
- - Errors in one observer should not prevent other observers from receiving notifications
25
- - Each observer callback should be wrapped in a try-catch block
26
- - Failed observers should be logged but should not break the notification chain
27
-
28
- **Fail-Safe Notification**
29
- ```typescript
30
- interface Observer<T> {
31
- next(value: T): void | Promise<void>;
32
- error(err: Error): void | Promise<void>;
33
- complete(): void | Promise<void>;
34
- }
35
-
36
- class SafeObservable<T> {
37
- private observers: Set<Observer<T>> = new Set();
38
-
39
- subscribe(observer: Observer<T>): () => void {
40
- this.observers.add(observer);
41
- return () => this.observers.delete(observer);
42
- }
43
-
44
- notify(value: T): void {
45
- this.observers.forEach(observer => {
46
- try {
47
- const result = observer.next(value);
48
-
49
- // Handle async observers
50
- if (result instanceof Promise) {
51
- result.catch(err => {
52
- this.handleObserverError(observer, err, value);
53
- });
54
- }
55
- } catch (err) {
56
- this.handleObserverError(observer, err, value);
57
- }
58
- });
59
- }
60
-
61
- private handleObserverError(
62
- observer: Observer<T>,
63
- err: unknown,
64
- value: T
65
- ): void {
66
- const error = err instanceof Error ? err : new Error(String(err));
67
-
68
- // Try to notify observer of error
69
- try {
70
- observer.error(error);
71
- } catch (handlerError) {
72
- // Last resort: log to fallback logger
73
- console.error('Error in observer error handler:', handlerError);
74
- }
75
- }
76
- }
77
- ```
78
-
79
- ### 1.2 Error Handling Patterns
80
-
81
- **Pattern 1: Safe Notification with Error Callback**
82
- ```typescript
83
- type SafeObserverCallback<T> = (value: T) => void | Promise<void>;
84
- type ErrorHandler = (error: Error, observer: SafeObserverCallback<any>) => void;
85
-
86
- class ErrorSafeObservable<T> {
87
- private observers: Map<SafeObserverCallback<T>, ErrorHandler> = new Map();
88
-
89
- subscribe(
90
- onNext: SafeObserverCallback<T>,
91
- onError?: ErrorHandler
92
- ): () => void {
93
- this.observers.set(onNext, onError || this.defaultErrorHandler);
94
- return () => this.observers.delete(onNext);
95
- }
96
-
97
- notify(value: T): void {
98
- this.observers.forEach((errorHandler, observer) => {
99
- try {
100
- const result = observer(value);
101
- if (result instanceof Promise) {
102
- result.catch(err => errorHandler(err, observer));
103
- }
104
- } catch (err) {
105
- errorHandler(err, observer);
106
- }
107
- });
108
- }
109
-
110
- private defaultErrorHandler: ErrorHandler = (error, observer) => {
111
- console.error('Observer callback error:', error);
112
- };
113
- }
114
- ```
115
-
116
- **Pattern 2: Error Aggregation**
117
- ```typescript
118
- interface ObserverError {
119
- observer: string;
120
- error: Error;
121
- timestamp: Date;
122
- value?: any;
123
- }
124
-
125
- class ObservableWithErrorAggregation<T> {
126
- private observers: Set<Observer<T>> = new Set();
127
- private errors: ObserverError[] = [];
128
-
129
- notify(value: T): ObserverError[] {
130
- this.errors = [];
131
-
132
- this.observers.forEach(observer => {
133
- try {
134
- observer.next(value);
135
- } catch (err) {
136
- this.errors.push({
137
- observer: observer.constructor.name || 'Anonymous',
138
- error: err instanceof Error ? err : new Error(String(err)),
139
- timestamp: new Date(),
140
- value
141
- });
142
- }
143
- });
144
-
145
- return this.errors;
146
- }
147
-
148
- getErrors(): ObserverError[] {
149
- return [...this.errors];
150
- }
151
- }
152
- ```
153
-
154
- ### 1.3 Best Practices for Observer Error Handling
155
-
156
- 1. **Always wrap observer callbacks in try-catch**
157
- - Prevents cascading failures
158
- - Allows other observers to execute
159
-
160
- 2. **Provide error feedback to observers**
161
- - Implement the `error()` method on observers
162
- - Pass errors back to the observer for handling
163
-
164
- 3. **Log all observer errors**
165
- - Use structured logging with context
166
- - Include observer identity and value that caused error
167
-
168
- 4. **Consider unsubscribing failed observers**
169
- - Optional: Auto-unsubscribe after N errors
170
- - Prevents repeated failures from same observer
171
-
172
- 5. **Handle both sync and async observers**
173
- - Check for Promise return values
174
- - Attach catch handlers to async callbacks
175
-
176
- ---
177
-
178
- ## 2. Logger Context Propagation Through Callback Chains
179
-
180
- ### 2.1 Context Propagation Patterns
181
-
182
- **Pattern 1: AsyncLocalStorage (Node.js)**
183
- ```typescript
184
- import { AsyncLocalStorage } from 'async_hooks';
185
-
186
- interface LogContext {
187
- correlationId: string;
188
- userId?: string;
189
- requestId?: string;
190
- operation?: string;
191
- }
192
-
193
- const contextStorage = new AsyncLocalStorage<LogContext>();
194
-
195
- class ContextualLogger {
196
- error(message: string, error?: Error): void {
197
- const context = contextStorage.getStore();
198
- console.error({
199
- timestamp: new Date().toISOString(),
200
- message,
201
- error: error ? {
202
- name: error.name,
203
- message: error.message,
204
- stack: error.stack
205
- } : undefined,
206
- ...context
207
- });
208
- }
209
-
210
- info(message: string, metadata?: Record<string, any>): void {
211
- const context = contextStorage.getStore();
212
- console.info({
213
- timestamp: new Date().toISOString(),
214
- message,
215
- ...metadata,
216
- ...context
217
- });
218
- }
219
- }
220
-
221
- // Usage
222
- const logger = new ContextualLogger();
223
-
224
- async function withContext<T>(
225
- context: LogContext,
226
- fn: () => Promise<T>
227
- ): Promise<T> {
228
- return contextStorage.run(context, fn);
229
- }
230
-
231
- // Example: Context propagates through callback chain
232
- async function processUser(userId: string) {
233
- return withContext(
234
- { correlationId: generateId(), userId, operation: 'processUser' },
235
- async () => {
236
- logger.info('Starting user processing');
237
-
238
- // Context is preserved through all async operations
239
- await processData();
240
- await validateData();
241
-
242
- logger.info('Completed user processing');
243
- }
244
- );
245
- }
246
- ```
247
-
248
- **Pattern 2: Explicit Context Passing**
249
- ```typescript
250
- interface LoggerContext {
251
- traceId: string;
252
- component: string;
253
- userId?: string;
254
- }
255
-
256
- type ContextualCallback<T> = (context: LoggerContext, data: T) => void;
257
-
258
- class ContextAwareObservable<T> {
259
- private baseContext: LoggerContext;
260
- private observers: Set<ContextualCallback<T>> = new Set();
261
-
262
- constructor(baseContext: LoggerContext) {
263
- this.baseContext = baseContext;
264
- }
265
-
266
- subscribe(callback: ContextualCallback<T>): () => void {
267
- this.observers.add(callback);
268
- return () => this.observers.delete(callback);
269
- }
270
-
271
- notify(data: T): void {
272
- const context = {
273
- ...this.baseContext,
274
- timestamp: new Date().toISOString()
275
- };
276
-
277
- this.observers.forEach(callback => {
278
- try {
279
- callback(context, data);
280
- } catch (err) {
281
- console.error('Observer error:', {
282
- error: err instanceof Error ? err.message : String(err),
283
- context
284
- });
285
- }
286
- });
287
- }
288
- }
289
-
290
- // Usage
291
- const observable = new ContextAwareObservable({
292
- traceId: 'trace-123',
293
- component: 'UserService'
294
- });
295
-
296
- observable.subscribe((context, data) => {
297
- console.log('Received data:', { context, data });
298
- });
299
- ```
300
-
301
- **Pattern 3: Logger Factory Pattern**
302
- ```typescript
303
- class LoggerFactory {
304
- private static baseContext: Record<string, any> = {};
305
-
306
- static setBaseContext(context: Record<string, any>): void {
307
- this.baseContext = { ...this.baseContext, ...context };
308
- }
309
-
310
- static createLogger(component: string): Logger {
311
- return new Logger({
312
- ...this.baseContext,
313
- component
314
- });
315
- }
316
-
317
- static withContext<T>(
318
- context: Record<string, any>,
319
- fn: () => T
320
- ): T {
321
- const originalContext = { ...this.baseContext };
322
- this.baseContext = { ...this.baseContext, ...context };
323
-
324
- try {
325
- return fn();
326
- } finally {
327
- this.baseContext = originalContext;
328
- }
329
- }
330
- }
331
-
332
- class Logger {
333
- constructor(private context: Record<string, any>) {}
334
-
335
- error(message: string, error?: Error): void {
336
- console.error({
337
- timestamp: new Date().toISOString(),
338
- level: 'error',
339
- message,
340
- ...(error && {
341
- error: {
342
- name: error.name,
343
- message: error.message,
344
- stack: error.stack
345
- }
346
- }),
347
- ...this.context
348
- });
349
- }
350
- }
351
- ```
352
-
353
- ### 2.2 Best Practices for Context Propagation
354
-
355
- 1. **Use AsyncLocalStorage in Node.js**
356
- - Automatic propagation through async boundaries
357
- - No need to manually pass context
358
- - Zero overhead for synchronous code
359
-
360
- 2. **Include correlation/trace IDs**
361
- - Track requests across service boundaries
362
- - Enable distributed tracing
363
- - Use UUIDs or similar unique identifiers
364
-
365
- 3. **Make context immutable**
366
- - Prevent accidental modifications
367
- - Use Readonly types in TypeScript
368
- - Create new context objects instead of mutating
369
-
370
- 4. **Set context at entry points**
371
- - HTTP request handlers
372
- - Message queue consumers
373
- - Scheduled job entry points
374
-
375
- 5. **Beware of context loss**
376
- - Some async operations lose context
377
- - Be careful with setTimeout/setInterval
378
- - Test context propagation thoroughly
379
-
380
- ---
381
-
382
- ## 3. Replacing console.error with Structured Logging
383
-
384
- ### 3.1 Why Replace console.error?
385
-
386
- **Limitations of console.error:**
387
- - Inconsistent format across browsers/environments
388
- - Difficult to parse and search in production
389
- - No built-in log levels or filtering
390
- - Lacks metadata/context attachment
391
- - Not suitable for centralized logging
392
-
393
- **Benefits of Structured Logging:**
394
- - JSON format for easy parsing
395
- - Searchable and queryable
396
- - Consistent schema across application
397
- - Support for log levels and filtering
398
- - Integration with log aggregation tools
399
- - Better debugging in production
400
-
401
- ### 3.2 Structured Logging Libraries
402
-
403
- **Winston (Industry Standard)**
404
- ```typescript
405
- import winston from 'winston';
406
-
407
- const logger = winston.createLogger({
408
- level: process.env.LOG_LEVEL || 'info',
409
- format: winston.format.combine(
410
- winston.format.timestamp({
411
- format: 'YYYY-MM-DD HH:mm:ss'
412
- }),
413
- winston.format.errors({ stack: true }),
414
- winston.format.json()
415
- ),
416
- defaultMeta: {
417
- service: 'user-service',
418
- environment: process.env.NODE_ENV
419
- },
420
- transports: [
421
- new winston.transports.Console({
422
- format: winston.format.combine(
423
- winston.format.colorize(),
424
- winston.format.simple()
425
- )
426
- }),
427
- new winston.transports.File({
428
- filename: 'error.log',
429
- level: 'error'
430
- }),
431
- new winston.transports.File({
432
- filename: 'combined.log'
433
- })
434
- ]
435
- });
436
-
437
- // Usage
438
- logger.error('Failed to process user', {
439
- userId: '12345',
440
- error: error.message,
441
- stack: error.stack,
442
- operation: 'processUser'
443
- });
444
- ```
445
-
446
- **Pino (High Performance)**
447
- ```typescript
448
- import pino from 'pino';
449
-
450
- const logger = pino({
451
- level: process.env.LOG_LEVEL || 'info',
452
- formatters: {
453
- level: (label) => {
454
- return { level: label };
455
- }
456
- },
457
- redact: ['password', 'token', 'secret'],
458
- timestamp: pino.stdTimeFunctions.isoTime
459
- });
460
-
461
- // Usage
462
- logger.error({
463
- userId: '12345',
464
- err: {
465
- type: error.name,
466
- message: error.message,
467
- stack: error.stack
468
- },
469
- operation: 'processUser'
470
- }, 'Failed to process user');
471
- ```
472
-
473
- **Roarr (Minimalist)**
474
- ```typescript
475
- import Logger from 'roarr';
476
-
477
- const logger = new Logger();
478
-
479
- logger.error({
480
- userId: '12345',
481
- error: {
482
- message: error.message,
483
- stack: error.stack
484
- }
485
- }, 'Failed to process user');
486
- ```
487
-
488
- ### 3.3 Migration Strategy
489
-
490
- **Phase 1: Create Logging Abstraction**
491
- ```typescript
492
- interface ILogger {
493
- error(message: string, error?: Error, context?: Record<string, any>): void;
494
- warn(message: string, context?: Record<string, any>): void;
495
- info(message: string, context?: Record<string, any>): void;
496
- debug(message: string, context?: Record<string, any>): void;
497
- }
498
-
499
- // Create adapter for your chosen library
500
- class LoggerAdapter implements ILogger {
501
- constructor(private winston: winston.Logger) {}
502
-
503
- error(message: string, error?: Error, context?: Record<string, any>): void {
504
- this.winston.error(message, {
505
- ...(error && {
506
- error: {
507
- name: error.name,
508
- message: error.message,
509
- stack: error.stack
510
- }
511
- }),
512
- ...context
513
- });
514
- }
515
-
516
- // ... other methods
517
- }
518
- ```
519
-
520
- **Phase 2: Gradual Replacement**
521
- ```typescript
522
- // Before
523
- console.error('Observer error:', error);
524
-
525
- // After
526
- logger.error('Observer error', error, {
527
- component: 'Observable',
528
- observer: observerName
529
- });
530
- ```
531
-
532
- **Phase 3: Replace All Instances**
533
- ```bash
534
- # Find all console.error calls
535
- grep -r "console\.error" src/
536
-
537
- # Replace systematically
538
- ```
539
-
540
- ### 3.4 Structured Logging Best Practices
541
-
542
- 1. **Use consistent field names**
543
- - `timestamp` (ISO 8601 format)
544
- - `level` (error, warn, info, debug)
545
- - `message` (human-readable description)
546
- - `error` (error details)
547
- - `context` (additional metadata)
548
-
549
- 2. **Include correlation IDs**
550
- - Link related log entries
551
- - Track requests across boundaries
552
- - Enable distributed tracing
553
-
554
- 3. **Sanitize sensitive data**
555
- - Passwords, tokens, API keys
556
- - Personal information (PII)
557
- - Use redaction in logger configuration
558
-
559
- 4. **Use appropriate log levels**
560
- - `error`: Application errors requiring attention
561
- - `warn`: Warning conditions not stopping execution
562
- - `info`: General informational messages
563
- - `debug`: Detailed diagnostic information
564
-
565
- 5. **Structure error objects consistently**
566
- ```typescript
567
- {
568
- error: {
569
- type: 'DatabaseError',
570
- message: 'Connection failed',
571
- code: 'DB_CONN_001',
572
- stack: '...',
573
- context: {
574
- host: 'localhost',
575
- port: 5432
576
- }
577
- }
578
- }
579
- ```
580
-
581
- ---
582
-
583
- ## 4. TypeScript-Specific Considerations
584
-
585
- ### 4.1 Type-Safe Error Handling
586
-
587
- **Typed Error Classes**
588
- ```typescript
589
- abstract class AppError extends Error {
590
- abstract readonly code: string;
591
- abstract readonly statusCode: number;
592
-
593
- constructor(
594
- message: string,
595
- public readonly context?: Record<string, any>
596
- ) {
597
- super(message);
598
- this.name = this.constructor.name;
599
- Error.captureStackTrace(this, this.constructor);
600
- }
601
- }
602
-
603
- class ValidationError extends AppError {
604
- readonly code = 'VALIDATION_ERROR';
605
- readonly statusCode = 400;
606
-
607
- constructor(
608
- message: string,
609
- public readonly validationErrors: Record<string, string[]>
610
- ) {
611
- super(message);
612
- }
613
- }
614
-
615
- class DatabaseError extends AppError {
616
- readonly code = 'DATABASE_ERROR';
617
- readonly statusCode = 500;
618
-
619
- constructor(
620
- message: string,
621
- public readonly originalError?: Error
622
- ) {
623
- super(message);
624
- }
625
- }
626
- ```
627
-
628
- **Type-Safe Observer Pattern**
629
- ```typescript
630
- type SafeObserverCallback<T, E extends Error = Error> = (
631
- value: T
632
- ) => void | Promise<void>;
633
-
634
- type ErrorHandler<E extends Error = Error> = (
635
- error: E
636
- ) => void | Promise<void>;
637
-
638
- interface StrictObserver<T, E extends Error = Error> {
639
- next(value: T): void | Promise<void>;
640
- error(error: E): void | Promise<void>;
641
- complete(): void | Promise<void>;
642
- }
643
-
644
- class TypedObservable<T, E extends Error = Error> {
645
- private observers: Set<StrictObserver<T, E>> = new Set();
646
-
647
- subscribe(observer: StrictObserver<T, E>): () => void {
648
- this.observers.add(observer);
649
- return () => this.observers.delete(observer);
650
- }
651
-
652
- notify(value: T): void;
653
- notify(error: E): void;
654
- notify(value: T | E): void {
655
- this.observers.forEach(observer => {
656
- try {
657
- if (value instanceof Error) {
658
- observer.error(value as E);
659
- } else {
660
- observer.next(value);
661
- }
662
- } catch (err) {
663
- console.error('Observer error:', err);
664
- }
665
- });
666
- }
667
- }
668
- ```
669
-
670
- ### 4.2 Type-Safe Logger
671
-
672
- ```typescript
673
- type LogLevel = 'debug' | 'info' | 'warn' | 'error';
674
-
675
- interface LogMetadata {
676
- [key: string]: any;
677
- }
678
-
679
- interface LogEntry {
680
- timestamp: string;
681
- level: LogLevel;
682
- message: string;
683
- error?: {
684
- name: string;
685
- message: string;
686
- stack?: string;
687
- code?: string;
688
- };
689
- metadata?: LogMetadata;
690
- }
691
-
692
- class TypedLogger {
693
- constructor(
694
- private component: string,
695
- private baseContext: LogMetadata = {}
696
- ) {}
697
-
698
- private log(level: LogLevel, message: string, entry: Partial<LogEntry> = {}): void {
699
- const logEntry: LogEntry = {
700
- timestamp: new Date().toISOString(),
701
- level,
702
- message,
703
- ...entry,
704
- metadata: {
705
- component: this.component,
706
- ...this.baseContext,
707
- ...entry.metadata
708
- }
709
- };
710
-
711
- console[level](JSON.stringify(logEntry));
712
- }
713
-
714
- error(message: string, error?: Error, metadata?: LogMetadata): void {
715
- this.log('error', message, {
716
- ...(error && {
717
- error: {
718
- name: error.name,
719
- message: error.message,
720
- stack: error.stack,
721
- code: (error as any).code
722
- }
723
- }),
724
- metadata
725
- });
726
- }
727
-
728
- warn(message: string, metadata?: LogMetadata): void {
729
- this.log('warn', message, { metadata });
730
- }
731
-
732
- info(message: string, metadata?: LogMetadata): void {
733
- this.log('info', message, { metadata });
734
- }
735
-
736
- debug(message: string, metadata?: LogMetadata): void {
737
- this.log('debug', message, { metadata });
738
- }
739
-
740
- withContext(context: LogMetadata): TypedLogger {
741
- return new TypedLogger(this.component, {
742
- ...this.baseContext,
743
- ...context
744
- });
745
- }
746
- }
747
-
748
- // Usage
749
- const logger = new TypedLogger('UserService');
750
-
751
- logger.error('Failed to create user', error, {
752
- userId: '12345',
753
- email: 'user@example.com'
754
- });
755
-
756
- const userScopedLogger = logger.withContext({ userId: '12345' });
757
- userScopedLogger.info('User profile updated');
758
- ```
759
-
760
- ### 4.3 Type Guards for Error Handling
761
-
762
- ```typescript
763
- function isError(error: unknown): error is Error {
764
- return (
765
- error instanceof Error ||
766
- (typeof error === 'object' &&
767
- error !== null &&
768
- 'message' in error &&
769
- typeof error.message === 'string')
770
- );
771
- }
772
-
773
- function isAppError(error: unknown): error is AppError {
774
- return isError(error) && error instanceof AppError;
775
- }
776
-
777
- function handleUnknownError(error: unknown): void {
778
- if (isAppError(error)) {
779
- logger.error('Application error', error, {
780
- code: error.code,
781
- context: error.context
782
- });
783
- } else if (isError(error)) {
784
- logger.error('Unexpected error', error);
785
- } else {
786
- logger.error('Unknown error type', undefined, {
787
- error: String(error)
788
- });
789
- }
790
- }
791
- ```
792
-
793
- ### 4.4 TypeScript Best Practices
794
-
795
- 1. **Use discriminated unions for error types**
796
- ```typescript
797
- type Result<T, E extends Error = Error> =
798
- | { success: true; data: T }
799
- | { success: false; error: E };
800
- ```
801
-
802
- 2. **Leverage utility types**
803
- ```typescript
804
- type ErrorContext<T extends Error> = {
805
- [K in keyof T]?: T[K];
806
- };
807
- ```
808
-
809
- 3. **Use readonly for context**
810
- ```typescript
811
- interface LogContext {
812
- readonly correlationId: string;
813
- readonly userId?: string;
814
- }
815
- ```
816
-
817
- 4. **Enable strict error checking**
818
- ```typescript
819
- // tsconfig.json
820
- {
821
- "compilerOptions": {
822
- "strictNullChecks": true,
823
- "strictPropertyInitialization": true,
824
- "noImplicitAny": true,
825
- "useUnknownInCatchVariables": true
826
- }
827
- }
828
- ```
829
-
830
- 5. **Type-safe logger factories**
831
- ```typescript
832
- function createLogger(component: string): Logger {
833
- return new TypedLogger(component);
834
- }
835
-
836
- // Ensure component names are valid
837
- type ValidComponent =
838
- | 'UserService'
839
- | 'AuthService'
840
- | 'DatabaseService';
841
-
842
- function createComponentLogger(
843
- component: ValidComponent
844
- ): Logger {
845
- return createLogger(component);
846
- }
847
- ```
848
-
849
- ---
850
-
851
- ## 5. Recommended Libraries and Tools
852
-
853
- ### 5.1 Logging Libraries
854
-
855
- | Library | Performance | Features | Best For |
856
- |---------|-------------|----------|----------|
857
- | **Winston** | Medium | Rich features, multiple transports | General-purpose applications |
858
- | **Pino** | Very Fast | Minimal, high performance | High-throughput applications |
859
- | **Bunyan** | Fast | JSON-first, extensible | Node.js applications |
860
- | **log4js** | Medium | Flexible, multiple categories | Applications needing categories |
861
- | **Roarr** | Fast | Minimalist, structured | Modern Node.js applications |
862
-
863
- ### 5.2 Error Handling Libraries
864
-
865
- | Library | Purpose | TypeScript Support |
866
- |---------|---------|-------------------|
867
- | **fp-ts** | Functional error handling | Excellent |
868
- | **neverthrow** | Result type for error handling | Excellent |
869
- | **ts-results** | Result/Option types | Excellent |
870
- | **Vest** | Validation framework | Good |
871
-
872
- ### 5.3 Observable/RxJS Libraries
873
-
874
- | Library | Error Handling | TypeScript Support |
875
- |---------|---------------|-------------------|
876
- | **RxJS** | Comprehensive error operators | Excellent |
877
- | **Zen-observable** | Basic observer pattern | Good |
878
- | **Observable-Flyd** | Lightweight streams | Basic |
879
-
880
- ---
881
-
882
- ## 6. Implementation Examples
883
-
884
- ### 6.1 Complete Observer with Structured Logging
885
-
886
- ```typescript
887
- import winston from 'winston';
888
-
889
- // Setup logger
890
- const logger = winston.createLogger({
891
- level: 'info',
892
- format: winston.format.combine(
893
- winston.format.timestamp(),
894
- winston.format.json()
895
- ),
896
- transports: [new winston.transports.Console()]
897
- });
898
-
899
- // Error types
900
- class ObserverError extends Error {
901
- constructor(
902
- message: string,
903
- public readonly observerName: string,
904
- public readonly value?: any
905
- ) {
906
- super(message);
907
- this.name = 'ObserverError';
908
- }
909
- }
910
-
911
- // Observer interface with error handling
912
- interface Observer<T> {
913
- next(value: T): void | Promise<void>;
914
- error(error: Error): void | Promise<void>;
915
- complete(): void | Promise<void>;
916
- }
917
-
918
- // Observable with comprehensive error handling
919
- class Observable<T> {
920
- private observers: Map<string, Observer<T>> = new Map();
921
- private errors: ObserverError[] = [];
922
-
923
- subscribe(observer: Observer<T>, name: string): () => void {
924
- this.observers.set(name, observer);
925
- return () => this.observers.delete(name);
926
- }
927
-
928
- notify(value: T): void {
929
- this.errors = [];
930
-
931
- this.observers.forEach((observer, name) => {
932
- try {
933
- const result = observer.next(value);
934
-
935
- if (result instanceof Promise) {
936
- result.catch(err => {
937
- this.handleError(name, err, value);
938
- });
939
- }
940
- } catch (err) {
941
- this.handleError(name, err, value);
942
- }
943
- });
944
-
945
- // Log all errors
946
- this.errors.forEach(err => {
947
- logger.error('Observer callback failed', err, {
948
- component: 'Observable',
949
- observer: err.observerName,
950
- value: err.value
951
- });
952
- });
953
- }
954
-
955
- private handleError(
956
- observerName: string,
957
- err: unknown,
958
- value: T
959
- ): void {
960
- const error = err instanceof Error
961
- ? err
962
- : new Error(String(err));
963
-
964
- const observerError = new ObserverError(
965
- error.message,
966
- observerName,
967
- value
968
- );
969
-
970
- this.errors.push(observerError);
971
-
972
- // Try to notify observer
973
- const observer = this.observers.get(observerName);
974
- if (observer) {
975
- try {
976
- observer.error(observerError);
977
- } catch (handlerError) {
978
- logger.error('Observer error handler failed', handlerError instanceof Error ? handlerError : undefined, {
979
- component: 'Observable',
980
- observer: observerName,
981
- originalError: error.message
982
- });
983
- }
984
- }
985
- }
986
- }
987
-
988
- // Usage
989
- const observable = new Observable<number>();
990
-
991
- observable.subscribe(
992
- {
993
- next: (value) => {
994
- console.log('Received:', value);
995
- },
996
- error: (error) => {
997
- console.error('Error:', error.message);
998
- },
999
- complete: () => {
1000
- console.log('Complete');
1001
- }
1002
- },
1003
- 'ConsoleObserver'
1004
- );
1005
-
1006
- observable.notify(42);
1007
- ```
1008
-
1009
- ### 6.2 Logger with Context Propagation
1010
-
1011
- ```typescript
1012
- import { AsyncLocalStorage } from 'async_hooks';
1013
- import winston from 'winston';
1014
-
1015
- interface LogContext {
1016
- traceId: string;
1017
- userId?: string;
1018
- operation?: string;
1019
- }
1020
-
1021
- class ContextualLogger {
1022
- private static storage = new AsyncLocalStorage<LogContext>();
1023
- private static baseLogger = winston.createLogger({
1024
- level: 'info',
1025
- format: winston.format.combine(
1026
- winston.format.timestamp(),
1027
- winston.format.json()
1028
- ),
1029
- transports: [new winston.transports.Console()]
1030
- });
1031
-
1032
- static runWithContext<T>(
1033
- context: LogContext,
1034
- fn: () => Promise<T>
1035
- ): Promise<T> {
1036
- return this.storage.run(context, fn);
1037
- }
1038
-
1039
- private static getContext(): LogContext {
1040
- return this.storage.getStore() || { traceId: 'unknown' };
1041
- }
1042
-
1043
- static error(message: string, error?: Error): void {
1044
- const context = this.getContext();
1045
- this.baseLogger.error(message, {
1046
- ...context,
1047
- ...(error && {
1048
- error: {
1049
- name: error.name,
1050
- message: error.message,
1051
- stack: error.stack
1052
- }
1053
- })
1054
- });
1055
- }
1056
-
1057
- static info(message: string, metadata?: Record<string, any>): void {
1058
- const context = this.getContext();
1059
- this.baseLogger.info(message, {
1060
- ...context,
1061
- ...metadata
1062
- });
1063
- }
1064
- }
1065
-
1066
- // Usage with observer pattern
1067
- async function processWithObserver(data: any[]) {
1068
- return ContextualLogger.runWithContext(
1069
- { traceId: generateId(), operation: 'processData' },
1070
- async () => {
1071
- const observable = new Observable<any>();
1072
-
1073
- observable.subscribe(
1074
- {
1075
- next: (value) => {
1076
- ContextualLogger.info('Processing item', { itemId: value.id });
1077
- // Process value
1078
- },
1079
- error: (error) => {
1080
- ContextualLogger.error('Observer error', error);
1081
- },
1082
- complete: () => {
1083
- ContextualLogger.info('Processing complete');
1084
- }
1085
- },
1086
- 'ItemProcessor'
1087
- );
1088
-
1089
- for (const item of data) {
1090
- observable.notify(item);
1091
- }
1092
- }
1093
- );
1094
- }
1095
- ```
1096
-
1097
- ---
1098
-
1099
- ## Summary and Recommendations
1100
-
1101
- ### Key Takeaways
1102
-
1103
- 1. **Observer Pattern Error Handling**
1104
- - Always wrap observer callbacks in try-catch
1105
- - Isolate errors to prevent cascading failures
1106
- - Provide error feedback through error() method
1107
- - Support both sync and async observers
1108
-
1109
- 2. **Context Propagation**
1110
- - Use AsyncLocalStorage in Node.js for automatic propagation
1111
- - Include correlation/trace IDs for distributed tracing
1112
- - Make context immutable
1113
- - Set context at application entry points
1114
-
1115
- 3. **Structured Logging**
1116
- - Replace console.error with a structured logging library
1117
- - Use consistent field names and schemas
1118
- - Include correlation IDs and metadata
1119
- - Sanitize sensitive data
1120
-
1121
- 4. **TypeScript-Specific Considerations**
1122
- - Create typed error classes
1123
- - Use type guards for error handling
1124
- - Leverage utility types
1125
- - Enable strict error checking in tsconfig
1126
-
1127
- ### Implementation Roadmap
1128
-
1129
- 1. **Phase 1: Setup Infrastructure**
1130
- - Choose and install logging library (Winston or Pino recommended)
1131
- - Create logger abstraction layer
1132
- - Setup AsyncLocalStorage for context propagation
1133
-
1134
- 2. **Phase 2: Create Error Types**
1135
- - Define application error hierarchy
1136
- - Create type-safe error classes
1137
- - Implement error type guards
1138
-
1139
- 3. **Phase 3: Migrate Observer Pattern**
1140
- - Update observer interface with error handling
1141
- - Implement safe notification with try-catch
1142
- - Add structured logging to error handlers
1143
-
1144
- 4. **Phase 4: Replace console.error**
1145
- - Systematically find and replace console.error calls
1146
- - Ensure all errors are logged with context
1147
- - Add correlation IDs throughout application
1148
-
1149
- 5. **Phase 5: Testing and Validation**
1150
- - Test error isolation in observers
1151
- - Verify context propagation
1152
- - Validate log output structure
1153
- - Performance testing
1154
-
1155
- ### Additional Resources
1156
-
1157
- **Documentation**
1158
- - Winston: https://github.com/winstonjs/winston
1159
- - Pino: https://getpino.io/
1160
- - AsyncLocalStorage: https://nodejs.org/api/async_context.html
1161
- - RxJS Error Handling: https://rxjs.dev/guide/error-handling
1162
-
1163
- **Articles**
1164
- - "The Twelve-Factor App - Logging": https://12factor.net/logs
1165
- - "Structured Logging Best Practices": Various Medium/dev.to articles
1166
- - "Observer Pattern in TypeScript": TypeScript documentation and patterns
1167
-
1168
- ---
1169
-
1170
- **Note:** Due to web search quota limitations (resets February 1, 2026), this research is based on established best practices and patterns. For the most current information and specific library documentation, please refer to the official documentation linked above.