@dewtech/dare-cli 3.11.0 → 3.12.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 (308) hide show
  1. package/README.md +2 -0
  2. package/dist/__tests__/ensure-skills.test.js +5 -0
  3. package/dist/__tests__/ensure-skills.test.js.map +1 -1
  4. package/dist/__tests__/ide-command-parity.test.js +1 -0
  5. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  6. package/dist/__tests__/project-generator.test.js +17 -0
  7. package/dist/__tests__/project-generator.test.js.map +1 -1
  8. package/dist/__tests__/reverse-facts.test.js +1 -0
  9. package/dist/__tests__/reverse-facts.test.js.map +1 -1
  10. package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
  11. package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
  12. package/dist/__tests__/terminal-parity-regression.test.js +116 -0
  13. package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
  14. package/dist/__tests__/terminal-parity.test.d.ts +2 -0
  15. package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
  16. package/dist/__tests__/terminal-parity.test.js +81 -0
  17. package/dist/__tests__/terminal-parity.test.js.map +1 -0
  18. package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
  19. package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
  20. package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
  21. package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
  22. package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
  23. package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
  24. package/dist/agent/__tests__/codex-driver.test.js +68 -0
  25. package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
  26. package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
  27. package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
  28. package/dist/agent/__tests__/cursor-driver.test.js +52 -0
  29. package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
  30. package/dist/agent/driver.d.ts +1 -1
  31. package/dist/agent/driver.d.ts.map +1 -1
  32. package/dist/agent/drivers/antigravity.d.ts +8 -0
  33. package/dist/agent/drivers/antigravity.d.ts.map +1 -0
  34. package/dist/agent/drivers/antigravity.js +99 -0
  35. package/dist/agent/drivers/antigravity.js.map +1 -0
  36. package/dist/agent/drivers/codex.d.ts +12 -0
  37. package/dist/agent/drivers/codex.d.ts.map +1 -0
  38. package/dist/agent/drivers/codex.js +137 -0
  39. package/dist/agent/drivers/codex.js.map +1 -0
  40. package/dist/agent/drivers/cursor.d.ts +8 -0
  41. package/dist/agent/drivers/cursor.d.ts.map +1 -0
  42. package/dist/agent/drivers/cursor.js +99 -0
  43. package/dist/agent/drivers/cursor.js.map +1 -0
  44. package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
  45. package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
  46. package/dist/ai/__tests__/ai-core.test.js +41 -0
  47. package/dist/ai/__tests__/ai-core.test.js.map +1 -0
  48. package/dist/ai/__tests__/parity.test.d.ts +2 -0
  49. package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
  50. package/dist/ai/__tests__/parity.test.js +36 -0
  51. package/dist/ai/__tests__/parity.test.js.map +1 -0
  52. package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
  53. package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
  54. package/dist/ai/__tests__/pipeline.test.js +147 -0
  55. package/dist/ai/__tests__/pipeline.test.js.map +1 -0
  56. package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
  57. package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
  58. package/dist/ai/__tests__/refine-bridge.test.js +17 -0
  59. package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
  60. package/dist/ai/__tests__/resolve.test.d.ts +2 -0
  61. package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
  62. package/dist/ai/__tests__/resolve.test.js +42 -0
  63. package/dist/ai/__tests__/resolve.test.js.map +1 -0
  64. package/dist/ai/capabilities.d.ts +3 -0
  65. package/dist/ai/capabilities.d.ts.map +1 -0
  66. package/dist/ai/capabilities.js +11 -0
  67. package/dist/ai/capabilities.js.map +1 -0
  68. package/dist/ai/command-options.d.ts +10 -0
  69. package/dist/ai/command-options.d.ts.map +1 -0
  70. package/dist/ai/command-options.js +15 -0
  71. package/dist/ai/command-options.js.map +1 -0
  72. package/dist/ai/config.d.ts +27 -0
  73. package/dist/ai/config.d.ts.map +1 -0
  74. package/dist/ai/config.js +89 -0
  75. package/dist/ai/config.js.map +1 -0
  76. package/dist/ai/parity.d.ts +13 -0
  77. package/dist/ai/parity.d.ts.map +1 -0
  78. package/dist/ai/parity.js +87 -0
  79. package/dist/ai/parity.js.map +1 -0
  80. package/dist/ai/parse-json-output.d.ts +5 -0
  81. package/dist/ai/parse-json-output.d.ts.map +1 -0
  82. package/dist/ai/parse-json-output.js +25 -0
  83. package/dist/ai/parse-json-output.js.map +1 -0
  84. package/dist/ai/pipeline.d.ts +20 -0
  85. package/dist/ai/pipeline.d.ts.map +1 -0
  86. package/dist/ai/pipeline.js +303 -0
  87. package/dist/ai/pipeline.js.map +1 -0
  88. package/dist/ai/prompts.d.ts +6 -0
  89. package/dist/ai/prompts.d.ts.map +1 -0
  90. package/dist/ai/prompts.js +49 -0
  91. package/dist/ai/prompts.js.map +1 -0
  92. package/dist/ai/providers.d.ts +63 -0
  93. package/dist/ai/providers.d.ts.map +1 -0
  94. package/dist/ai/providers.js +297 -0
  95. package/dist/ai/providers.js.map +1 -0
  96. package/dist/ai/refine-bridge.d.ts +5 -0
  97. package/dist/ai/refine-bridge.d.ts.map +1 -0
  98. package/dist/ai/refine-bridge.js +14 -0
  99. package/dist/ai/refine-bridge.js.map +1 -0
  100. package/dist/ai/registry.d.ts +12 -0
  101. package/dist/ai/registry.d.ts.map +1 -0
  102. package/dist/ai/registry.js +43 -0
  103. package/dist/ai/registry.js.map +1 -0
  104. package/dist/ai/resolve.d.ts +28 -0
  105. package/dist/ai/resolve.d.ts.map +1 -0
  106. package/dist/ai/resolve.js +83 -0
  107. package/dist/ai/resolve.js.map +1 -0
  108. package/dist/ai/schemas.d.ts +175 -0
  109. package/dist/ai/schemas.d.ts.map +1 -0
  110. package/dist/ai/schemas.js +199 -0
  111. package/dist/ai/schemas.js.map +1 -0
  112. package/dist/ai/types.d.ts +52 -0
  113. package/dist/ai/types.d.ts.map +1 -0
  114. package/dist/ai/types.js +8 -0
  115. package/dist/ai/types.js.map +1 -0
  116. package/dist/bin/dare.js +2 -0
  117. package/dist/bin/dare.js.map +1 -1
  118. package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
  119. package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
  120. package/dist/commands/__tests__/ai-command.test.js +68 -0
  121. package/dist/commands/__tests__/ai-command.test.js.map +1 -0
  122. package/dist/commands/__tests__/execute-agent.test.js +82 -0
  123. package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
  124. package/dist/commands/ai.d.ts +3 -0
  125. package/dist/commands/ai.d.ts.map +1 -0
  126. package/dist/commands/ai.js +141 -0
  127. package/dist/commands/ai.js.map +1 -0
  128. package/dist/commands/blueprint.d.ts.map +1 -1
  129. package/dist/commands/blueprint.js +17 -3
  130. package/dist/commands/blueprint.js.map +1 -1
  131. package/dist/commands/design.d.ts.map +1 -1
  132. package/dist/commands/design.js +21 -2
  133. package/dist/commands/design.js.map +1 -1
  134. package/dist/commands/discover.d.ts.map +1 -1
  135. package/dist/commands/discover.js +9 -1
  136. package/dist/commands/discover.js.map +1 -1
  137. package/dist/commands/dna.d.ts.map +1 -1
  138. package/dist/commands/dna.js +23 -3
  139. package/dist/commands/dna.js.map +1 -1
  140. package/dist/commands/execute.d.ts +11 -0
  141. package/dist/commands/execute.d.ts.map +1 -1
  142. package/dist/commands/execute.js +111 -4
  143. package/dist/commands/execute.js.map +1 -1
  144. package/dist/commands/init.d.ts.map +1 -1
  145. package/dist/commands/init.js +1 -0
  146. package/dist/commands/init.js.map +1 -1
  147. package/dist/commands/migrate.d.ts.map +1 -1
  148. package/dist/commands/migrate.js +14 -2
  149. package/dist/commands/migrate.js.map +1 -1
  150. package/dist/commands/patterns.d.ts.map +1 -1
  151. package/dist/commands/patterns.js +14 -2
  152. package/dist/commands/patterns.js.map +1 -1
  153. package/dist/commands/refine.d.ts.map +1 -1
  154. package/dist/commands/refine.js +23 -2
  155. package/dist/commands/refine.js.map +1 -1
  156. package/dist/commands/reverse.d.ts.map +1 -1
  157. package/dist/commands/reverse.js +28 -3
  158. package/dist/commands/reverse.js.map +1 -1
  159. package/dist/commands/review.d.ts.map +1 -1
  160. package/dist/commands/review.js +25 -3
  161. package/dist/commands/review.js.map +1 -1
  162. package/dist/core/types/project.d.ts +1 -1
  163. package/dist/core/types/project.d.ts.map +1 -1
  164. package/dist/dag-runner/run_dag.d.ts +1 -1
  165. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  166. package/dist/exec/safe-spawn.d.ts.map +1 -1
  167. package/dist/exec/safe-spawn.js +6 -1
  168. package/dist/exec/safe-spawn.js.map +1 -1
  169. package/dist/skills/bundled.d.ts +5 -0
  170. package/dist/skills/bundled.d.ts.map +1 -0
  171. package/dist/skills/bundled.js +34 -0
  172. package/dist/skills/bundled.js.map +1 -0
  173. package/dist/skills/commands/add.d.ts +1 -3
  174. package/dist/skills/commands/add.d.ts.map +1 -1
  175. package/dist/skills/commands/add.js +20 -3
  176. package/dist/skills/commands/add.js.map +1 -1
  177. package/dist/skills/tests/bundled.spec.d.ts +2 -0
  178. package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
  179. package/dist/skills/tests/bundled.spec.js +24 -0
  180. package/dist/skills/tests/bundled.spec.js.map +1 -0
  181. package/dist/types/UpdateManifest.types.d.ts +1 -1
  182. package/dist/types/UpdateManifest.types.d.ts.map +1 -1
  183. package/dist/utils/dag-converter.js +1 -1
  184. package/dist/utils/dag-converter.js.map +1 -1
  185. package/dist/utils/project-detector.d.ts +1 -0
  186. package/dist/utils/project-detector.d.ts.map +1 -1
  187. package/dist/utils/project-detector.js +8 -0
  188. package/dist/utils/project-detector.js.map +1 -1
  189. package/dist/utils/project-generator.d.ts +1 -1
  190. package/dist/utils/project-generator.d.ts.map +1 -1
  191. package/dist/utils/project-generator.js +23 -2
  192. package/dist/utils/project-generator.js.map +1 -1
  193. package/dist/utils/templates.d.ts +2 -0
  194. package/dist/utils/templates.d.ts.map +1 -1
  195. package/dist/utils/templates.js +74 -0
  196. package/dist/utils/templates.js.map +1 -1
  197. package/dist/verification/__tests__/safe-spawn.test.js +12 -0
  198. package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
  199. package/package.json +2 -1
  200. package/skills/dare-ax/generator.ts +325 -0
  201. package/skills/dare-ax/index.ts +19 -0
  202. package/skills/dare-ax/metrics.ts +352 -0
  203. package/skills/dare-ax/package-lock.json +1855 -0
  204. package/skills/dare-ax/package.json +50 -0
  205. package/skills/dare-ax/secret-detector.ts +123 -0
  206. package/skills/dare-ax/skill.yml +19 -0
  207. package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
  208. package/skills/dare-ax/tests/generator.spec.ts +193 -0
  209. package/skills/dare-ax/tests/metrics.spec.ts +394 -0
  210. package/skills/dare-ax/tests/validator.spec.ts +298 -0
  211. package/skills/dare-ax/tsconfig.json +18 -0
  212. package/skills/dare-ax/types.ts +79 -0
  213. package/skills/dare-ax/validator.ts +238 -0
  214. package/skills/dare-frontend-design/generator.ts +616 -0
  215. package/skills/dare-frontend-design/index.ts +25 -0
  216. package/skills/dare-frontend-design/linter.ts +227 -0
  217. package/skills/dare-frontend-design/metrics.ts +82 -0
  218. package/skills/dare-frontend-design/package-lock.json +1855 -0
  219. package/skills/dare-frontend-design/package.json +43 -0
  220. package/skills/dare-frontend-design/skill.yml +20 -0
  221. package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
  222. package/skills/dare-frontend-design/tsconfig.json +18 -0
  223. package/skills/dare-frontend-design/types.ts +62 -0
  224. package/skills/dare-layered-design/generator.ts +740 -0
  225. package/skills/dare-layered-design/index.ts +17 -0
  226. package/skills/dare-layered-design/linter.ts +462 -0
  227. package/skills/dare-layered-design/metrics.ts +409 -0
  228. package/skills/dare-layered-design/package-lock.json +1855 -0
  229. package/skills/dare-layered-design/package.json +50 -0
  230. package/skills/dare-layered-design/skill.yml +35 -0
  231. package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
  232. package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
  233. package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
  234. package/skills/dare-layered-design/tsconfig.json +18 -0
  235. package/skills/dare-layered-design/types.ts +48 -0
  236. package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
  237. package/skills/dare-llm-integration/index.ts +49 -0
  238. package/skills/dare-llm-integration/metrics.ts +107 -0
  239. package/skills/dare-llm-integration/package-lock.json +1855 -0
  240. package/skills/dare-llm-integration/package.json +49 -0
  241. package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
  242. package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
  243. package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
  244. package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
  245. package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
  246. package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
  247. package/skills/dare-llm-integration/skill.yml +23 -0
  248. package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
  249. package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
  250. package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
  251. package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
  252. package/skills/dare-llm-integration/tsconfig.json +23 -0
  253. package/skills/dare-llm-integration/types.ts +91 -0
  254. package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
  255. package/skills/dare-quality-telemetry/collect.ts +134 -0
  256. package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
  257. package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
  258. package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
  259. package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
  260. package/skills/dare-quality-telemetry/index.ts +18 -0
  261. package/skills/dare-quality-telemetry/metrics.ts +137 -0
  262. package/skills/dare-quality-telemetry/package-lock.json +1855 -0
  263. package/skills/dare-quality-telemetry/package.json +48 -0
  264. package/skills/dare-quality-telemetry/regression.ts +60 -0
  265. package/skills/dare-quality-telemetry/reporter.ts +132 -0
  266. package/skills/dare-quality-telemetry/skill.yml +18 -0
  267. package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
  268. package/skills/dare-quality-telemetry/tsconfig.json +19 -0
  269. package/skills/dare-quality-telemetry/types.ts +41 -0
  270. package/skills/dare-realtime/event_registry.ts +101 -0
  271. package/skills/dare-realtime/index.ts +30 -0
  272. package/skills/dare-realtime/metrics.ts +84 -0
  273. package/skills/dare-realtime/package-lock.json +1855 -0
  274. package/skills/dare-realtime/package.json +43 -0
  275. package/skills/dare-realtime/reconnect_strategy.ts +85 -0
  276. package/skills/dare-realtime/schema_validator.ts +80 -0
  277. package/skills/dare-realtime/skill.yml +21 -0
  278. package/skills/dare-realtime/subscription_manager.ts +106 -0
  279. package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
  280. package/skills/dare-realtime/tsconfig.json +18 -0
  281. package/skills/dare-realtime/types.ts +51 -0
  282. package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
  283. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
  284. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
  285. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
  286. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
  287. package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
  288. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
  289. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
  290. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
  291. package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
  292. package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
  293. package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
  294. package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
  295. package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
  296. package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
  297. package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
  298. package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
  299. package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
  300. package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
  301. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
  302. package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
  303. package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
  304. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
  305. package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
  306. package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
  307. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
  308. package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@dewtech/dare-realtime",
