@coralai/sps-cli 0.55.13 → 0.56.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 (428) hide show
  1. package/dist/commands/cardMarkComplete.d.ts.map +1 -1
  2. package/dist/commands/cardMarkComplete.js +6 -3
  3. package/dist/commands/cardMarkComplete.js.map +1 -1
  4. package/dist/commands/projectInit.d.ts +18 -16
  5. package/dist/commands/projectInit.d.ts.map +1 -1
  6. package/dist/commands/projectInit.js +59 -186
  7. package/dist/commands/projectInit.js.map +1 -1
  8. package/dist/commands/skillCommand.js +7 -4
  9. package/dist/commands/skillCommand.js.map +1 -1
  10. package/dist/commands/tick.d.ts +2 -20
  11. package/dist/commands/tick.d.ts.map +1 -1
  12. package/dist/commands/tick.js +58 -1
  13. package/dist/commands/tick.js.map +1 -1
  14. package/dist/console/index.d.ts.map +1 -1
  15. package/dist/console/index.js +4 -0
  16. package/dist/console/index.js.map +1 -1
  17. package/dist/console/routes/chat.d.ts.map +1 -1
  18. package/dist/console/routes/chat.js +121 -0
  19. package/dist/console/routes/chat.js.map +1 -1
  20. package/dist/console/routes/projects.d.ts +0 -6
  21. package/dist/console/routes/projects.d.ts.map +1 -1
  22. package/dist/console/routes/projects.js +11 -2
  23. package/dist/console/routes/projects.js.map +1 -1
  24. package/dist/console/routes/providers.d.ts +10 -0
  25. package/dist/console/routes/providers.d.ts.map +1 -0
  26. package/dist/console/routes/providers.js +63 -0
  27. package/dist/console/routes/providers.js.map +1 -0
  28. package/dist/console/routes/smartarrange.d.ts +4 -0
  29. package/dist/console/routes/smartarrange.d.ts.map +1 -0
  30. package/dist/console/routes/smartarrange.js +107 -0
  31. package/dist/console/routes/smartarrange.js.map +1 -0
  32. package/dist/console/routes/system.d.ts.map +1 -1
  33. package/dist/console/routes/system.js +28 -0
  34. package/dist/console/routes/system.js.map +1 -1
  35. package/dist/console/routes/workers.d.ts.map +1 -1
  36. package/dist/console/routes/workers.js +36 -4
  37. package/dist/console/routes/workers.js.map +1 -1
  38. package/dist/console-assets/assets/index-CWkYVI5d.js +600 -0
  39. package/dist/console-assets/assets/index-CnUBHNsN.css +10 -0
  40. package/dist/console-assets/index.html +2 -2
  41. package/dist/core/agents/AcpBackend.d.ts +24 -0
  42. package/dist/core/agents/AcpBackend.d.ts.map +1 -0
  43. package/dist/core/agents/AcpBackend.js +86 -0
  44. package/dist/core/agents/AcpBackend.js.map +1 -0
  45. package/dist/core/agents/AgentBackend.d.ts +53 -0
  46. package/dist/core/agents/AgentBackend.d.ts.map +1 -0
  47. package/dist/core/agents/AgentBackend.js +18 -0
  48. package/dist/core/agents/AgentBackend.js.map +1 -0
  49. package/dist/core/agents/ClaudeAcpBackend.d.ts +13 -0
  50. package/dist/core/agents/ClaudeAcpBackend.d.ts.map +1 -0
  51. package/dist/core/agents/ClaudeAcpBackend.js +14 -0
  52. package/dist/core/agents/ClaudeAcpBackend.js.map +1 -0
  53. package/dist/core/agents/ClaudeSdkBackend.d.ts +26 -0
  54. package/dist/core/agents/ClaudeSdkBackend.d.ts.map +1 -0
  55. package/dist/core/agents/ClaudeSdkBackend.js +102 -0
  56. package/dist/core/agents/ClaudeSdkBackend.js.map +1 -0
  57. package/dist/core/agents/CodexAppServerBackend.d.ts +33 -0
  58. package/dist/core/agents/CodexAppServerBackend.d.ts.map +1 -0
  59. package/dist/core/agents/CodexAppServerBackend.js +168 -0
  60. package/dist/core/agents/CodexAppServerBackend.js.map +1 -0
  61. package/dist/core/agents/OpenAiAgentBackend.d.ts +39 -0
  62. package/dist/core/agents/OpenAiAgentBackend.d.ts.map +1 -0
  63. package/dist/core/agents/OpenAiAgentBackend.js +132 -0
  64. package/dist/core/agents/OpenAiAgentBackend.js.map +1 -0
  65. package/dist/core/agents/agentsMd.d.ts +2 -0
  66. package/dist/core/agents/agentsMd.d.ts.map +1 -0
  67. package/dist/core/agents/agentsMd.js +22 -0
  68. package/dist/core/agents/agentsMd.js.map +1 -0
  69. package/dist/core/agents/localTracing.d.ts +3 -0
  70. package/dist/core/agents/localTracing.d.ts.map +1 -0
  71. package/dist/core/agents/localTracing.js +42 -0
  72. package/dist/core/agents/localTracing.js.map +1 -0
  73. package/dist/core/agents/resolveBackend.d.ts +26 -0
  74. package/dist/core/agents/resolveBackend.d.ts.map +1 -0
  75. package/dist/core/agents/resolveBackend.js +27 -0
  76. package/dist/core/agents/resolveBackend.js.map +1 -0
  77. package/dist/core/agents/workerOutputSink.d.ts +4 -0
  78. package/dist/core/agents/workerOutputSink.d.ts.map +1 -0
  79. package/dist/core/agents/workerOutputSink.js +39 -0
  80. package/dist/core/agents/workerOutputSink.js.map +1 -0
  81. package/dist/core/config.d.ts +6 -0
  82. package/dist/core/config.d.ts.map +1 -1
  83. package/dist/core/config.js +4 -0
  84. package/dist/core/config.js.map +1 -1
  85. package/dist/core/intel/RuntimeSession.d.ts +16 -0
  86. package/dist/core/intel/RuntimeSession.d.ts.map +1 -0
  87. package/dist/core/intel/RuntimeSession.js +89 -0
  88. package/dist/core/intel/RuntimeSession.js.map +1 -0
  89. package/dist/core/intel/agentsConfig.d.ts +20 -0
  90. package/dist/core/intel/agentsConfig.d.ts.map +1 -0
  91. package/dist/core/intel/agentsConfig.js +68 -0
  92. package/dist/core/intel/agentsConfig.js.map +1 -0
  93. package/dist/core/intel/planStore.d.ts +23 -0
  94. package/dist/core/intel/planStore.d.ts.map +1 -0
  95. package/dist/core/intel/planStore.js +67 -0
  96. package/dist/core/intel/planStore.js.map +1 -0
  97. package/dist/core/intel/types.d.ts +86 -0
  98. package/dist/core/intel/types.d.ts.map +1 -0
  99. package/dist/core/intel/types.js +8 -0
  100. package/dist/core/intel/types.js.map +1 -0
  101. package/dist/core/memoryIngest.d.ts +18 -0
  102. package/dist/core/memoryIngest.d.ts.map +1 -0
  103. package/dist/core/memoryIngest.js +56 -0
  104. package/dist/core/memoryIngest.js.map +1 -0
  105. package/dist/core/memoryProvider.d.ts +63 -0
  106. package/dist/core/memoryProvider.d.ts.map +1 -0
  107. package/dist/core/memoryProvider.js +205 -0
  108. package/dist/core/memoryProvider.js.map +1 -0
  109. package/dist/core/skillStore.d.ts.map +1 -1
  110. package/dist/core/skillStore.js +2 -1
  111. package/dist/core/skillStore.js.map +1 -1
  112. package/dist/core/skills/SkillsManager.d.ts +38 -0
  113. package/dist/core/skills/SkillsManager.d.ts.map +1 -0
  114. package/dist/core/skills/SkillsManager.js +231 -0
  115. package/dist/core/skills/SkillsManager.js.map +1 -0
  116. package/dist/core/skills/distribution.d.ts +64 -0
  117. package/dist/core/skills/distribution.d.ts.map +1 -0
  118. package/dist/core/skills/distribution.js +269 -0
  119. package/dist/core/skills/distribution.js.map +1 -0
  120. package/dist/core/skills/index.d.ts +13 -0
  121. package/dist/core/skills/index.d.ts.map +1 -0
  122. package/dist/core/skills/index.js +13 -0
  123. package/dist/core/skills/index.js.map +1 -0
  124. package/dist/core/skills/types.d.ts +44 -0
  125. package/dist/core/skills/types.d.ts.map +1 -0
  126. package/dist/core/skills/types.js +9 -0
  127. package/dist/core/skills/types.js.map +1 -0
  128. package/dist/core/taskPrompts.d.ts +0 -12
  129. package/dist/core/taskPrompts.d.ts.map +1 -1
  130. package/dist/core/taskPrompts.js +0 -14
  131. package/dist/core/taskPrompts.js.map +1 -1
  132. package/dist/core/transcriptIngest.d.ts +37 -0
  133. package/dist/core/transcriptIngest.d.ts.map +1 -0
  134. package/dist/core/transcriptIngest.js +137 -0
  135. package/dist/core/transcriptIngest.js.map +1 -0
  136. package/dist/core/wiki/types.d.ts +282 -745
  137. package/dist/core/wiki/types.d.ts.map +1 -1
  138. package/dist/core/wiki/types.js +1 -1
  139. package/dist/core/wiki/types.js.map +1 -1
  140. package/dist/engines/SmartArrangeEngine.d.ts +75 -0
  141. package/dist/engines/SmartArrangeEngine.d.ts.map +1 -0
  142. package/dist/engines/SmartArrangeEngine.js +112 -0
  143. package/dist/engines/SmartArrangeEngine.js.map +1 -0
  144. package/dist/engines/StageEngine.d.ts +3 -17
  145. package/dist/engines/StageEngine.d.ts.map +1 -1
  146. package/dist/engines/StageEngine.js +13 -91
  147. package/dist/engines/StageEngine.js.map +1 -1
  148. package/dist/engines/smartarrange/AcpWorkerExec.d.ts +35 -0
  149. package/dist/engines/smartarrange/AcpWorkerExec.d.ts.map +1 -0
  150. package/dist/engines/smartarrange/AcpWorkerExec.js +71 -0
  151. package/dist/engines/smartarrange/AcpWorkerExec.js.map +1 -0
  152. package/dist/engines/smartarrange/cardSink.d.ts +29 -0
  153. package/dist/engines/smartarrange/cardSink.d.ts.map +1 -0
  154. package/dist/engines/smartarrange/cardSink.js +43 -0
  155. package/dist/engines/smartarrange/cardSink.js.map +1 -0
  156. package/dist/engines/smartarrange/runner.d.ts +24 -0
  157. package/dist/engines/smartarrange/runner.d.ts.map +1 -0
  158. package/dist/engines/smartarrange/runner.js +116 -0
  159. package/dist/engines/smartarrange/runner.js.map +1 -0
  160. package/dist/engines/smartarrange/screenshot.d.ts +5 -0
  161. package/dist/engines/smartarrange/screenshot.d.ts.map +1 -0
  162. package/dist/engines/smartarrange/screenshot.js +117 -0
  163. package/dist/engines/smartarrange/screenshot.js.map +1 -0
  164. package/dist/main.js +127 -92
  165. package/dist/main.js.map +1 -1
  166. package/dist/manager/worker-manager-impl.d.ts.map +1 -1
  167. package/dist/manager/worker-manager-impl.js +7 -0
  168. package/dist/manager/worker-manager-impl.js.map +1 -1
  169. package/dist/providers/LLMClient.d.ts +32 -0
  170. package/dist/providers/LLMClient.d.ts.map +1 -0
  171. package/dist/providers/LLMClient.js +108 -0
  172. package/dist/providers/LLMClient.js.map +1 -0
  173. package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -1
  174. package/dist/providers/MarkdownTaskBackend.js +3 -2
  175. package/dist/providers/MarkdownTaskBackend.js.map +1 -1
  176. package/dist/providers/llm/chatTools.d.ts +11 -0
  177. package/dist/providers/llm/chatTools.d.ts.map +1 -0
  178. package/dist/providers/llm/chatTools.js +57 -0
  179. package/dist/providers/llm/chatTools.js.map +1 -0
  180. package/dist/providers/llm/codexAuth.d.ts +8 -0
  181. package/dist/providers/llm/codexAuth.d.ts.map +1 -0
  182. package/dist/providers/llm/codexAuth.js +57 -0
  183. package/dist/providers/llm/codexAuth.js.map +1 -0
  184. package/dist/providers/llm/codexModel.d.ts +14 -0
  185. package/dist/providers/llm/codexModel.d.ts.map +1 -0
  186. package/dist/providers/llm/codexModel.js +96 -0
  187. package/dist/providers/llm/codexModel.js.map +1 -0
  188. package/dist/providers/llm/localSubscription.d.ts +15 -0
  189. package/dist/providers/llm/localSubscription.d.ts.map +1 -0
  190. package/dist/providers/llm/localSubscription.js +66 -0
  191. package/dist/providers/llm/localSubscription.js.map +1 -0
  192. package/dist/providers/llm/modelFactory.d.ts +14 -0
  193. package/dist/providers/llm/modelFactory.d.ts.map +1 -0
  194. package/dist/providers/llm/modelFactory.js +22 -0
  195. package/dist/providers/llm/modelFactory.js.map +1 -0
  196. package/dist/providers/llm/monitorSkills.d.ts +6 -0
  197. package/dist/providers/llm/monitorSkills.d.ts.map +1 -0
  198. package/dist/providers/llm/monitorSkills.js +37 -0
  199. package/dist/providers/llm/monitorSkills.js.map +1 -0
  200. package/dist/providers/llm/probeTools.d.ts +7 -0
  201. package/dist/providers/llm/probeTools.d.ts.map +1 -0
  202. package/dist/providers/llm/probeTools.js +84 -0
  203. package/dist/providers/llm/probeTools.js.map +1 -0
  204. package/dist/providers/llm/providers.d.ts +26 -0
  205. package/dist/providers/llm/providers.d.ts.map +1 -0
  206. package/dist/providers/llm/providers.js +68 -0
  207. package/dist/providers/llm/providers.js.map +1 -0
  208. package/dist/providers/llm/skillTools.d.ts +4 -0
  209. package/dist/providers/llm/skillTools.d.ts.map +1 -0
  210. package/dist/providers/llm/skillTools.js +42 -0
  211. package/dist/providers/llm/skillTools.js.map +1 -0
  212. package/dist/providers/llm/workerTools.d.ts +9 -0
  213. package/dist/providers/llm/workerTools.d.ts.map +1 -0
  214. package/dist/providers/llm/workerTools.js +111 -0
  215. package/dist/providers/llm/workerTools.js.map +1 -0
  216. package/dist/providers/mcp/spsMcpServer.d.ts +15 -0
  217. package/dist/providers/mcp/spsMcpServer.d.ts.map +1 -0
  218. package/dist/providers/mcp/spsMcpServer.js +67 -0
  219. package/dist/providers/mcp/spsMcpServer.js.map +1 -0
  220. package/dist/providers/mcp/spsMcpStdio.d.ts +2 -0
  221. package/dist/providers/mcp/spsMcpStdio.d.ts.map +1 -0
  222. package/dist/providers/mcp/spsMcpStdio.js +32 -0
  223. package/dist/providers/mcp/spsMcpStdio.js.map +1 -0
  224. package/dist/providers/mcp/spsMcpStdioConfig.d.ts +11 -0
  225. package/dist/providers/mcp/spsMcpStdioConfig.d.ts.map +1 -0
  226. package/dist/providers/mcp/spsMcpStdioConfig.js +19 -0
  227. package/dist/providers/mcp/spsMcpStdioConfig.js.map +1 -0
  228. package/dist/server.d.ts +23 -0
  229. package/dist/server.d.ts.map +1 -1
  230. package/dist/server.js +23 -0
  231. package/dist/server.js.map +1 -1
  232. package/dist/services/ChatService.d.ts +8 -0
  233. package/dist/services/ChatService.d.ts.map +1 -1
  234. package/dist/services/ChatService.js +2 -0
  235. package/dist/services/ChatService.js.map +1 -1
  236. package/dist/services/LogService.d.ts +1 -1
  237. package/dist/services/LogService.d.ts.map +1 -1
  238. package/dist/services/LogService.js +3 -2
  239. package/dist/services/LogService.js.map +1 -1
  240. package/dist/services/ProjectService.d.ts +12 -2
  241. package/dist/services/ProjectService.d.ts.map +1 -1
  242. package/dist/services/ProjectService.js +1 -0
  243. package/dist/services/ProjectService.js.map +1 -1
  244. package/dist/services/SkillService.js +11 -13
  245. package/dist/services/SkillService.js.map +1 -1
  246. package/dist/services/SmartArrangeService.d.ts +12 -0
  247. package/dist/services/SmartArrangeService.d.ts.map +1 -0
  248. package/dist/services/SmartArrangeService.js +37 -0
  249. package/dist/services/SmartArrangeService.js.map +1 -0
  250. package/dist/services/SystemService.d.ts +20 -0
  251. package/dist/services/SystemService.d.ts.map +1 -1
  252. package/dist/services/SystemService.js +93 -0
  253. package/dist/services/SystemService.js.map +1 -1
  254. package/dist/services/WorkerService.d.ts +8 -0
  255. package/dist/services/WorkerService.d.ts.map +1 -1
  256. package/dist/services/WorkerService.js +73 -3
  257. package/dist/services/WorkerService.js.map +1 -1
  258. package/dist/services/container.d.ts +2 -0
  259. package/dist/services/container.d.ts.map +1 -1
  260. package/dist/services/container.js +2 -0
  261. package/dist/services/container.js.map +1 -1
  262. package/dist/shared/localTime.d.ts +8 -0
  263. package/dist/shared/localTime.d.ts.map +1 -0
  264. package/dist/shared/localTime.js +11 -0
  265. package/dist/shared/localTime.js.map +1 -0
  266. package/dist/shared/runtimePaths.d.ts +1 -1
  267. package/dist/shared/runtimePaths.d.ts.map +1 -1
  268. package/dist/shared/runtimePaths.js +2 -2
  269. package/dist/shared/runtimePaths.js.map +1 -1
  270. package/dist/shared/runtimeSchemas.d.ts +74 -245
  271. package/dist/shared/runtimeSchemas.d.ts.map +1 -1
  272. package/dist/shared/runtimeSchemas.js +2 -2
  273. package/dist/shared/runtimeSchemas.js.map +1 -1
  274. package/monitor-skills/probe-playbook/SKILL.md +32 -0
  275. package/monitor-skills/visual-rubric/SKILL.md +34 -0
  276. package/package.json +8 -8
  277. package/project-template/.claude/hooks/stop.sh +3 -1
  278. package/dist/console-assets/assets/index-BvWWj69G.js +0 -557
  279. package/dist/console-assets/assets/index-Eo4PuNPl.css +0 -10
  280. package/dist/interfaces/ACPClient.d.ts +0 -107
  281. package/dist/interfaces/ACPClient.d.ts.map +0 -1
  282. package/dist/interfaces/ACPClient.js +0 -17
  283. package/dist/interfaces/ACPClient.js.map +0 -1
  284. package/dist/interfaces/AgentRuntime.d.ts +0 -40
  285. package/dist/interfaces/AgentRuntime.d.ts.map +0 -1
  286. package/dist/interfaces/AgentRuntime.js +0 -17
  287. package/dist/interfaces/AgentRuntime.js.map +0 -1
  288. package/dist/manager/agentmemory.d.ts +0 -6
  289. package/dist/manager/agentmemory.d.ts.map +0 -1
  290. package/dist/manager/agentmemory.js +0 -73
  291. package/dist/manager/agentmemory.js.map +0 -1
  292. package/dist/models/acp.d.ts +0 -64
  293. package/dist/models/acp.d.ts.map +0 -1
  294. package/dist/models/acp.js +0 -17
  295. package/dist/models/acp.js.map +0 -1
  296. package/dist/providers/LocalACPClient.d.ts +0 -27
  297. package/dist/providers/LocalACPClient.d.ts.map +0 -1
  298. package/dist/providers/LocalACPClient.js +0 -26
  299. package/dist/providers/LocalACPClient.js.map +0 -1
  300. package/dist/providers/adapters/AcpSdkAdapter.d.ts +0 -24
  301. package/dist/providers/adapters/AcpSdkAdapter.d.ts.map +0 -1
  302. package/dist/providers/adapters/AcpSdkAdapter.js +0 -439
  303. package/dist/providers/adapters/AcpSdkAdapter.js.map +0 -1
  304. package/dist/providers/adapters/acp-fs-handlers.d.ts +0 -26
  305. package/dist/providers/adapters/acp-fs-handlers.d.ts.map +0 -1
  306. package/dist/providers/adapters/acp-fs-handlers.js +0 -61
  307. package/dist/providers/adapters/acp-fs-handlers.js.map +0 -1
  308. package/dist/providers/adapters/acp-permissions.d.ts +0 -42
  309. package/dist/providers/adapters/acp-permissions.d.ts.map +0 -1
  310. package/dist/providers/adapters/acp-permissions.js +0 -76
  311. package/dist/providers/adapters/acp-permissions.js.map +0 -1
  312. package/dist/providers/adapters/acp-session-accumulator.d.ts +0 -55
  313. package/dist/providers/adapters/acp-session-accumulator.d.ts.map +0 -1
  314. package/dist/providers/adapters/acp-session-accumulator.js +0 -133
  315. package/dist/providers/adapters/acp-session-accumulator.js.map +0 -1
  316. package/dist/providers/adapters/acp-terminal-manager.d.ts +0 -56
  317. package/dist/providers/adapters/acp-terminal-manager.d.ts.map +0 -1
  318. package/dist/providers/adapters/acp-terminal-manager.js +0 -127
  319. package/dist/providers/adapters/acp-terminal-manager.js.map +0 -1
  320. package/project-template/logs/.gitkeep +0 -0
  321. package/skills/architecture-decision-records/SKILL.md +0 -207
  322. package/skills/backend/SKILL.md +0 -62
  323. package/skills/backend/references/api-design.md +0 -168
  324. package/skills/backend/references/caching.md +0 -181
  325. package/skills/backend/references/data-access.md +0 -173
  326. package/skills/backend/references/layering.md +0 -181
  327. package/skills/backend/references/observability.md +0 -190
  328. package/skills/backend/references/resilience.md +0 -201
  329. package/skills/backend/references/security.md +0 -186
  330. package/skills/backend-architect/SKILL.md +0 -119
  331. package/skills/code-reviewer/SKILL.md +0 -143
  332. package/skills/coding-standards/SKILL.md +0 -60
  333. package/skills/coding-standards/references/clean-code.md +0 -258
  334. package/skills/coding-standards/references/code-review.md +0 -192
  335. package/skills/coding-standards/references/commits-and-prs.md +0 -226
  336. package/skills/coding-standards/references/error-strategy.md +0 -193
  337. package/skills/coding-standards/references/naming.md +0 -185
  338. package/skills/coding-standards/references/tdd.md +0 -171
  339. package/skills/database/SKILL.md +0 -53
  340. package/skills/database/references/indexing.md +0 -190
  341. package/skills/database/references/migrations.md +0 -199
  342. package/skills/database/references/nosql.md +0 -185
  343. package/skills/database/references/queries.md +0 -295
  344. package/skills/database/references/scaling.md +0 -203
  345. package/skills/database/references/schema.md +0 -191
  346. package/skills/database-optimizer/SKILL.md +0 -168
  347. package/skills/debugging-workflow/SKILL.md +0 -244
  348. package/skills/dev-worker/SKILL.md +0 -40
  349. package/skills/dev-worker/references/architect.md +0 -139
  350. package/skills/dev-worker/references/backend.md +0 -163
  351. package/skills/dev-worker/references/frontend.md +0 -122
  352. package/skills/dev-worker/references/fullstack.md +0 -179
  353. package/skills/dev-worker/references/optimizer.md +0 -151
  354. package/skills/dev-worker/references/phaser.md +0 -109
  355. package/skills/dev-worker/references/prototyper.md +0 -171
  356. package/skills/dev-worker/references/reviewer.md +0 -122
  357. package/skills/dev-worker/references/security.md +0 -154
  358. package/skills/dev-worker/references/senior.md +0 -155
  359. package/skills/dev-worker/references/typescript.md +0 -65
  360. package/skills/dev-worker/references/writer.md +0 -201
  361. package/skills/devops/SKILL.md +0 -55
  362. package/skills/devops/references/ci-cd.md +0 -204
  363. package/skills/devops/references/containers.md +0 -272
  364. package/skills/devops/references/deploy.md +0 -201
  365. package/skills/devops/references/iac.md +0 -252
  366. package/skills/devops/references/observability.md +0 -228
  367. package/skills/devops/references/secrets.md +0 -178
  368. package/skills/devops-automator/SKILL.md +0 -164
  369. package/skills/frontend/SKILL.md +0 -52
  370. package/skills/frontend/references/accessibility.md +0 -222
  371. package/skills/frontend/references/components.md +0 -206
  372. package/skills/frontend/references/performance.md +0 -219
  373. package/skills/frontend/references/routing.md +0 -209
  374. package/skills/frontend/references/state.md +0 -190
  375. package/skills/frontend/references/testing.md +0 -216
  376. package/skills/frontend-developer/SKILL.md +0 -115
  377. package/skills/git-workflow/SKILL.md +0 -355
  378. package/skills/golang/SKILL.md +0 -49
  379. package/skills/golang/references/concurrency.md +0 -284
  380. package/skills/golang/references/errors.md +0 -241
  381. package/skills/golang/references/idioms.md +0 -285
  382. package/skills/golang/references/testing.md +0 -238
  383. package/skills/java/SKILL.md +0 -50
  384. package/skills/java/references/concurrency.md +0 -194
  385. package/skills/java/references/idioms.md +0 -283
  386. package/skills/java/references/testing.md +0 -228
  387. package/skills/kotlin/SKILL.md +0 -47
  388. package/skills/kotlin/references/coroutines.md +0 -240
  389. package/skills/kotlin/references/idioms.md +0 -268
  390. package/skills/kotlin/references/testing.md +0 -219
  391. package/skills/mobile/SKILL.md +0 -50
  392. package/skills/mobile/references/architecture.md +0 -204
  393. package/skills/mobile/references/navigation.md +0 -158
  394. package/skills/mobile/references/performance.md +0 -152
  395. package/skills/mobile/references/platform.md +0 -166
  396. package/skills/mobile/references/state-and-data.md +0 -174
  397. package/skills/python/SKILL.md +0 -51
  398. package/skills/python/THIRD_PARTY.md +0 -14
  399. package/skills/python/references/async.md +0 -218
  400. package/skills/python/references/error-handling.md +0 -254
  401. package/skills/python/references/idioms.md +0 -279
  402. package/skills/python/references/packaging.md +0 -233
  403. package/skills/python/references/testing.md +0 -269
  404. package/skills/python/references/typing.md +0 -292
  405. package/skills/qa-tester/SKILL.md +0 -186
  406. package/skills/rust/SKILL.md +0 -50
  407. package/skills/rust/references/async.md +0 -224
  408. package/skills/rust/references/errors.md +0 -240
  409. package/skills/rust/references/ownership.md +0 -263
  410. package/skills/rust/references/testing.md +0 -274
  411. package/skills/rust/references/traits.md +0 -250
  412. package/skills/security-engineer/SKILL.md +0 -157
  413. package/skills/sps-memory/SKILL.md +0 -213
  414. package/skills/sps-pipeline/SKILL.md +0 -476
  415. package/skills/swift/SKILL.md +0 -48
  416. package/skills/swift/references/concurrency.md +0 -280
  417. package/skills/swift/references/idioms.md +0 -334
  418. package/skills/swift/references/testing.md +0 -229
  419. package/skills/tax-worker/SKILL.md +0 -150
  420. package/skills/tax-worker/references/account-codes.md +0 -165
  421. package/skills/typescript/SKILL.md +0 -51
  422. package/skills/typescript/references/async.md +0 -241
  423. package/skills/typescript/references/errors.md +0 -208
  424. package/skills/typescript/references/idioms.md +0 -246
  425. package/skills/typescript/references/testing.md +0 -225
  426. package/skills/typescript/references/tooling.md +0 -208
  427. package/skills/typescript/references/types.md +0 -259
  428. package/skills/wiki-update/SKILL.md +0 -300
