@dewtech/dare-cli 3.11.0 → 3.13.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 (316) hide show
  1. package/README.md +2 -0
  2. package/dist/__tests__/cli-only-invariants.test.d.ts +2 -0
  3. package/dist/__tests__/cli-only-invariants.test.d.ts.map +1 -0
  4. package/dist/__tests__/cli-only-invariants.test.js +100 -0
  5. package/dist/__tests__/cli-only-invariants.test.js.map +1 -0
  6. package/dist/__tests__/cli-only-regression.test.d.ts +2 -0
  7. package/dist/__tests__/cli-only-regression.test.d.ts.map +1 -0
  8. package/dist/__tests__/cli-only-regression.test.js +29 -0
  9. package/dist/__tests__/cli-only-regression.test.js.map +1 -0
  10. package/dist/__tests__/ensure-skills.test.js +5 -0
  11. package/dist/__tests__/ensure-skills.test.js.map +1 -1
  12. package/dist/__tests__/ide-command-parity.test.js +1 -0
  13. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  14. package/dist/__tests__/project-generator.test.js +17 -0
  15. package/dist/__tests__/project-generator.test.js.map +1 -1
  16. package/dist/__tests__/reverse-facts.test.js +1 -0
  17. package/dist/__tests__/reverse-facts.test.js.map +1 -1
  18. package/dist/__tests__/terminal-parity-regression.test.d.ts +2 -0
  19. package/dist/__tests__/terminal-parity-regression.test.d.ts.map +1 -0
  20. package/dist/__tests__/terminal-parity-regression.test.js +116 -0
  21. package/dist/__tests__/terminal-parity-regression.test.js.map +1 -0
  22. package/dist/__tests__/terminal-parity.test.d.ts +2 -0
  23. package/dist/__tests__/terminal-parity.test.d.ts.map +1 -0
  24. package/dist/__tests__/terminal-parity.test.js +81 -0
  25. package/dist/__tests__/terminal-parity.test.js.map +1 -0
  26. package/dist/agent/__tests__/antigravity-driver.test.d.ts +2 -0
  27. package/dist/agent/__tests__/antigravity-driver.test.d.ts.map +1 -0
  28. package/dist/agent/__tests__/antigravity-driver.test.js +52 -0
  29. package/dist/agent/__tests__/antigravity-driver.test.js.map +1 -0
  30. package/dist/agent/__tests__/codex-driver.test.d.ts +2 -0
  31. package/dist/agent/__tests__/codex-driver.test.d.ts.map +1 -0
  32. package/dist/agent/__tests__/codex-driver.test.js +68 -0
  33. package/dist/agent/__tests__/codex-driver.test.js.map +1 -0
  34. package/dist/agent/__tests__/cursor-driver.test.d.ts +2 -0
  35. package/dist/agent/__tests__/cursor-driver.test.d.ts.map +1 -0
  36. package/dist/agent/__tests__/cursor-driver.test.js +52 -0
  37. package/dist/agent/__tests__/cursor-driver.test.js.map +1 -0
  38. package/dist/agent/driver.d.ts +1 -1
  39. package/dist/agent/driver.d.ts.map +1 -1
  40. package/dist/agent/drivers/antigravity.d.ts +8 -0
  41. package/dist/agent/drivers/antigravity.d.ts.map +1 -0
  42. package/dist/agent/drivers/antigravity.js +99 -0
  43. package/dist/agent/drivers/antigravity.js.map +1 -0
  44. package/dist/agent/drivers/codex.d.ts +12 -0
  45. package/dist/agent/drivers/codex.d.ts.map +1 -0
  46. package/dist/agent/drivers/codex.js +137 -0
  47. package/dist/agent/drivers/codex.js.map +1 -0
  48. package/dist/agent/drivers/cursor.d.ts +8 -0
  49. package/dist/agent/drivers/cursor.d.ts.map +1 -0
  50. package/dist/agent/drivers/cursor.js +99 -0
  51. package/dist/agent/drivers/cursor.js.map +1 -0
  52. package/dist/ai/__tests__/ai-core.test.d.ts +2 -0
  53. package/dist/ai/__tests__/ai-core.test.d.ts.map +1 -0
  54. package/dist/ai/__tests__/ai-core.test.js +41 -0
  55. package/dist/ai/__tests__/ai-core.test.js.map +1 -0
  56. package/dist/ai/__tests__/parity.test.d.ts +2 -0
  57. package/dist/ai/__tests__/parity.test.d.ts.map +1 -0
  58. package/dist/ai/__tests__/parity.test.js +36 -0
  59. package/dist/ai/__tests__/parity.test.js.map +1 -0
  60. package/dist/ai/__tests__/pipeline.test.d.ts +2 -0
  61. package/dist/ai/__tests__/pipeline.test.d.ts.map +1 -0
  62. package/dist/ai/__tests__/pipeline.test.js +147 -0
  63. package/dist/ai/__tests__/pipeline.test.js.map +1 -0
  64. package/dist/ai/__tests__/refine-bridge.test.d.ts +2 -0
  65. package/dist/ai/__tests__/refine-bridge.test.d.ts.map +1 -0
  66. package/dist/ai/__tests__/refine-bridge.test.js +17 -0
  67. package/dist/ai/__tests__/refine-bridge.test.js.map +1 -0
  68. package/dist/ai/__tests__/resolve.test.d.ts +2 -0
  69. package/dist/ai/__tests__/resolve.test.d.ts.map +1 -0
  70. package/dist/ai/__tests__/resolve.test.js +42 -0
  71. package/dist/ai/__tests__/resolve.test.js.map +1 -0
  72. package/dist/ai/capabilities.d.ts +3 -0
  73. package/dist/ai/capabilities.d.ts.map +1 -0
  74. package/dist/ai/capabilities.js +11 -0
  75. package/dist/ai/capabilities.js.map +1 -0
  76. package/dist/ai/command-options.d.ts +10 -0
  77. package/dist/ai/command-options.d.ts.map +1 -0
  78. package/dist/ai/command-options.js +15 -0
  79. package/dist/ai/command-options.js.map +1 -0
  80. package/dist/ai/config.d.ts +27 -0
  81. package/dist/ai/config.d.ts.map +1 -0
  82. package/dist/ai/config.js +89 -0
  83. package/dist/ai/config.js.map +1 -0
  84. package/dist/ai/parity.d.ts +13 -0
  85. package/dist/ai/parity.d.ts.map +1 -0
  86. package/dist/ai/parity.js +87 -0
  87. package/dist/ai/parity.js.map +1 -0
  88. package/dist/ai/parse-json-output.d.ts +5 -0
  89. package/dist/ai/parse-json-output.d.ts.map +1 -0
  90. package/dist/ai/parse-json-output.js +25 -0
  91. package/dist/ai/parse-json-output.js.map +1 -0
  92. package/dist/ai/pipeline.d.ts +20 -0
  93. package/dist/ai/pipeline.d.ts.map +1 -0
  94. package/dist/ai/pipeline.js +303 -0
  95. package/dist/ai/pipeline.js.map +1 -0
  96. package/dist/ai/prompts.d.ts +6 -0
  97. package/dist/ai/prompts.d.ts.map +1 -0
  98. package/dist/ai/prompts.js +49 -0
  99. package/dist/ai/prompts.js.map +1 -0
  100. package/dist/ai/providers.d.ts +63 -0
  101. package/dist/ai/providers.d.ts.map +1 -0
  102. package/dist/ai/providers.js +297 -0
  103. package/dist/ai/providers.js.map +1 -0
  104. package/dist/ai/refine-bridge.d.ts +5 -0
  105. package/dist/ai/refine-bridge.d.ts.map +1 -0
  106. package/dist/ai/refine-bridge.js +14 -0
  107. package/dist/ai/refine-bridge.js.map +1 -0
  108. package/dist/ai/registry.d.ts +12 -0
  109. package/dist/ai/registry.d.ts.map +1 -0
  110. package/dist/ai/registry.js +43 -0
  111. package/dist/ai/registry.js.map +1 -0
  112. package/dist/ai/resolve.d.ts +28 -0
  113. package/dist/ai/resolve.d.ts.map +1 -0
  114. package/dist/ai/resolve.js +83 -0
  115. package/dist/ai/resolve.js.map +1 -0
  116. package/dist/ai/schemas.d.ts +175 -0
  117. package/dist/ai/schemas.d.ts.map +1 -0
  118. package/dist/ai/schemas.js +199 -0
  119. package/dist/ai/schemas.js.map +1 -0
  120. package/dist/ai/types.d.ts +52 -0
  121. package/dist/ai/types.d.ts.map +1 -0
  122. package/dist/ai/types.js +8 -0
  123. package/dist/ai/types.js.map +1 -0
  124. package/dist/bin/dare.js +2 -0
  125. package/dist/bin/dare.js.map +1 -1
  126. package/dist/commands/__tests__/ai-command.test.d.ts +2 -0
  127. package/dist/commands/__tests__/ai-command.test.d.ts.map +1 -0
  128. package/dist/commands/__tests__/ai-command.test.js +68 -0
  129. package/dist/commands/__tests__/ai-command.test.js.map +1 -0
  130. package/dist/commands/__tests__/execute-agent.test.js +82 -0
  131. package/dist/commands/__tests__/execute-agent.test.js.map +1 -1
  132. package/dist/commands/ai.d.ts +3 -0
  133. package/dist/commands/ai.d.ts.map +1 -0
  134. package/dist/commands/ai.js +141 -0
  135. package/dist/commands/ai.js.map +1 -0
  136. package/dist/commands/blueprint.d.ts.map +1 -1
  137. package/dist/commands/blueprint.js +17 -3
  138. package/dist/commands/blueprint.js.map +1 -1
  139. package/dist/commands/design.d.ts.map +1 -1
  140. package/dist/commands/design.js +21 -2
  141. package/dist/commands/design.js.map +1 -1
  142. package/dist/commands/discover.d.ts.map +1 -1
  143. package/dist/commands/discover.js +9 -1
  144. package/dist/commands/discover.js.map +1 -1
  145. package/dist/commands/dna.d.ts.map +1 -1
  146. package/dist/commands/dna.js +23 -3
  147. package/dist/commands/dna.js.map +1 -1
  148. package/dist/commands/execute.d.ts +11 -0
  149. package/dist/commands/execute.d.ts.map +1 -1
  150. package/dist/commands/execute.js +111 -4
  151. package/dist/commands/execute.js.map +1 -1
  152. package/dist/commands/init.d.ts.map +1 -1
  153. package/dist/commands/init.js +1 -0
  154. package/dist/commands/init.js.map +1 -1
  155. package/dist/commands/migrate.d.ts.map +1 -1
  156. package/dist/commands/migrate.js +14 -2
  157. package/dist/commands/migrate.js.map +1 -1
  158. package/dist/commands/patterns.d.ts.map +1 -1
  159. package/dist/commands/patterns.js +14 -2
  160. package/dist/commands/patterns.js.map +1 -1
  161. package/dist/commands/refine.d.ts.map +1 -1
  162. package/dist/commands/refine.js +23 -2
  163. package/dist/commands/refine.js.map +1 -1
  164. package/dist/commands/reverse.d.ts.map +1 -1
  165. package/dist/commands/reverse.js +28 -3
  166. package/dist/commands/reverse.js.map +1 -1
  167. package/dist/commands/review.d.ts.map +1 -1
  168. package/dist/commands/review.js +25 -3
  169. package/dist/commands/review.js.map +1 -1
  170. package/dist/core/types/project.d.ts +1 -1
  171. package/dist/core/types/project.d.ts.map +1 -1
  172. package/dist/dag-runner/run_dag.d.ts +1 -1
  173. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  174. package/dist/exec/safe-spawn.d.ts.map +1 -1
  175. package/dist/exec/safe-spawn.js +6 -1
  176. package/dist/exec/safe-spawn.js.map +1 -1
  177. package/dist/skills/bundled.d.ts +5 -0
  178. package/dist/skills/bundled.d.ts.map +1 -0
  179. package/dist/skills/bundled.js +34 -0
  180. package/dist/skills/bundled.js.map +1 -0
  181. package/dist/skills/commands/add.d.ts +1 -3
  182. package/dist/skills/commands/add.d.ts.map +1 -1
  183. package/dist/skills/commands/add.js +20 -3
  184. package/dist/skills/commands/add.js.map +1 -1
  185. package/dist/skills/tests/bundled.spec.d.ts +2 -0
  186. package/dist/skills/tests/bundled.spec.d.ts.map +1 -0
  187. package/dist/skills/tests/bundled.spec.js +24 -0
  188. package/dist/skills/tests/bundled.spec.js.map +1 -0
  189. package/dist/types/UpdateManifest.types.d.ts +1 -1
  190. package/dist/types/UpdateManifest.types.d.ts.map +1 -1
  191. package/dist/utils/dag-converter.js +1 -1
  192. package/dist/utils/dag-converter.js.map +1 -1
  193. package/dist/utils/project-detector.d.ts +1 -0
  194. package/dist/utils/project-detector.d.ts.map +1 -1
  195. package/dist/utils/project-detector.js +8 -0
  196. package/dist/utils/project-detector.js.map +1 -1
  197. package/dist/utils/project-generator.d.ts +1 -1
  198. package/dist/utils/project-generator.d.ts.map +1 -1
  199. package/dist/utils/project-generator.js +23 -2
  200. package/dist/utils/project-generator.js.map +1 -1
  201. package/dist/utils/templates.d.ts +2 -0
  202. package/dist/utils/templates.d.ts.map +1 -1
  203. package/dist/utils/templates.js +74 -0
  204. package/dist/utils/templates.js.map +1 -1
  205. package/dist/verification/__tests__/safe-spawn.test.js +12 -0
  206. package/dist/verification/__tests__/safe-spawn.test.js.map +1 -1
  207. package/package.json +2 -1
  208. package/skills/dare-ax/generator.ts +325 -0
  209. package/skills/dare-ax/index.ts +19 -0
  210. package/skills/dare-ax/metrics.ts +352 -0
  211. package/skills/dare-ax/package-lock.json +1855 -0
  212. package/skills/dare-ax/package.json +50 -0
  213. package/skills/dare-ax/secret-detector.ts +123 -0
  214. package/skills/dare-ax/skill.yml +19 -0
  215. package/skills/dare-ax/templates/llms.txt.jinja2 +80 -0
  216. package/skills/dare-ax/tests/generator.spec.ts +193 -0
  217. package/skills/dare-ax/tests/metrics.spec.ts +394 -0
  218. package/skills/dare-ax/tests/validator.spec.ts +298 -0
  219. package/skills/dare-ax/tsconfig.json +18 -0
  220. package/skills/dare-ax/types.ts +79 -0
  221. package/skills/dare-ax/validator.ts +238 -0
  222. package/skills/dare-frontend-design/generator.ts +616 -0
  223. package/skills/dare-frontend-design/index.ts +25 -0
  224. package/skills/dare-frontend-design/linter.ts +227 -0
  225. package/skills/dare-frontend-design/metrics.ts +82 -0
  226. package/skills/dare-frontend-design/package-lock.json +1855 -0
  227. package/skills/dare-frontend-design/package.json +43 -0
  228. package/skills/dare-frontend-design/skill.yml +20 -0
  229. package/skills/dare-frontend-design/tests/frontend_design.spec.ts +435 -0
  230. package/skills/dare-frontend-design/tsconfig.json +18 -0
  231. package/skills/dare-frontend-design/types.ts +62 -0
  232. package/skills/dare-layered-design/generator.ts +740 -0
  233. package/skills/dare-layered-design/index.ts +17 -0
  234. package/skills/dare-layered-design/linter.ts +462 -0
  235. package/skills/dare-layered-design/metrics.ts +409 -0
  236. package/skills/dare-layered-design/package-lock.json +1855 -0
  237. package/skills/dare-layered-design/package.json +50 -0
  238. package/skills/dare-layered-design/skill.yml +35 -0
  239. package/skills/dare-layered-design/tests/generator.spec.ts +156 -0
  240. package/skills/dare-layered-design/tests/linter.spec.ts +255 -0
  241. package/skills/dare-layered-design/tests/metrics.spec.ts +286 -0
  242. package/skills/dare-layered-design/tsconfig.json +18 -0
  243. package/skills/dare-layered-design/types.ts +48 -0
  244. package/skills/dare-llm-integration/cache/llm_cache.ts +122 -0
  245. package/skills/dare-llm-integration/index.ts +49 -0
  246. package/skills/dare-llm-integration/metrics.ts +107 -0
  247. package/skills/dare-llm-integration/package-lock.json +1855 -0
  248. package/skills/dare-llm-integration/package.json +49 -0
  249. package/skills/dare-llm-integration/prompts/prompt_loader.ts +258 -0
  250. package/skills/dare-llm-integration/providers/anthropic_provider.ts +159 -0
  251. package/skills/dare-llm-integration/providers/dummy_provider.ts +113 -0
  252. package/skills/dare-llm-integration/providers/llm_provider.ts +6 -0
  253. package/skills/dare-llm-integration/providers/openai_provider.ts +215 -0
  254. package/skills/dare-llm-integration/rate_limit/token_bucket.ts +86 -0
  255. package/skills/dare-llm-integration/skill.yml +23 -0
  256. package/skills/dare-llm-integration/tests/fixtures/greet_v1.jinja2 +1 -0
  257. package/skills/dare-llm-integration/tests/fixtures/summarize_v1.jinja2 +1 -0
  258. package/skills/dare-llm-integration/tests/fixtures/summarize_v2.jinja2 +3 -0
  259. package/skills/dare-llm-integration/tests/llm_integration.spec.ts +657 -0
  260. package/skills/dare-llm-integration/tsconfig.json +23 -0
  261. package/skills/dare-llm-integration/types.ts +91 -0
  262. package/skills/dare-llm-integration/validators/output_validator.ts +200 -0
  263. package/skills/dare-quality-telemetry/collect.ts +134 -0
  264. package/skills/dare-quality-telemetry/collectors/dare_ax_collector.ts +301 -0
  265. package/skills/dare-quality-telemetry/collectors/dare_layered_design_collector.ts +406 -0
  266. package/skills/dare-quality-telemetry/collectors/index.ts +24 -0
  267. package/skills/dare-quality-telemetry/github_actions_template.ts +25 -0
  268. package/skills/dare-quality-telemetry/index.ts +18 -0
  269. package/skills/dare-quality-telemetry/metrics.ts +137 -0
  270. package/skills/dare-quality-telemetry/package-lock.json +1855 -0
  271. package/skills/dare-quality-telemetry/package.json +48 -0
  272. package/skills/dare-quality-telemetry/regression.ts +60 -0
  273. package/skills/dare-quality-telemetry/reporter.ts +132 -0
  274. package/skills/dare-quality-telemetry/skill.yml +18 -0
  275. package/skills/dare-quality-telemetry/tests/quality_telemetry.spec.ts +885 -0
  276. package/skills/dare-quality-telemetry/tsconfig.json +19 -0
  277. package/skills/dare-quality-telemetry/types.ts +41 -0
  278. package/skills/dare-realtime/event_registry.ts +101 -0
  279. package/skills/dare-realtime/index.ts +30 -0
  280. package/skills/dare-realtime/metrics.ts +84 -0
  281. package/skills/dare-realtime/package-lock.json +1855 -0
  282. package/skills/dare-realtime/package.json +43 -0
  283. package/skills/dare-realtime/reconnect_strategy.ts +85 -0
  284. package/skills/dare-realtime/schema_validator.ts +80 -0
  285. package/skills/dare-realtime/skill.yml +21 -0
  286. package/skills/dare-realtime/subscription_manager.ts +106 -0
  287. package/skills/dare-realtime/tests/realtime.spec.ts +482 -0
  288. package/skills/dare-realtime/tsconfig.json +18 -0
  289. package/skills/dare-realtime/types.ts +51 -0
  290. package/templates/ide/antigravity/.agents/skills/dare-ai/SKILL.md +17 -0
  291. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +2 -0
  292. package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +2 -0
  293. package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +3 -0
  294. package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +3 -0
  295. package/templates/ide/antigravity/.agents/skills/dare-patterns/SKILL.md +3 -0
  296. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +3 -0
  297. package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +3 -0
  298. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +3 -0
  299. package/templates/ide/claude/.claude/commands/dare-ai.md +17 -0
  300. package/templates/ide/claude/.claude/commands/dare-blueprint.md +2 -0
  301. package/templates/ide/claude/.claude/commands/dare-design.md +2 -0
  302. package/templates/ide/claude/.claude/commands/dare-dna.md +2 -0
  303. package/templates/ide/claude/.claude/commands/dare-migrate.md +2 -0
  304. package/templates/ide/claude/.claude/commands/dare-patterns.md +3 -0
  305. package/templates/ide/claude/.claude/commands/dare-refine.md +3 -0
  306. package/templates/ide/claude/.claude/commands/dare-reverse.md +2 -0
  307. package/templates/ide/claude/.claude/commands/dare-review.md +3 -0
  308. package/templates/ide/cursor/.cursor/commands/dare-ai.md +17 -0
  309. package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +3 -0
  310. package/templates/ide/cursor/.cursor/commands/dare-design.md +3 -0
  311. package/templates/ide/cursor/.cursor/commands/dare-dna.md +2 -0
  312. package/templates/ide/cursor/.cursor/commands/dare-migrate.md +2 -0
  313. package/templates/ide/cursor/.cursor/commands/dare-patterns.md +3 -0
  314. package/templates/ide/cursor/.cursor/commands/dare-refine.md +3 -0
  315. package/templates/ide/cursor/.cursor/commands/dare-reverse.md +2 -0
  316. package/templates/ide/cursor/.cursor/commands/dare-review.md +3 -0