3
+ "version": "1.0.0",
4
+ "description": "dare-realtime — Real-time communication patterns skill for DARE Method v3.0",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "skill.yml"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^20.19.41",
26
+ "typescript": "^5.9.3",
27
+ "vitest": "^1.6.1"
28
+ },
29
+ "keywords": [
30
+ "dare",
31
+ "dare-method",
32
+ "dare-realtime",
33
+ "websocket",
34
+ "sse",
35
+ "pubsub",
36
+ "realtime"
37
+ ],
38
+ "author": "Dewtech Technologies",
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ }
43
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * dare-realtime — ReconnectStrategy
3
+ * Exponential backoff for WebSocket / SSE reconnection.
4
+ *
5
+ * Delays: attempt 0=1s, 1=2s, 2=4s, 3=8s, … capped at maxDelay (30s).
6
+ * License: MIT
7
+ */
8
+
9
+ export interface ReconnectStrategyConfig {
10
+ /** Initial delay in milliseconds. Default: 1000 (1s). */
11
+ initialDelayMs?: number;
12
+ /** Maximum delay in milliseconds. Default: 30000 (30s). */
13
+ maxDelayMs?: number;
14
+ /** Jitter factor (0–1) to randomize delay and avoid thundering herd. Default: 0 (no jitter). */
15
+ jitter?: number;
16
+ }
17
+
18
+ export class ReconnectStrategy {
19
+ private readonly initialDelayMs: number;
20
+ private readonly maxDelayMs: number;
21
+ private readonly jitter: number;
22
+ private _attempt: number = 0;
23
+
24
+ constructor(config: ReconnectStrategyConfig = {}) {
25
+ this.initialDelayMs = config.initialDelayMs ?? 1_000;
26
+ this.maxDelayMs = config.maxDelayMs ?? 30_000;
27
+ this.jitter = Math.min(1, Math.max(0, config.jitter ?? 0));
28
+ }
29
+
30
+ /**
31
+ * Get the delay in milliseconds for a given attempt number.
32
+ * Follows exponential backoff: initialDelay * 2^attempt, capped at maxDelay.
33
+ *
34
+ * @param attempt - Zero-based attempt count (0 = first reconnect)
35
+ */
36
+ getDelay(attempt: number): number {
37
+ if (attempt < 0) attempt = 0;
38
+ const base = this.initialDelayMs * Math.pow(2, attempt);
39
+ const capped = Math.min(base, this.maxDelayMs);
40
+
41
+ if (this.jitter > 0) {
42
+ const jitterAmount = capped * this.jitter * Math.random();
43
+ return Math.round(capped + jitterAmount);
44
+ }
45
+
46
+ return capped;
47
+ }
48
+
49
+ /**
50
+ * Get the delay for the next attempt (auto-incrementing internal counter).
51
+ */
52
+ nextDelay(): number {
53
+ const delay = this.getDelay(this._attempt);
54
+ this._attempt++;
55
+ return delay;
56
+ }
57
+
58
+ /**
59
+ * Reset the attempt counter back to 0 (call after a successful connection).
60
+ */
61
+ reset(): void {
62
+ this._attempt = 0;
63
+ }
64
+
65
+ /**
66
+ * Current attempt count.
67
+ */
68
+ get attempt(): number {
69
+ return this._attempt;
70
+ }
71
+
72
+ /**
73
+ * Configured initial delay in milliseconds.
74
+ */
75
+ get initialDelay(): number {
76
+ return this.initialDelayMs;
77
+ }
78
+
79
+ /**
80
+ * Configured maximum delay in milliseconds.
81
+ */
82
+ get maxDelay(): number {
83
+ return this.maxDelayMs;
84
+ }
85
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * dare-realtime — SchemaValidator
3
+ * Validates a real-time event payload against a JSON Schema definition.
4
+ * Zero external dependencies.
5
+ * License: MIT
6
+ */
7
+
8
+ import type { ValidationResult, ValidationError, EventSchema } from './types.js';
9
+
10
+ export class SchemaValidator {
11
+ /**
12
+ * Validate a payload against a schema.
13
+ */
14
+ validate(payload: unknown, schema: EventSchema): ValidationResult {
15
+ const errors: ValidationError[] = [];
16
+ validateValue(payload, schema, '$', errors);
17
+ return { ok: errors.length === 0, errors };
18
+ }
19
+ }
20
+
21
+ function validateValue(
22
+ value: unknown,
23
+ schema: EventSchema,
24
+ path: string,
25
+ errors: ValidationError[]
26
+ ): void {
27
+ // Type check
28
+ if (schema.type !== undefined) {
29
+ const actualType = getType(value);
30
+ if (schema.type !== actualType) {
31
+ errors.push({
32
+ field: path,
33
+ message: `Expected type "${schema.type}", got "${actualType}"`,
34
+ value,
35
+ });
36
+ return; // No further checks if type is wrong
37
+ }
38
+ }
39
+
40
+ // Object checks
41
+ if (schema.type === 'object' && typeof value === 'object' && value !== null && !Array.isArray(value)) {
42
+ const obj = value as Record<string, unknown>;
43
+
44
+ // Required fields
45
+ if (schema.required) {
46
+ for (const field of schema.required) {
47
+ if (!(field in obj) || obj[field] === undefined || obj[field] === null) {
48
+ errors.push({
49
+ field: `${path}.${field}`,
50
+ message: `Required field "${field}" is missing`,
51
+ });
52
+ }
53
+ }
54
+ }
55
+
56
+ // Properties
57
+ if (schema.properties) {
58
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
59
+ if (key in obj) {
60
+ validateValue(obj[key], propSchema, `${path}.${key}`, errors);
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ // Array checks
67
+ if (schema.type === 'array' && Array.isArray(value)) {
68
+ if (schema.items) {
69
+ (value as unknown[]).forEach((item, i) => {
70
+ validateValue(item, schema.items!, `${path}[${i}]`, errors);
71
+ });
72
+ }
73
+ }
74
+ }
75
+
76
+ function getType(value: unknown): string {
77
+ if (value === null) return 'null';
78
+ if (Array.isArray(value)) return 'array';
79
+ return typeof value;
80
+ }
@@ -0,0 +1,21 @@
1
+ name: dare-realtime
2
+ version: 1.0.0
3
+ license: MIT
4
+ description: >
5
+ Skill transversal DARE para real-time communication. Fornece schema validation
6
+ de eventos, registro central de tipos de evento, estratégia de reconexão com
7
+ exponential backoff, e gerenciamento de subscriptions com limpeza garantida
8
+ (zero ghost listeners).
9
+ author: Dewtech Technologies
10
+ metrics:
11
+ - id: M-01
12
+ description: 100% de event types com JSON Schema definido
13
+ - id: M-02
14
+ description: 100% de subscriptions autorizadas
15
+ - id: M-03
16
+ description: 0 ghost listeners após desconexão
17
+ - id: M-04
18
+ description: Estratégia de reconexão configurada
19
+ transports:
20
+ - WebSocket
21
+ - SSE
@@ -0,0 +1,106 @@
1
+ /**
2
+ * dare-realtime — SubscriptionManager
3
+ * Manages subscriptions per channel with guaranteed cleanup (zero ghost listeners).
4
+ * License: MIT
5
+ */
6
+
7
+ type Handler<T = unknown> = (payload: T) => void;
8
+
9
+ interface Subscription<T = unknown> {
10
+ handler: Handler<T>;
11
+ id: string;
12
+ }
13
+
14
+ export class SubscriptionManager {
15
+ private readonly channels: Map<string, Subscription[]> = new Map();
16
+ private nextId = 0;
17
+
18
+ /**
19
+ * Subscribe to a channel.
20
+ * @returns Unsubscribe function — call it to remove this specific handler.
21
+ */
22
+ subscribe<T = unknown>(channel: string, handler: Handler<T>): () => void {
23
+ if (!this.channels.has(channel)) {
24
+ this.channels.set(channel, []);
25
+ }
26
+
27
+ const id = String(this.nextId++);
28
+ const subscription: Subscription<T> = { handler: handler as Handler, id };
29
+ this.channels.get(channel)!.push(subscription as Subscription);
30
+
31
+ // Return unsubscribe function
32
+ return () => {
33
+ const subs = this.channels.get(channel);
34
+ if (!subs) return;
35
+ const idx = subs.findIndex((s) => s.id === id);
36
+ if (idx >= 0) {
37
+ subs.splice(idx, 1);
38
+ // Clean up empty channel entry to prevent memory accumulation
39
+ if (subs.length === 0) {
40
+ this.channels.delete(channel);
41
+ }
42
+ }
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Remove all handlers for a channel.
48
+ * Guarantees zero ghost listeners after this call.
49
+ */
50
+ unsubscribeAll(channel: string): void {
51
+ this.channels.delete(channel);
52
+ }
53
+
54
+ /**
55
+ * Publish a payload to all handlers of a channel.
56
+ */
57
+ publish<T = unknown>(channel: string, payload: T): void {
58
+ const subs = this.channels.get(channel);
59
+ if (!subs || subs.length === 0) return;
60
+
61
+ // Iterate over a snapshot to avoid issues if a handler removes itself
62
+ const snapshot = [...subs];
63
+ for (const sub of snapshot) {
64
+ sub.handler(payload);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Get all channels that have at least one active subscription.
70
+ */
71
+ getActiveChannels(): string[] {
72
+ return Array.from(this.channels.keys());
73
+ }
74
+
75
+ /**
76
+ * Count active subscriptions for a specific channel.
77
+ */
78
+ countSubscriptions(channel: string): number {
79
+ return this.channels.get(channel)?.length ?? 0;
80
+ }
81
+
82
+ /**
83
+ * Total subscriptions across all channels.
84
+ */
85
+ get totalSubscriptions(): number {
86
+ let count = 0;
87
+ for (const subs of this.channels.values()) {
88
+ count += subs.length;
89
+ }
90
+ return count;
91
+ }
92
+
93
+ /**
94
+ * True if no active subscriptions exist (no ghost listeners).
95
+ */
96
+ get isEmpty(): boolean {
97
+ return this.channels.size === 0;
98
+ }
99
+
100
+ /**
101
+ * Remove all subscriptions across all channels.
102
+ */
103
+ clear(): void {
104
+ this.channels.clear();
105
+ }
106
+ }