@@ -1,225 +0,0 @@
1
- # TypeScript — Testing
2
-
3
- Vitest / Jest, mocking, fixtures. For TDD cycle and general philosophy, see `coding-standards/references/tdd.md`.
4
-
5
- ## Runner: Vitest > Jest (for new projects)
6
-
7
- Vitest is faster, ESM-native, and shares config with Vite. Jest is still fine on existing code.
8
-
9
- ```ts
10
- // vitest.config.ts
11
- import { defineConfig } from 'vitest/config';
12
- export default defineConfig({
13
- test: {
14
- coverage: { provider: 'v8', reporter: ['text', 'html'], thresholds: { lines: 80 } },
15
- globals: false, // import describe/it/expect explicitly
16
- },
17
- });
18
- ```
19
-
20
- ## File layout
21
-
22
- | Convention | Pattern |
23
- |---|---|
24
- | Colocated | `src/user.ts` + `src/user.test.ts` |
25
- | Separated | `src/user.ts` + `tests/user.test.ts` |
26
-
27
- Colocated is easier to maintain; separated is easier to exclude from production bundles (if your bundler doesn't already tree-shake tests). Pick one and be consistent.
28
-
29
- ## Structure
30
-
31
- ```ts
32
- import { describe, it, expect, beforeEach } from 'vitest';
33
- import { UserService } from './user-service';
34
-
35
- describe('UserService', () => {
36
- let service: UserService;
37
-
38
- beforeEach(() => {
39
- service = new UserService(new InMemoryUserRepo());
40
- });
41
-
42
- it('creates a user with a generated id', async () => {
43
- const u = await service.create({ name: 'A', email: 'a@x.com' });
44
- expect(u.id).toBeTypeOf('string');
45
- expect(u.name).toBe('A');
46
- });
47
-
48
- it('rejects empty email', async () => {
49
- await expect(service.create({ name: 'A', email: '' }))
50
- .rejects.toThrow(ValidationError);
51
- });
52
- });
53
- ```
54
-
55
- Test names describe behaviour, not implementation. `creates a user with a generated id`, not `test_1`.
56
-
57
- ## Assertions
58
-
59
- ```ts
60
- expect(value).toBe(expected); // strict equality (===)
61
- expect(value).toEqual(expected); // deep equality
62
- expect(value).toStrictEqual(expected); // deep + prototype + undefined
63
-
64
- expect(fn).toThrow(TypeError);
65
- expect(fn).toThrow(/invalid email/);
66
- await expect(promise).rejects.toThrow();
67
-
68
- expect(array).toContain(item);
69
- expect(obj).toMatchObject({ name: 'A' }); // partial match
70
-
71
- expect(value).toSatisfy(v => v > 0 && v < 10);
72
- ```
73
-
74
- `toBe` on objects compares references, almost always wrong. Use `toEqual`.
75
-
76
- ## Mocking
77
-
78
- Prefer fakes (real implementations with in-memory backing) over mocks. Mocks drift from the thing they imitate.
79
-
80
- ```ts
81
- // ✅ fake — behaves like a repo, just in memory
82
- class InMemoryUserRepo implements UserRepository {
83
- private users = new Map<string, User>();
84
- async findById(id: string) { return this.users.get(id) ?? null; }
85
- async save(u: User) { this.users.set(u.id, u); }
86
- }
87
-
88
- // ⚠️ mock — easy for one test, painful when the repo grows
89
- const mockRepo = {
90
- findById: vi.fn().mockResolvedValue(null),
91
- save: vi.fn(),
92
- } as unknown as UserRepository;
93
- ```
94
-
95
- When you do mock:
96
-
97
- ```ts
98
- import { vi } from 'vitest';
99
-
100
- const sendEmail = vi.fn();
101
- vi.mock('./email', () => ({ sendEmail }));
102
-
103
- it('sends welcome email', async () => {
104
- await service.signup('a@x.com');
105
- expect(sendEmail).toHaveBeenCalledWith({ to: 'a@x.com', template: 'welcome' });
106
- });
107
- ```
108
-
109
- `vi.mock` hoists — the import is replaced everywhere the module is used.
110
-
111
- ## Fixtures — inject what the test needs
112
-
113
- ```ts
114
- function makeUser(overrides: Partial<User> = {}): User {
115
- return { id: 'u_1', email: 'a@x.com', active: true, ...overrides };
116
- }
117
-
118
- it('rejects inactive users', () => {
119
- const u = makeUser({ active: false });
120
- expect(() => assertActive(u)).toThrow();
121
- });
122
- ```
123
-
124
- Factories beat hard-coded objects. Default in place, override per test.
125
-
126
- ## Parameterized tests
127
-
128
- ```ts
129
- describe.each([
130
- { a: 1, b: 2, sum: 3 },
131
- { a: 0, b: 0, sum: 0 },
132
- { a: -1, b: 1, sum: 0 },
133
- ])('add($a, $b)', ({ a, b, sum }) => {
134
- it(`returns ${sum}`, () => expect(add(a, b)).toBe(sum));
135
- });
136
- ```
137
-
138
- Use `it.each` for simpler cases.
139
-
140
- ## Async tests
141
-
142
- ```ts
143
- it('fetches', async () => {
144
- const u = await findUser('u_1');
145
- expect(u).not.toBeNull();
146
- });
147
-
148
- // Rejections
149
- await expect(findUser('bad')).rejects.toThrow(NotFoundError);
150
-
151
- // Don't forget `await`; a missing `await` on a rejecting promise is a silent false pass
152
- ```
153
-
154
- Fake timers for time-based code:
155
-
156
- ```ts
157
- vi.useFakeTimers();
158
- const p = sleep(1000).then(() => 'done');
159
- vi.advanceTimersByTime(1000);
160
- await expect(p).resolves.toBe('done');
161
- vi.useRealTimers();
162
- ```
163
-
164
- ## Snapshot tests — use sparingly
165
-
166
- ```ts
167
- expect(renderEmail(user)).toMatchSnapshot();
168
- ```
169
-
170
- Good for large structural output. Bad as a lazy "assert-something" catch-all — a stale snapshot silently legitimizes bugs.
171
-
172
- Review every snapshot change deliberately. If you're running `--update-snapshots` as a reflex, they've lost their value.
173
-
174
- ## Integration tests
175
-
176
- Hit real dependencies (DB, Redis, HTTP) where feasible. Testcontainers makes this portable.
177
-
178
- ```ts
179
- // tests/integration/user.test.ts
180
- import { GenericContainer } from 'testcontainers';
181
-
182
- let pg;
183
- beforeAll(async () => {
184
- pg = await new GenericContainer('postgres:16-alpine')
185
- .withEnvironment({ POSTGRES_PASSWORD: 'test' })
186
- .withExposedPorts(5432)
187
- .start();
188
- // set DB_URL from pg.getMappedPort(5432)
189
- });
190
- afterAll(() => pg.stop());
191
- ```
192
-
193
- Integration tests give confidence that unit tests alone can't. Keep them separate from unit tests (`tests/integration/**`) so CI can run them in a different stage.
194
-
195
- ## Coverage — a floor, not a goal
196
-
197
- See `coding-standards/references/tdd.md` for coverage targets. Chasing 100% coverage with meaningless assertions hurts more than it helps.
198
-
199
- Enforce in CI:
200
-
201
- ```ts
202
- // vitest.config.ts
203
- test: {
204
- coverage: {
205
- thresholds: {
206
- lines: 80,
207
- functions: 80,
208
- branches: 70,
209
- },
210
- },
211
- }
212
- ```
213
-
214
- ## Anti-patterns
215
-
216
- | Anti-pattern | Fix |
217
- |---|---|
218
- | Tests that sleep for real seconds | Fake timers |
219
- | `it.only` committed to main | CI rule: reject `.only` in `test`/`it`/`describe` |
220
- | Shared mutable state between tests | Reset in `beforeEach` |
221
- | Testing by spying on console.log | Test observable behaviour, not debug output |
222
- | `expect(x).toEqual(x)` | Tautology; no signal |
223
- | Over-mocking: 10 mocks to test 20 lines | Refactor so the unit is easier to test |
224
- | Network in unit tests | Use fakes; move to integration suite |
225
- | Snapshot tests for volatile output (dates, uuids) | Redact or use deterministic fixtures |
@@ -1,208 +0,0 @@
1
- # TypeScript — Tooling
2
-
3
- `tsconfig`, linting, formatting, bundlers, monorepos.
4
-
5
- ## `tsconfig.json` — the baseline
6
-
7
- ```json
8
- {
9
- "compilerOptions": {
10
- "target": "ES2022",
11
- "module": "ESNext",
12
- "moduleResolution": "Bundler",
13
-
14
- "strict": true,
15
- "noUncheckedIndexedAccess": true,
16
- "noImplicitOverride": true,
17
- "exactOptionalPropertyTypes": true,
18
-
19
- "esModuleInterop": true,
20
- "skipLibCheck": true,
21
- "forceConsistentCasingInFileNames": true,
22
-
23
- "resolveJsonModule": true,
24
- "isolatedModules": true,
25
-
26
- "declaration": true,
27
- "declarationMap": true,
28
- "sourceMap": true,
29
-
30
- "outDir": "dist",
31
- "rootDir": "src"
32
- },
33
- "include": ["src/**/*"],
34
- "exclude": ["**/*.test.ts", "dist"]
35
- }
36
- ```
37
-
38
- Key switches:
39
-
40
- | Option | Why |
41
- |---|---|
42
- | `strict: true` | Turns on all strict flags. Required. |
43
- | `noUncheckedIndexedAccess` | `arr[0]` returns `T \| undefined`. Prevents off-by-one bugs. |
44
- | `exactOptionalPropertyTypes` | `{ x?: number }` vs `{ x: number \| undefined }` are actually different. |
45
- | `isolatedModules` | Required for swc/esbuild/bun. Catches things the single-file compilers can't handle. |
46
- | `skipLibCheck: true` | Faster; trust your deps. |
47
-
48
- ## Node vs. bundler resolution
49
-
50
- `moduleResolution: "Bundler"` for Vite, esbuild, webpack, Vite, Bun. `"NodeNext"` for plain Node.js. Pick based on the runtime.
51
-
52
- ## Path aliases
53
-
54
- ```json
55
- {
56
- "compilerOptions": {
57
- "baseUrl": ".",
58
- "paths": {
59
- "@/*": ["src/*"]
60
- }
61
- }
62
- }
63
- ```
64
-
65
- Mirror this in the bundler and test runner, or imports resolve in TS but not at runtime.
66
-
67
- ## Linting — ESLint (flat config)
68
-
69
- ```js
70
- // eslint.config.js
71
- import tseslint from 'typescript-eslint';
72
- export default tseslint.config(
73
- ...tseslint.configs.recommendedTypeChecked,
74
- {
75
- languageOptions: { parserOptions: { project: true } },
76
- rules: {
77
- '@typescript-eslint/no-floating-promises': 'error',
78
- '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
79
- '@typescript-eslint/switch-exhaustiveness-check': 'error',
80
- '@typescript-eslint/consistent-type-imports': 'error',
81
- '@typescript-eslint/no-explicit-any': 'error',
82
- },
83
- },
84
- );
85
- ```
86
-
87
- High-signal rules:
88
- - `no-floating-promises` — forgotten `await` is a frequent bug
89
- - `switch-exhaustiveness-check` — forgotten case in a union switch
90
- - `no-misused-promises` — `async` callback passed where sync is expected
91
- - `consistent-type-imports` — `import type { X }` keeps runtime lean
92
-
93
- ## Formatting — Prettier (or project-specific)
94
-
95
- Let the formatter run in CI and on save. Don't argue style in PRs.
96
-
97
- ```json
98
- // .prettierrc
99
- {
100
- "semi": true,
101
- "singleQuote": true,
102
- "trailingComma": "all",
103
- "printWidth": 100,
104
- "arrowParens": "always"
105
- }
106
- ```
107
-
108
- Team preference is fine — the choice matters less than the consistency.
109
-
110
- ## `tsc` vs. the bundlers
111
-
112
- | Tool | Role |
113
- |---|---|
114
- | `tsc` | Type checking + `.d.ts` emit |
115
- | `esbuild` / `swc` | Fast transpile (strip types, downlevel syntax) |
116
- | `tsup` / `rollup` | Libraries with exports maps |
117
- | `vite` / `rsbuild` / `rspack` | App bundling (frontend / dev server) |
118
-
119
- Typical modern setup: `vitest` for tests, `vite` for the dev server, `tsc --noEmit` in CI for type checking. Transpile is handled by the bundler — `tsc` is not on the hot path.
120
-
121
- ## Package managers
122
-
123
- `pnpm` is the default recommendation:
124
- - Content-addressable store → disk savings, fast installs
125
- - Strict by default → catches phantom dependencies
126
- - Excellent monorepo support via workspaces
127
-
128
- `npm` works. `yarn classic` (v1) is deprecated; `yarn berry` (v3+) is fine but niche. `bun` is fastest but still rough around the edges for some toolchains.
129
-
130
- Commit the lockfile.
131
-
132
- ## Monorepo
133
-
134
- For 3+ packages that share code, use workspaces.
135
-
136
- ```json
137
- // package.json (root)
138
- {
139
- "private": true,
140
- "workspaces": ["packages/*", "apps/*"]
141
- }
142
- ```
143
-
144
- Prefer workspace tools over hand-rolled symlinks:
145
- - `pnpm` workspaces (native)
146
- - `turborepo` / `nx` for task orchestration + caching
147
- - `changesets` for versioning + release notes
148
-
149
- Keep the dependency graph explicit — `apps/web` depends on `packages/ui`, not the reverse.
150
-
151
- ## `package.json` essentials
152
-
153
- ```json
154
- {
155
- "name": "@org/pkg",
156
- "version": "1.2.0",
157
- "type": "module",
158
- "exports": {
159
- ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
160
- "./utils": { "types": "./dist/utils.d.ts", "import": "./dist/utils.js" }
161
- },
162
- "files": ["dist"],
163
- "scripts": {
164
- "build": "tsup src/index.ts --format esm --dts",
165
- "test": "vitest run",
166
- "lint": "eslint .",
167
- "typecheck": "tsc --noEmit"
168
- },
169
- "engines": { "node": ">=20" }
170
- }
171
- ```
172
-
173
- - `type: "module"` — ESM by default. New projects should be ESM.
174
- - `exports` — explicit public API, not "everything in the dist directory".
175
- - `engines` — fail loudly when users install on an unsupported Node.
176
-
177
- ## Dev vs. prod dependencies
178
-
179
- - `dependencies`: anything the shipped app actually runs
180
- - `devDependencies`: build tools, test frameworks, types
181
- - `peerDependencies`: libraries (only) — "I need X, user provides it"
182
-
183
- A library that ships `react` in `dependencies` causes duplicate-React bugs. Put it in `peerDependencies` with a loose range.
184
-
185
- ## CI checklist
186
-
187
- ```yaml
188
- # GitHub Actions sketch
189
- - run: pnpm install --frozen-lockfile
190
- - run: pnpm typecheck
191
- - run: pnpm lint
192
- - run: pnpm test --coverage
193
- - run: pnpm build
194
- ```
195
-
196
- Order matters: typecheck before tests (cheap fail); lint before tests (cheap fail); build last.
197
-
198
- ## Anti-patterns
199
-
200
- | Anti-pattern | Fix |
201
- |---|---|
202
- | `strict: false` | Turn it on; fix errors incrementally with `// @ts-expect-error` |
203
- | `tsc` on every file save in a large repo | Use `--incremental` or IDE's language server |
204
- | Leaving `skipLibCheck: false` | Fine for a tiny project; wastes CI on any larger one |
205
- | Committing `dist/` | Publish it, don't commit it |
206
- | `type: "commonjs"` in new projects | Go ESM |
207
- | Mixing formatters across directories | One config at the repo root |
208
- | `ts-node` in production | Pre-compile; don't transpile at boot |
@@ -1,259 +0,0 @@
1
- # TypeScript — Types
2
-
3
- Generics, unions, discriminated unions, utility types, brands.
4
-
5
- ## `unknown` over `any`
6
-
7
- `any` disables type checking. `unknown` forces you to narrow before use.
8
-
9
- ```ts
10
- // ❌ silent bugs
11
- function parse(raw: any) {
12
- return raw.user.email.toLowerCase(); // crashes at runtime, no TS error
13
- }
14
-
15
- // ✅
16
- function parse(raw: unknown) {
17
- if (typeof raw === 'object' && raw !== null && 'user' in raw) {
18
- // ... still need more narrowing
19
- }
20
- }
21
-
22
- // ✅✅ parse at boundary with a schema
23
- import { z } from 'zod';
24
- const Schema = z.object({ user: z.object({ email: z.string().email() }) });
25
- function parse(raw: unknown) {
26
- const { user } = Schema.parse(raw); // throws on bad shape
27
- return user.email.toLowerCase();
28
- }
29
- ```
30
-
31
- ## Discriminated unions — the TS superpower
32
-
33
- Model state with a tagged sum type. Narrowing happens automatically.
34
-
35
- ```ts
36
- type Result<T, E> =
37
- | { ok: true; value: T }
38
- | { ok: false; error: E };
39
-
40
- function handle(r: Result<User, Error>) {
41
- if (r.ok) {
42
- // r is narrowed to { ok: true; value: User }
43
- console.log(r.value.name);
44
- } else {
45
- // r is narrowed to { ok: false; error: Error }
46
- console.error(r.error.message);
47
- }
48
- }
49
- ```
50
-
51
- Prefer over boolean flags + optional fields:
52
-
53
- ```ts
54
- // ❌
55
- type Loading = { isLoading: boolean; data?: User; error?: string };
56
-
57
- // ✅
58
- type Loading =
59
- | { status: 'idle' }
60
- | { status: 'loading' }
61
- | { status: 'success'; data: User }
62
- | { status: 'error'; error: string };
63
- ```
64
-
65
- The compiler stops you from accessing `data` on an `error` state.
66
-
67
- ## Exhaustiveness checks
68
-
69
- When you switch over a union, make sure every case is handled.
70
-
71
- ```ts
72
- function render(r: Loading) {
73
- switch (r.status) {
74
- case 'idle': return <Idle />;
75
- case 'loading': return <Spinner />;
76
- case 'success': return <Show data={r.data} />;
77
- case 'error': return <Err msg={r.error} />;
78
- default: return assertNever(r);
79
- }
80
- }
81
-
82
- function assertNever(x: never): never {
83
- throw new Error(`Unreachable: ${JSON.stringify(x)}`);
84
- }
85
- ```
86
-
87
- Add a new variant → the compiler forces you to update every `switch`.
88
-
89
- ## Generics
90
-
91
- Use when a function / class preserves a type relationship.
92
-
93
- ```ts
94
- function first<T>(xs: readonly T[]): T | undefined {
95
- return xs[0];
96
- }
97
-
98
- // Bounded
99
- function byId<T extends { id: string }>(xs: T[], id: string): T | undefined {
100
- return xs.find(x => x.id === id);
101
- }
102
-
103
- // Default
104
- type Paginated<T, Cursor = string> = {
105
- data: T[];
106
- nextCursor: Cursor | null;
107
- };
108
- ```
109
-
110
- If a generic parameter appears only once in the signature, you probably don't need generics.
111
-
112
- ## Utility types — the greatest hits
113
-
114
- | Type | Use |
115
- |---|---|
116
- | `Partial<T>` | All fields optional |
117
- | `Required<T>` | All fields required |
118
- | `Readonly<T>` | All fields readonly |
119
- | `Pick<T, K>` | Subset of fields |
120
- | `Omit<T, K>` | All fields except K |
121
- | `Record<K, V>` | Map-like object |
122
- | `Awaited<P>` | Unwrap Promise |
123
- | `ReturnType<F>` | The return type of a function |
124
- | `Parameters<F>` | Tuple of function params |
125
- | `NonNullable<T>` | Exclude null / undefined |
126
-
127
- ```ts
128
- type User = { id: string; email: string; password: string };
129
- type PublicUser = Omit<User, 'password'>;
130
- type UserUpdate = Partial<Pick<User, 'email' | 'password'>>;
131
- ```
132
-
133
- ## Branded types
134
-
135
- Prevent string / number mix-ups at compile time.
136
-
137
- ```ts
138
- type Brand<K, T> = K & { __brand: T };
139
-
140
- type UserId = Brand<string, 'UserId'>;
141
- type OrgId = Brand<string, 'OrgId'>;
142
-
143
- function userId(s: string): UserId { return s as UserId; }
144
- function orgId(s: string): OrgId { return s as OrgId; }
145
-
146
- function findUser(id: UserId): User { ... }
147
-
148
- findUser(userId('u_1')); // ✅
149
- findUser('u_1'); // ❌ not a UserId
150
- findUser(orgId('o_1')); // ❌ wrong brand
151
- ```
152
-
153
- The runtime cost is zero — it's just a compile-time distinction. Use it for domain ids, units, hashed vs raw strings.
154
-
155
- ## Type guards
156
-
157
- Custom predicates that narrow.
158
-
159
- ```ts
160
- function isUser(x: unknown): x is User {
161
- return typeof x === 'object' && x !== null && 'id' in x && typeof (x as any).id === 'string';
162
- }
163
-
164
- const raw: unknown = fetchSomething();
165
- if (isUser(raw)) {
166
- raw.id.toLowerCase(); // raw is narrowed to User
167
- }
168
- ```
169
-
170
- For anything more than two fields, use a schema validator (`zod`, `valibot`). Hand-written guards drift from the shape.
171
-
172
- ## `as const` — literal-typed values
173
-
174
- Widening turns `"hello"` into `string`. `as const` keeps it literal.
175
-
176
- ```ts
177
- const ROLES = ['admin', 'user', 'guest'] as const;
178
- type Role = typeof ROLES[number]; // 'admin' | 'user' | 'guest'
179
-
180
- const CONFIG = { retries: 3, timeout: 5000 } as const;
181
- // CONFIG.retries is 3, not number; CONFIG is readonly
182
- ```
183
-
184
- ## Conditional & mapped types — use sparingly
185
-
186
- Powerful, but expensive on the reader. Reach for them when the alternative is copy-paste.
187
-
188
- ```ts
189
- // Conditional
190
- type NonNull<T> = T extends null | undefined ? never : T;
191
-
192
- // Mapped
193
- type Nullable<T> = { [K in keyof T]: T[K] | null };
194
-
195
- // Both, with `infer`
196
- type UnwrapArray<T> = T extends (infer U)[] ? U : T;
197
-
198
- type X = UnwrapArray<User[]>; // User
199
- type Y = UnwrapArray<string>; // string
200
- ```
201
-
202
- If the type gets fancy enough that a teammate asks "what does this do?", add a comment with an example, or simplify.
203
-
204
- ## `never` — the bottom type
205
-
206
- `never` appears when TS knows no value can reach here.
207
-
208
- ```ts
209
- function throwErr(m: string): never { throw new Error(m); }
210
-
211
- const x = cond ? 1 : throwErr('no'); // x is number
212
-
213
- // Exhaustiveness (see above)
214
- default: return assertNever(r);
215
- ```
216
-
217
- `never` in a position where you expect a value is a bug signal: "you forgot a case".
218
-
219
- ## `satisfies` — typecheck without widening
220
-
221
- Force a value to conform to a type, but keep its narrow inferred type.
222
-
223
- ```ts
224
- const routes = {
225
- home: '/home',
226
- profile: '/profile/:id',
227
- } satisfies Record<string, string>;
228
-
229
- // routes.home is the literal "/home", not string
230
- type RouteKey = keyof typeof routes; // 'home' | 'profile'
231
- ```
232
-
233
- Great for config objects. `as Record<string, string>` would erase the literals.
234
-
235
- ## Enums — avoid; prefer string unions
236
-
237
- ```ts
238
- // ❌ enum (generates runtime code, not tree-shakeable, weird reverse mapping)
239
- enum Role { Admin, User, Guest }
240
-
241
- // ✅ string union (zero runtime, tree-shakeable, grepable)
242
- type Role = 'admin' | 'user' | 'guest';
243
-
244
- // ✅ object + `as const` if you need a value container
245
- const Role = { Admin: 'admin', User: 'user', Guest: 'guest' } as const;
246
- type Role = typeof Role[keyof typeof Role];
247
- ```
248
-
249
- `const enum` exists but trips up bundlers and project-references. Not worth it.
250
-
251
- ## Class vs. type vs. interface
252
-
253
- | Use | When |
254
- |---|---|
255
- | `type` | Unions, intersections, mapped / conditional, brands, non-extensible shapes |
256
- | `interface` | Public object contract, open for extension by users (declaration merging) |
257
- | `class` | Need a runtime object with methods and state |
258
-
259
- Prefer `type` for data and `interface` for object behaviours. Don't mix conventions arbitrarily.