@@ -0,0 +1,394 @@
1
+ /**
2
+ * dare-ax — metrics tests (M-01 to M-04)
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import path from 'path';
9
+ import { DareAxMetrics } from '../metrics.js';
10
+
11
+ /** A valid llms.txt for M-01 tests */
12
+ const VALID_LLMS_TXT = `# llms.txt — Project Context for AI Agents
13
+
14
+ ## Project Overview
15
+ A test project demonstrating DARE Method layered architecture.
16
+
17
+ ## Tech Stack
18
+ - Language: TypeScript
19
+ - Framework: NestJS
20
+ - Database: Postgres
21
+
22
+ ## Architecture
23
+ 4-layer architecture: Handlers, Services, Repositories, Models.
24
+ Dependency flows downward only: Handler → Service → Repository → Model.
25
+
26
+ ## Directory Structure
27
+ \`\`\`
28
+ src/
29
+ ├── handlers/
30
+ ├── services/
31
+ ├── repositories/
32
+ └── models/
33
+ \`\`\`
34
+
35
+ ## Key Endpoints
36
+ - GET /health — Health check
37
+ - GET /api/v1/users — List users
38
+
39
+ ## Important Files
40
+ - config.json — Configuration
41
+
42
+ ## Getting Started
43
+ \`\`\`bash
44
+ make dev
45
+ \`\`\`
46
+
47
+ ## Rate Limits
48
+ - Public endpoints: 100 req/min per IP
49
+
50
+ ## Security Notes
51
+ - Input validated in handlers
52
+
53
+ ## For AI Agents
54
+ - OpenAPI: GET /openapi.json
55
+ - CLI: ./app --json
56
+ - No secrets here
57
+ `;
58
+
59
+ describe('DareAxMetrics', () => {
60
+ let tmpDir: string;
61
+ let metrics: DareAxMetrics;
62
+
63
+ beforeEach(() => {
64
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dare-ax-metrics-test-'));
65
+ metrics = new DareAxMetrics();
66
+ });
67
+
68
+ afterEach(() => {
69
+ fs.rmSync(tmpDir, { recursive: true, force: true });
70
+ });
71
+
72
+ // ── M-01 ──────────────────────────────────────────────────────────────
73
+
74
+ describe('M-01: llms.txt valid', () => {
75
+ it('passes when llms.txt exists and is valid', () => {
76
+ fs.writeFileSync(path.join(tmpDir, 'llms.txt'), VALID_LLMS_TXT, 'utf-8');
77
+
78
+ const result = metrics.collectM01(tmpDir);
79
+
80
+ expect(result.id).toBe('M-01');
81
+ expect(result.pass).toBe(true);
82
+ });
83
+
84
+ it('fails when llms.txt does not exist', () => {
85
+ const result = metrics.collectM01(tmpDir);
86
+
87
+ expect(result.id).toBe('M-01');
88
+ expect(result.pass).toBe(false);
89
+ expect(result.detail).toContain('not found');
90
+ });
91
+
92
+ it('fails when llms.txt is missing required sections', () => {
93
+ fs.writeFileSync(
94
+ path.join(tmpDir, 'llms.txt'),
95
+ '# llms.txt\n\nJust a comment, no sections.\n',
96
+ 'utf-8'
97
+ );
98
+
99
+ const result = metrics.collectM01(tmpDir);
100
+
101
+ expect(result.pass).toBe(false);
102
+ expect(result.detail).toContain('Validation failed');
103
+ });
104
+
105
+ it('fails when llms.txt contains a secret', () => {
106
+ const content = VALID_LLMS_TXT + '\naws_key=' + 'AKIA' + 'IOSFODNN7EXAMPLE\n';
107
+ fs.writeFileSync(path.join(tmpDir, 'llms.txt'), content, 'utf-8');
108
+
109
+ const result = metrics.collectM01(tmpDir);
110
+
111
+ expect(result.pass).toBe(false);
112
+ expect(result.detail!.toLowerCase()).toContain('secret');
113
+ });
114
+ });
115
+
116
+ // ── M-02 ──────────────────────────────────────────────────────────────
117
+
118
+ describe('M-02: openapi.json exists', () => {
119
+ it('passes when openapi.json is at project root', () => {
120
+ fs.writeFileSync(
121
+ path.join(tmpDir, 'openapi.json'),
122
+ '{"openapi":"3.1.0"}',
123
+ 'utf-8'
124
+ );
125
+
126
+ const result = metrics.collectM02(tmpDir);
127
+
128
+ expect(result.id).toBe('M-02');
129
+ expect(result.pass).toBe(true);
130
+ expect(result.detail).toContain('openapi.json');
131
+ });
132
+
133
+ it('passes when openapi.json is in public/', () => {
134
+ const publicDir = path.join(tmpDir, 'public');
135
+ fs.mkdirSync(publicDir);
136
+ fs.writeFileSync(
137
+ path.join(publicDir, 'openapi.json'),
138
+ '{"openapi":"3.1.0"}',
139
+ 'utf-8'
140
+ );
141
+
142
+ const result = metrics.collectM02(tmpDir);
143
+
144
+ expect(result.pass).toBe(true);
145
+ // Normalize path separators for Windows/Unix compatibility
146
+ expect(result.detail?.replace(/\\/g, '/')).toContain('public/openapi.json');
147
+ });
148
+
149
+ it('passes when openapi.yaml is at project root', () => {
150
+ fs.writeFileSync(path.join(tmpDir, 'openapi.yaml'), 'openapi: "3.1.0"', 'utf-8');
151
+
152
+ const result = metrics.collectM02(tmpDir);
153
+
154
+ expect(result.pass).toBe(true);
155
+ });
156
+
157
+ it('fails when no openapi file found', () => {
158
+ const result = metrics.collectM02(tmpDir);
159
+
160
+ expect(result.id).toBe('M-02');
161
+ expect(result.pass).toBe(false);
162
+ expect(result.detail).toContain('No openapi');
163
+ });
164
+ });
165
+
166
+ // ── M-03 ──────────────────────────────────────────────────────────────
167
+
168
+ describe('M-03: CLI supports --json', () => {
169
+ it('passes when --json flag found in src/', () => {
170
+ const srcDir = path.join(tmpDir, 'src');
171
+ fs.mkdirSync(srcDir);
172
+ fs.writeFileSync(
173
+ path.join(srcDir, 'cli.ts'),
174
+ `
175
+ import { Command } from 'commander';
176
+ const cmd = new Command();
177
+ cmd.option('--json', 'Output as JSON');
178
+ cmd.parse(process.argv);
179
+ `,
180
+ 'utf-8'
181
+ );
182
+
183
+ const result = metrics.collectM03(tmpDir);
184
+
185
+ expect(result.id).toBe('M-03');
186
+ expect(result.pass).toBe(true);
187
+ expect(result.detail).toContain('--json');
188
+ });
189
+
190
+ it('passes when --json found in bin/', () => {
191
+ const binDir = path.join(tmpDir, 'bin');
192
+ fs.mkdirSync(binDir);
193
+ fs.writeFileSync(
194
+ path.join(binDir, 'dare.ts'),
195
+ 'program.option("--json", "JSON output");\n',
196
+ 'utf-8'
197
+ );
198
+
199
+ const result = metrics.collectM03(tmpDir);
200
+
201
+ expect(result.pass).toBe(true);
202
+ });
203
+
204
+ it('passes when --json found nested in src/commands/', () => {
205
+ const dir = path.join(tmpDir, 'src', 'commands');
206
+ fs.mkdirSync(dir, { recursive: true });
207
+ fs.writeFileSync(
208
+ path.join(dir, 'init.ts'),
209
+ '.option("--json", "Output results as JSON")\n',
210
+ 'utf-8'
211
+ );
212
+
213
+ const result = metrics.collectM03(tmpDir);
214
+
215
+ expect(result.pass).toBe(true);
216
+ });
217
+
218
+ it('fails when no --json flag in any source file', () => {
219
+ const srcDir = path.join(tmpDir, 'src');
220
+ fs.mkdirSync(srcDir);
221
+ fs.writeFileSync(
222
+ path.join(srcDir, 'cli.ts'),
223
+ 'program.option("--verbose", "Verbose output");\n',
224
+ 'utf-8'
225
+ );
226
+
227
+ const result = metrics.collectM03(tmpDir);
228
+
229
+ expect(result.id).toBe('M-03');
230
+ expect(result.pass).toBe(false);
231
+ expect(result.detail).toContain('--json');
232
+ });
233
+
234
+ it('fails when project has no src/ or bin/ directories', () => {
235
+ const result = metrics.collectM03(tmpDir);
236
+
237
+ expect(result.pass).toBe(false);
238
+ });
239
+ });
240
+
241
+ // ── M-04 ──────────────────────────────────────────────────────────────
242
+
243
+ describe('M-04: Rate limit configuration detected', () => {
244
+ it('passes when express-rate-limit in package.json dependencies', () => {
245
+ const pkg = {
246
+ name: 'test',
247
+ dependencies: { 'express-rate-limit': '^7.0.0' },
248
+ };
249
+ fs.writeFileSync(
250
+ path.join(tmpDir, 'package.json'),
251
+ JSON.stringify(pkg),
252
+ 'utf-8'
253
+ );
254
+
255
+ const result = metrics.collectM04(tmpDir);
256
+
257
+ expect(result.id).toBe('M-04');
258
+ expect(result.pass).toBe(true);
259
+ expect(result.detail).toContain('express-rate-limit');
260
+ });
261
+
262
+ it('passes when @nestjs/throttler in package.json', () => {
263
+ const pkg = {
264
+ name: 'test',
265
+ dependencies: { '@nestjs/throttler': '^5.0.0' },
266
+ };
267
+ fs.writeFileSync(
268
+ path.join(tmpDir, 'package.json'),
269
+ JSON.stringify(pkg),
270
+ 'utf-8'
271
+ );
272
+
273
+ const result = metrics.collectM04(tmpDir);
274
+
275
+ expect(result.pass).toBe(true);
276
+ expect(result.detail).toContain('nestjs/throttler');
277
+ });
278
+
279
+ it('passes when rack-attack in Gemfile', () => {
280
+ fs.writeFileSync(
281
+ path.join(tmpDir, 'Gemfile'),
282
+ 'gem "rack-attack"\n',
283
+ 'utf-8'
284
+ );
285
+
286
+ const result = metrics.collectM04(tmpDir);
287
+
288
+ expect(result.pass).toBe(true);
289
+ expect(result.detail).toContain('rack-attack');
290
+ });
291
+
292
+ it('passes when tower-governor in Cargo.toml', () => {
293
+ fs.writeFileSync(
294
+ path.join(tmpDir, 'Cargo.toml'),
295
+ '[dependencies]\ntower-governor = "0.2"\n',
296
+ 'utf-8'
297
+ );
298
+
299
+ const result = metrics.collectM04(tmpDir);
300
+
301
+ expect(result.pass).toBe(true);
302
+ expect(result.detail).toContain('tower-governor');
303
+ });
304
+
305
+ it('passes when rate_limit pattern found in source', () => {
306
+ const srcDir = path.join(tmpDir, 'src');
307
+ fs.mkdirSync(srcDir);
308
+ fs.writeFileSync(
309
+ path.join(srcDir, 'middleware.ts'),
310
+ 'app.use(rateLimitMiddleware({ windowMs: 60000, max: 100 }));\n',
311
+ 'utf-8'
312
+ );
313
+
314
+ const result = metrics.collectM04(tmpDir);
315
+
316
+ expect(result.pass).toBe(true);
317
+ });
318
+
319
+ it('fails when no rate limit library or pattern found', () => {
320
+ const pkg = {
321
+ name: 'test',
322
+ dependencies: { express: '^4.0.0', nestjs: '^10.0.0' },
323
+ };
324
+ fs.writeFileSync(
325
+ path.join(tmpDir, 'package.json'),
326
+ JSON.stringify(pkg),
327
+ 'utf-8'
328
+ );
329
+
330
+ const result = metrics.collectM04(tmpDir);
331
+
332
+ expect(result.id).toBe('M-04');
333
+ expect(result.pass).toBe(false);
334
+ expect(result.detail).toContain('No rate limit');
335
+ });
336
+
337
+ it('fails when no manifests exist at all', () => {
338
+ const result = metrics.collectM04(tmpDir);
339
+
340
+ expect(result.pass).toBe(false);
341
+ });
342
+ });
343
+
344
+ // ── collect() (all metrics) ────────────────────────────────────────────
345
+
346
+ describe('collect()', () => {
347
+ it('returns array of 4 MetricResults', () => {
348
+ const results = metrics.collect(tmpDir);
349
+
350
+ expect(results).toHaveLength(4);
351
+ expect(results.map((r) => r.id)).toEqual(['M-01', 'M-02', 'M-03', 'M-04']);
352
+ });
353
+
354
+ it('all pass when project has all required assets', () => {
355
+ // Setup a project that satisfies all metrics
356
+ fs.writeFileSync(path.join(tmpDir, 'llms.txt'), VALID_LLMS_TXT, 'utf-8');
357
+ fs.writeFileSync(
358
+ path.join(tmpDir, 'openapi.json'),
359
+ '{"openapi":"3.1.0"}',
360
+ 'utf-8'
361
+ );
362
+ const srcDir = path.join(tmpDir, 'src');
363
+ fs.mkdirSync(srcDir);
364
+ fs.writeFileSync(
365
+ path.join(srcDir, 'cli.ts'),
366
+ 'cmd.option("--json", "JSON output");\n',
367
+ 'utf-8'
368
+ );
369
+ const pkg = {
370
+ name: 'test',
371
+ dependencies: { 'express-rate-limit': '^7.0.0' },
372
+ };
373
+ fs.writeFileSync(
374
+ path.join(tmpDir, 'package.json'),
375
+ JSON.stringify(pkg),
376
+ 'utf-8'
377
+ );
378
+
379
+ const results = metrics.collect(tmpDir);
380
+
381
+ for (const r of results) {
382
+ expect(r.pass, `Expected ${r.id} to pass, got: ${r.detail}`).toBe(true);
383
+ }
384
+ });
385
+
386
+ it('all fail when project directory is empty', () => {
387
+ const results = metrics.collect(tmpDir);
388
+
389
+ for (const r of results) {
390
+ expect(r.pass, `Expected ${r.id} to fail`).toBe(false);
391
+ }
392
+ });
393
+ });
394
+ });
@@ -0,0 +1,298 @@
1
+ /**
2
+ * dare-ax — validator tests
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import path from 'path';
9
+ import { DareAxValidator } from '../validator.js';
10
+
11
+ /** A complete, valid llms.txt for use as baseline in tests */
12
+ const VALID_LLMS_TXT = `# llms.txt — Project Context for AI Agents
13
+
14
+ ## Project Overview
15
+ This is a test API project that provides user management endpoints.
16
+ It follows the DARE Method layered architecture pattern.
17
+
18
+ ## Tech Stack
19
+ - Language: TypeScript
20
+ - Framework: NestJS
21
+ - Database: Postgres
22
+ - Key Dependencies: nestjs, typeorm, pg, class-validator, rxjs
23
+
24
+ ## Architecture
25
+ The project uses a 4-layer architecture: Handlers (controllers), Services,
26
+ Repositories, and Models. Each layer has a single responsibility. Handlers
27
+ never call Repositories directly — always through Services.
28
+
29
+ ## Directory Structure
30
+ \`\`\`
31
+ src/
32
+ ├── handlers/
33
+ ├── services/
34
+ ├── repositories/
35
+ └── models/
36
+ \`\`\`
37
+
38
+ ## Key Endpoints
39
+ - GET /health — Health check
40
+ - GET /api/v1/users — List users
41
+ - POST /api/v1/users — Create user
42
+
43
+ ## Important Files
44
+ - config.json — Application configuration
45
+ - docker-compose.yml — Local dev environment
46
+
47
+ ## Getting Started
48
+ \`\`\`bash
49
+ make dev
50
+ \`\`\`
51
+
52
+ ## Rate Limits
53
+ - Public endpoints: 100 req/min per IP
54
+ - Auth endpoints: 10 req/min per IP
55
+
56
+ ## Security Notes
57
+ - All input validated in handlers
58
+ - SQL via parameterized queries
59
+ - See .env.example
60
+
61
+ ## For AI Agents
62
+ - OpenAPI: GET /openapi.json
63
+ - CLI: ./project-cli --help, ./project-cli --json
64
+ - Architecture: Handler → Service → Repository → Model
65
+ `;
66
+
67
+ describe('DareAxValidator', () => {
68
+ let tmpDir: string;
69
+ let validator: DareAxValidator;
70
+
71
+ beforeEach(() => {
72
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dare-ax-validator-test-'));
73
+ validator = new DareAxValidator();
74
+ });
75
+
76
+ afterEach(() => {
77
+ fs.rmSync(tmpDir, { recursive: true, force: true });
78
+ });
79
+
80
+ // ── File-based validate() ───────────────────────────────────────────────
81
+
82
+ describe('validate(path)', () => {
83
+ it('returns valid=false when file does not exist', () => {
84
+ const result = validator.validate(path.join(tmpDir, 'non-existent.txt'));
85
+
86
+ expect(result.valid).toBe(false);
87
+ expect(result.errors.some((e) => e.code === 'E_FILE_NOT_FOUND')).toBe(true);
88
+ });
89
+
90
+ it('returns valid=false for empty file', () => {
91
+ const filePath = path.join(tmpDir, 'llms.txt');
92
+ fs.writeFileSync(filePath, '', 'utf-8');
93
+
94
+ const result = validator.validate(filePath);
95
+
96
+ expect(result.valid).toBe(false);
97
+ expect(result.errors.some((e) => e.code === 'E_EMPTY_FILE')).toBe(true);
98
+ });
99
+
100
+ it('returns valid=true for a complete llms.txt', () => {
101
+ const filePath = path.join(tmpDir, 'llms.txt');
102
+ fs.writeFileSync(filePath, VALID_LLMS_TXT, 'utf-8');
103
+
104
+ const result = validator.validate(filePath);
105
+
106
+ expect(result.valid).toBe(true);
107
+ expect(result.errors).toHaveLength(0);
108
+ });
109
+
110
+ it('returns error for missing "Project Overview" section', () => {
111
+ const content = VALID_LLMS_TXT.replace('## Project Overview', '## Old Overview');
112
+ const filePath = path.join(tmpDir, 'llms.txt');
113
+ fs.writeFileSync(filePath, content, 'utf-8');
114
+
115
+ const result = validator.validate(filePath);
116
+
117
+ expect(result.valid).toBe(false);
118
+ expect(result.errors.some((e) => e.message.includes('Project Overview'))).toBe(true);
119
+ });
120
+
121
+ it('returns error for missing "Tech Stack" section', () => {
122
+ const content = VALID_LLMS_TXT.replace('## Tech Stack', '## Stack');
123
+ const filePath = path.join(tmpDir, 'llms.txt');
124
+ fs.writeFileSync(filePath, content, 'utf-8');
125
+
126
+ const result = validator.validate(filePath);
127
+
128
+ expect(result.valid).toBe(false);
129
+ expect(result.errors.some((e) => e.message.includes('Tech Stack'))).toBe(true);
130
+ });
131
+
132
+ it('returns error for missing "Architecture" section', () => {
133
+ const content = VALID_LLMS_TXT.replace('## Architecture', '## Arch');
134
+ const filePath = path.join(tmpDir, 'llms.txt');
135
+ fs.writeFileSync(filePath, content, 'utf-8');
136
+
137
+ const result = validator.validate(filePath);
138
+
139
+ expect(result.valid).toBe(false);
140
+ expect(result.errors.some((e) => e.message.includes('Architecture'))).toBe(true);
141
+ });
142
+
143
+ it('returns error for missing "Key Endpoints" section', () => {
144
+ const content = VALID_LLMS_TXT.replace('## Key Endpoints', '## Endpoints');
145
+ const filePath = path.join(tmpDir, 'llms.txt');
146
+ fs.writeFileSync(filePath, content, 'utf-8');
147
+
148
+ const result = validator.validate(filePath);
149
+
150
+ expect(result.valid).toBe(false);
151
+ expect(result.errors.some((e) => e.message.includes('Key Endpoints'))).toBe(true);
152
+ });
153
+
154
+ it('returns error for missing "For AI Agents" section', () => {
155
+ const content = VALID_LLMS_TXT.replace('## For AI Agents', '## For Agents');
156
+ const filePath = path.join(tmpDir, 'llms.txt');
157
+ fs.writeFileSync(filePath, content, 'utf-8');
158
+
159
+ const result = validator.validate(filePath);
160
+
161
+ expect(result.valid).toBe(false);
162
+ expect(result.errors.some((e) => e.message.includes('For AI Agents'))).toBe(true);
163
+ });
164
+
165
+ it('returns error for all 5 required sections missing', () => {
166
+ const filePath = path.join(tmpDir, 'llms.txt');
167
+ fs.writeFileSync(filePath, '# Just a comment\n\nNo sections here at all.\n', 'utf-8');
168
+
169
+ const result = validator.validate(filePath);
170
+
171
+ expect(result.valid).toBe(false);
172
+ // Should have errors for all 5 required sections
173
+ const missingErrors = result.errors.filter((e) => e.code === 'E_MISSING_SECTION');
174
+ expect(missingErrors).toHaveLength(5);
175
+ });
176
+
177
+ it('returns error when AWS key detected', () => {
178
+ const content = VALID_LLMS_TXT + '\n' + 'AKIA' + 'IOSFODNN7EXAMPLE' + '\n';
179
+ const filePath = path.join(tmpDir, 'llms.txt');
180
+ fs.writeFileSync(filePath, content, 'utf-8');
181
+
182
+ const result = validator.validate(filePath);
183
+
184
+ expect(result.valid).toBe(false);
185
+ expect(result.errors.some((e) => e.code === 'E_SECRET_DETECTED')).toBe(true);
186
+ expect(result.errors.some((e) => e.message.includes('AWS'))).toBe(true);
187
+ });
188
+
189
+ it('returns error when Stripe secret key detected', () => {
190
+ const content =
191
+ VALID_LLMS_TXT + '\nstripe_key=' + 'sk_li' + 've_abcdefghijklmnopqrstuvwx\n';
192
+ const filePath = path.join(tmpDir, 'llms.txt');
193
+ fs.writeFileSync(filePath, content, 'utf-8');
194
+
195
+ const result = validator.validate(filePath);
196
+
197
+ expect(result.valid).toBe(false);
198
+ expect(result.errors.some((e) => e.code === 'E_SECRET_DETECTED')).toBe(true);
199
+ });
200
+
201
+ it('returns error when password assignment detected', () => {
202
+ const content = VALID_LLMS_TXT + '\ndatabase_password="s3cr3tP4ss"\n';
203
+ const filePath = path.join(tmpDir, 'llms.txt');
204
+ fs.writeFileSync(filePath, content, 'utf-8');
205
+
206
+ const result = validator.validate(filePath);
207
+
208
+ expect(result.valid).toBe(false);
209
+ expect(result.errors.some((e) => e.code === 'E_SECRET_DETECTED')).toBe(true);
210
+ });
211
+
212
+ it('returns warning for missing recommended sections', () => {
213
+ // Remove recommended sections but keep required
214
+ const contentWithoutRecommended = `# llms.txt
215
+
216
+ ## Project Overview
217
+ This is a test project with only required sections.
218
+
219
+ ## Tech Stack
220
+ - Language: TypeScript
221
+ - Framework: NestJS
222
+ - Database: Postgres
223
+
224
+ ## Architecture
225
+ 3-layer architecture with handlers, services, and repositories.
226
+
227
+ ## Key Endpoints
228
+ - GET /health — Health check
229
+ - GET /api/v1/users — List users
230
+
231
+ ## For AI Agents
232
+ - OpenAPI: GET /openapi.json
233
+ - CLI: ./app --json
234
+ `;
235
+ const filePath = path.join(tmpDir, 'llms.txt');
236
+ fs.writeFileSync(filePath, contentWithoutRecommended, 'utf-8');
237
+
238
+ const result = validator.validate(filePath);
239
+
240
+ expect(result.valid).toBe(true); // warnings don't make it invalid
241
+ expect(result.warnings.length).toBeGreaterThan(0);
242
+ expect(
243
+ result.warnings.some((w) => w.code === 'W_MISSING_RECOMMENDED_SECTION')
244
+ ).toBe(true);
245
+ });
246
+
247
+ it('warns when "For AI Agents" section does not mention OpenAPI', () => {
248
+ const content = VALID_LLMS_TXT.replace(
249
+ '- OpenAPI: GET /openapi.json\n- CLI: ./project-cli --help, ./project-cli --json',
250
+ '- CLI: ./project-cli --json'
251
+ );
252
+ const filePath = path.join(tmpDir, 'llms.txt');
253
+ fs.writeFileSync(filePath, content, 'utf-8');
254
+
255
+ const result = validator.validate(filePath);
256
+
257
+ expect(
258
+ result.warnings.some((w) => w.code === 'W_MISSING_OPENAPI_REFERENCE')
259
+ ).toBe(true);
260
+ });
261
+ });
262
+
263
+ // ── Content-based validateContent() ────────────────────────────────────
264
+
265
+ describe('validateContent(content)', () => {
266
+ it('validates string content without writing to disk', () => {
267
+ const result = validator.validateContent(VALID_LLMS_TXT);
268
+
269
+ expect(result.valid).toBe(true);
270
+ expect(result.errors).toHaveLength(0);
271
+ });
272
+
273
+ it('returns error for empty string', () => {
274
+ const result = validator.validateContent('');
275
+
276
+ expect(result.valid).toBe(false);
277
+ expect(result.errors.some((e) => e.code === 'E_EMPTY_FILE')).toBe(true);
278
+ });
279
+
280
+ it('returns error for OpenAI API key', () => {
281
+ const content =
282
+ VALID_LLMS_TXT + '\nopenai_key=sk-' + 'a'.repeat(48) + '\n';
283
+ const result = validator.validateContent(content);
284
+
285
+ expect(result.valid).toBe(false);
286
+ expect(result.errors.some((e) => e.code === 'E_SECRET_DETECTED')).toBe(true);
287
+ });
288
+
289
+ it('ignores Jinja2 template placeholders as secrets', () => {
290
+ // Template variables like {{ api_key }} should not be flagged as secrets
291
+ const content = VALID_LLMS_TXT + '\n- API key: {{ api_key }}\n';
292
+ const result = validator.validateContent(content);
293
+
294
+ // Template placeholders are not actual secrets
295
+ expect(result.errors.filter((e) => e.code === 'E_SECRET_DETECTED')).toHaveLength(0);
296
+ });
297
+ });
298
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": ".",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true
9
+ },
10
+ "include": [
11
+ "*.ts",
12
+ "tests/**/*.ts"
13
+ ],
14
+ "exclude": [
15
+ "node_modules",
16
+ "dist"
17
+ ]
18
+ }