@coralai/sps-cli 0.55.12 → 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 (431) 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/memory.d.ts.map +1 -1
  102. package/dist/core/memory.js +9 -12
  103. package/dist/core/memory.js.map +1 -1
  104. package/dist/core/memoryIngest.d.ts +18 -0
  105. package/dist/core/memoryIngest.d.ts.map +1 -0
  106. package/dist/core/memoryIngest.js +56 -0
  107. package/dist/core/memoryIngest.js.map +1 -0
  108. package/dist/core/memoryProvider.d.ts +63 -0
  109. package/dist/core/memoryProvider.d.ts.map +1 -0
  110. package/dist/core/memoryProvider.js +205 -0
  111. package/dist/core/memoryProvider.js.map +1 -0
  112. package/dist/core/skillStore.d.ts.map +1 -1
  113. package/dist/core/skillStore.js +2 -1
  114. package/dist/core/skillStore.js.map +1 -1
  115. package/dist/core/skills/SkillsManager.d.ts +38 -0
  116. package/dist/core/skills/SkillsManager.d.ts.map +1 -0
  117. package/dist/core/skills/SkillsManager.js +231 -0
  118. package/dist/core/skills/SkillsManager.js.map +1 -0
  119. package/dist/core/skills/distribution.d.ts +64 -0
  120. package/dist/core/skills/distribution.d.ts.map +1 -0
  121. package/dist/core/skills/distribution.js +269 -0
  122. package/dist/core/skills/distribution.js.map +1 -0
  123. package/dist/core/skills/index.d.ts +13 -0
  124. package/dist/core/skills/index.d.ts.map +1 -0
  125. package/dist/core/skills/index.js +13 -0
  126. package/dist/core/skills/index.js.map +1 -0
  127. package/dist/core/skills/types.d.ts +44 -0
  128. package/dist/core/skills/types.d.ts.map +1 -0
  129. package/dist/core/skills/types.js +9 -0
  130. package/dist/core/skills/types.js.map +1 -0
  131. package/dist/core/taskPrompts.d.ts +0 -12
  132. package/dist/core/taskPrompts.d.ts.map +1 -1
  133. package/dist/core/taskPrompts.js +0 -14
  134. package/dist/core/taskPrompts.js.map +1 -1
  135. package/dist/core/transcriptIngest.d.ts +37 -0
  136. package/dist/core/transcriptIngest.d.ts.map +1 -0
  137. package/dist/core/transcriptIngest.js +137 -0
  138. package/dist/core/transcriptIngest.js.map +1 -0
  139. package/dist/core/wiki/types.d.ts +282 -745
  140. package/dist/core/wiki/types.d.ts.map +1 -1
  141. package/dist/core/wiki/types.js +1 -1
  142. package/dist/core/wiki/types.js.map +1 -1
  143. package/dist/engines/SmartArrangeEngine.d.ts +75 -0
  144. package/dist/engines/SmartArrangeEngine.d.ts.map +1 -0
  145. package/dist/engines/SmartArrangeEngine.js +112 -0
  146. package/dist/engines/SmartArrangeEngine.js.map +1 -0
  147. package/dist/engines/StageEngine.d.ts +3 -17
  148. package/dist/engines/StageEngine.d.ts.map +1 -1
  149. package/dist/engines/StageEngine.js +13 -91
  150. package/dist/engines/StageEngine.js.map +1 -1
  151. package/dist/engines/smartarrange/AcpWorkerExec.d.ts +35 -0
  152. package/dist/engines/smartarrange/AcpWorkerExec.d.ts.map +1 -0
  153. package/dist/engines/smartarrange/AcpWorkerExec.js +71 -0
  154. package/dist/engines/smartarrange/AcpWorkerExec.js.map +1 -0
  155. package/dist/engines/smartarrange/cardSink.d.ts +29 -0
  156. package/dist/engines/smartarrange/cardSink.d.ts.map +1 -0
  157. package/dist/engines/smartarrange/cardSink.js +43 -0
  158. package/dist/engines/smartarrange/cardSink.js.map +1 -0
  159. package/dist/engines/smartarrange/runner.d.ts +24 -0
  160. package/dist/engines/smartarrange/runner.d.ts.map +1 -0
  161. package/dist/engines/smartarrange/runner.js +116 -0
  162. package/dist/engines/smartarrange/runner.js.map +1 -0
  163. package/dist/engines/smartarrange/screenshot.d.ts +5 -0
  164. package/dist/engines/smartarrange/screenshot.d.ts.map +1 -0
  165. package/dist/engines/smartarrange/screenshot.js +117 -0
  166. package/dist/engines/smartarrange/screenshot.js.map +1 -0
  167. package/dist/main.js +127 -92
  168. package/dist/main.js.map +1 -1
  169. package/dist/manager/worker-manager-impl.d.ts.map +1 -1
  170. package/dist/manager/worker-manager-impl.js +7 -0
  171. package/dist/manager/worker-manager-impl.js.map +1 -1
  172. package/dist/providers/LLMClient.d.ts +32 -0
  173. package/dist/providers/LLMClient.d.ts.map +1 -0
  174. package/dist/providers/LLMClient.js +108 -0
  175. package/dist/providers/LLMClient.js.map +1 -0
  176. package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -1
  177. package/dist/providers/MarkdownTaskBackend.js +3 -2
  178. package/dist/providers/MarkdownTaskBackend.js.map +1 -1
  179. package/dist/providers/llm/chatTools.d.ts +11 -0
  180. package/dist/providers/llm/chatTools.d.ts.map +1 -0
  181. package/dist/providers/llm/chatTools.js +57 -0
  182. package/dist/providers/llm/chatTools.js.map +1 -0
  183. package/dist/providers/llm/codexAuth.d.ts +8 -0
  184. package/dist/providers/llm/codexAuth.d.ts.map +1 -0
  185. package/dist/providers/llm/codexAuth.js +57 -0
  186. package/dist/providers/llm/codexAuth.js.map +1 -0
  187. package/dist/providers/llm/codexModel.d.ts +14 -0
  188. package/dist/providers/llm/codexModel.d.ts.map +1 -0
  189. package/dist/providers/llm/codexModel.js +96 -0
  190. package/dist/providers/llm/codexModel.js.map +1 -0
  191. package/dist/providers/llm/localSubscription.d.ts +15 -0
  192. package/dist/providers/llm/localSubscription.d.ts.map +1 -0
  193. package/dist/providers/llm/localSubscription.js +66 -0
  194. package/dist/providers/llm/localSubscription.js.map +1 -0
  195. package/dist/providers/llm/modelFactory.d.ts +14 -0
  196. package/dist/providers/llm/modelFactory.d.ts.map +1 -0
  197. package/dist/providers/llm/modelFactory.js +22 -0
  198. package/dist/providers/llm/modelFactory.js.map +1 -0
  199. package/dist/providers/llm/monitorSkills.d.ts +6 -0
  200. package/dist/providers/llm/monitorSkills.d.ts.map +1 -0
  201. package/dist/providers/llm/monitorSkills.js +37 -0
  202. package/dist/providers/llm/monitorSkills.js.map +1 -0
  203. package/dist/providers/llm/probeTools.d.ts +7 -0
  204. package/dist/providers/llm/probeTools.d.ts.map +1 -0
  205. package/dist/providers/llm/probeTools.js +84 -0
  206. package/dist/providers/llm/probeTools.js.map +1 -0
  207. package/dist/providers/llm/providers.d.ts +26 -0
  208. package/dist/providers/llm/providers.d.ts.map +1 -0
  209. package/dist/providers/llm/providers.js +68 -0
  210. package/dist/providers/llm/providers.js.map +1 -0
  211. package/dist/providers/llm/skillTools.d.ts +4 -0
  212. package/dist/providers/llm/skillTools.d.ts.map +1 -0
  213. package/dist/providers/llm/skillTools.js +42 -0
  214. package/dist/providers/llm/skillTools.js.map +1 -0
  215. package/dist/providers/llm/workerTools.d.ts +9 -0
  216. package/dist/providers/llm/workerTools.d.ts.map +1 -0
  217. package/dist/providers/llm/workerTools.js +111 -0
  218. package/dist/providers/llm/workerTools.js.map +1 -0
  219. package/dist/providers/mcp/spsMcpServer.d.ts +15 -0
  220. package/dist/providers/mcp/spsMcpServer.d.ts.map +1 -0
  221. package/dist/providers/mcp/spsMcpServer.js +67 -0
  222. package/dist/providers/mcp/spsMcpServer.js.map +1 -0
  223. package/dist/providers/mcp/spsMcpStdio.d.ts +2 -0
  224. package/dist/providers/mcp/spsMcpStdio.d.ts.map +1 -0
  225. package/dist/providers/mcp/spsMcpStdio.js +32 -0
  226. package/dist/providers/mcp/spsMcpStdio.js.map +1 -0
  227. package/dist/providers/mcp/spsMcpStdioConfig.d.ts +11 -0
  228. package/dist/providers/mcp/spsMcpStdioConfig.d.ts.map +1 -0
  229. package/dist/providers/mcp/spsMcpStdioConfig.js +19 -0
  230. package/dist/providers/mcp/spsMcpStdioConfig.js.map +1 -0
  231. package/dist/server.d.ts +23 -0
  232. package/dist/server.d.ts.map +1 -1
  233. package/dist/server.js +23 -0
  234. package/dist/server.js.map +1 -1
  235. package/dist/services/ChatService.d.ts +8 -0
  236. package/dist/services/ChatService.d.ts.map +1 -1
  237. package/dist/services/ChatService.js +2 -0
  238. package/dist/services/ChatService.js.map +1 -1
  239. package/dist/services/LogService.d.ts +1 -1
  240. package/dist/services/LogService.d.ts.map +1 -1
  241. package/dist/services/LogService.js +3 -2
  242. package/dist/services/LogService.js.map +1 -1
  243. package/dist/services/ProjectService.d.ts +12 -2
  244. package/dist/services/ProjectService.d.ts.map +1 -1
  245. package/dist/services/ProjectService.js +1 -0
  246. package/dist/services/ProjectService.js.map +1 -1
  247. package/dist/services/SkillService.js +11 -13
  248. package/dist/services/SkillService.js.map +1 -1
  249. package/dist/services/SmartArrangeService.d.ts +12 -0
  250. package/dist/services/SmartArrangeService.d.ts.map +1 -0
  251. package/dist/services/SmartArrangeService.js +37 -0
  252. package/dist/services/SmartArrangeService.js.map +1 -0
  253. package/dist/services/SystemService.d.ts +20 -0
  254. package/dist/services/SystemService.d.ts.map +1 -1
  255. package/dist/services/SystemService.js +93 -0
  256. package/dist/services/SystemService.js.map +1 -1
  257. package/dist/services/WorkerService.d.ts +8 -0
  258. package/dist/services/WorkerService.d.ts.map +1 -1
  259. package/dist/services/WorkerService.js +73 -3
  260. package/dist/services/WorkerService.js.map +1 -1
  261. package/dist/services/container.d.ts +2 -0
  262. package/dist/services/container.d.ts.map +1 -1
  263. package/dist/services/container.js +2 -0
  264. package/dist/services/container.js.map +1 -1
  265. package/dist/shared/localTime.d.ts +8 -0
  266. package/dist/shared/localTime.d.ts.map +1 -0
  267. package/dist/shared/localTime.js +11 -0
  268. package/dist/shared/localTime.js.map +1 -0
  269. package/dist/shared/runtimePaths.d.ts +1 -1
  270. package/dist/shared/runtimePaths.d.ts.map +1 -1
  271. package/dist/shared/runtimePaths.js +2 -2
  272. package/dist/shared/runtimePaths.js.map +1 -1
  273. package/dist/shared/runtimeSchemas.d.ts +74 -245
  274. package/dist/shared/runtimeSchemas.d.ts.map +1 -1
  275. package/dist/shared/runtimeSchemas.js +2 -2
  276. package/dist/shared/runtimeSchemas.js.map +1 -1
  277. package/monitor-skills/probe-playbook/SKILL.md +32 -0
  278. package/monitor-skills/visual-rubric/SKILL.md +34 -0
  279. package/package.json +8 -8
  280. package/project-template/.claude/hooks/stop.sh +3 -1
  281. package/dist/console-assets/assets/index-BvWWj69G.js +0 -557
  282. package/dist/console-assets/assets/index-Eo4PuNPl.css +0 -10
  283. package/dist/interfaces/ACPClient.d.ts +0 -107
  284. package/dist/interfaces/ACPClient.d.ts.map +0 -1
  285. package/dist/interfaces/ACPClient.js +0 -17
  286. package/dist/interfaces/ACPClient.js.map +0 -1
  287. package/dist/interfaces/AgentRuntime.d.ts +0 -40
  288. package/dist/interfaces/AgentRuntime.d.ts.map +0 -1
  289. package/dist/interfaces/AgentRuntime.js +0 -17
  290. package/dist/interfaces/AgentRuntime.js.map +0 -1
  291. package/dist/manager/agentmemory.d.ts +0 -6
  292. package/dist/manager/agentmemory.d.ts.map +0 -1
  293. package/dist/manager/agentmemory.js +0 -73
  294. package/dist/manager/agentmemory.js.map +0 -1
  295. package/dist/models/acp.d.ts +0 -64
  296. package/dist/models/acp.d.ts.map +0 -1
  297. package/dist/models/acp.js +0 -17
  298. package/dist/models/acp.js.map +0 -1
  299. package/dist/providers/LocalACPClient.d.ts +0 -27
  300. package/dist/providers/LocalACPClient.d.ts.map +0 -1
  301. package/dist/providers/LocalACPClient.js +0 -26
  302. package/dist/providers/LocalACPClient.js.map +0 -1
  303. package/dist/providers/adapters/AcpSdkAdapter.d.ts +0 -24
  304. package/dist/providers/adapters/AcpSdkAdapter.d.ts.map +0 -1
  305. package/dist/providers/adapters/AcpSdkAdapter.js +0 -439
  306. package/dist/providers/adapters/AcpSdkAdapter.js.map +0 -1
  307. package/dist/providers/adapters/acp-fs-handlers.d.ts +0 -26
  308. package/dist/providers/adapters/acp-fs-handlers.d.ts.map +0 -1
  309. package/dist/providers/adapters/acp-fs-handlers.js +0 -61
  310. package/dist/providers/adapters/acp-fs-handlers.js.map +0 -1
  311. package/dist/providers/adapters/acp-permissions.d.ts +0 -42
  312. package/dist/providers/adapters/acp-permissions.d.ts.map +0 -1
  313. package/dist/providers/adapters/acp-permissions.js +0 -76
  314. package/dist/providers/adapters/acp-permissions.js.map +0 -1
  315. package/dist/providers/adapters/acp-session-accumulator.d.ts +0 -55
  316. package/dist/providers/adapters/acp-session-accumulator.d.ts.map +0 -1
  317. package/dist/providers/adapters/acp-session-accumulator.js +0 -133
  318. package/dist/providers/adapters/acp-session-accumulator.js.map +0 -1
  319. package/dist/providers/adapters/acp-terminal-manager.d.ts +0 -56
  320. package/dist/providers/adapters/acp-terminal-manager.d.ts.map +0 -1
  321. package/dist/providers/adapters/acp-terminal-manager.js +0 -127
  322. package/dist/providers/adapters/acp-terminal-manager.js.map +0 -1
  323. package/project-template/logs/.gitkeep +0 -0
  324. package/skills/architecture-decision-records/SKILL.md +0 -207
  325. package/skills/backend/SKILL.md +0 -62
  326. package/skills/backend/references/api-design.md +0 -168
  327. package/skills/backend/references/caching.md +0 -181
  328. package/skills/backend/references/data-access.md +0 -173
  329. package/skills/backend/references/layering.md +0 -181
  330. package/skills/backend/references/observability.md +0 -190
  331. package/skills/backend/references/resilience.md +0 -201
  332. package/skills/backend/references/security.md +0 -186
  333. package/skills/backend-architect/SKILL.md +0 -119
  334. package/skills/code-reviewer/SKILL.md +0 -143
  335. package/skills/coding-standards/SKILL.md +0 -60
  336. package/skills/coding-standards/references/clean-code.md +0 -258
  337. package/skills/coding-standards/references/code-review.md +0 -192
  338. package/skills/coding-standards/references/commits-and-prs.md +0 -226
  339. package/skills/coding-standards/references/error-strategy.md +0 -193
  340. package/skills/coding-standards/references/naming.md +0 -185
  341. package/skills/coding-standards/references/tdd.md +0 -171
  342. package/skills/database/SKILL.md +0 -53
  343. package/skills/database/references/indexing.md +0 -190
  344. package/skills/database/references/migrations.md +0 -199
  345. package/skills/database/references/nosql.md +0 -185
  346. package/skills/database/references/queries.md +0 -295
  347. package/skills/database/references/scaling.md +0 -203
  348. package/skills/database/references/schema.md +0 -191
  349. package/skills/database-optimizer/SKILL.md +0 -168
  350. package/skills/debugging-workflow/SKILL.md +0 -244
  351. package/skills/dev-worker/SKILL.md +0 -40
  352. package/skills/dev-worker/references/architect.md +0 -139
  353. package/skills/dev-worker/references/backend.md +0 -163
  354. package/skills/dev-worker/references/frontend.md +0 -122
  355. package/skills/dev-worker/references/fullstack.md +0 -179
  356. package/skills/dev-worker/references/optimizer.md +0 -151
  357. package/skills/dev-worker/references/phaser.md +0 -109
  358. package/skills/dev-worker/references/prototyper.md +0 -171
  359. package/skills/dev-worker/references/reviewer.md +0 -122
  360. package/skills/dev-worker/references/security.md +0 -154
  361. package/skills/dev-worker/references/senior.md +0 -155
  362. package/skills/dev-worker/references/typescript.md +0 -65
  363. package/skills/dev-worker/references/writer.md +0 -201
  364. package/skills/devops/SKILL.md +0 -55
  365. package/skills/devops/references/ci-cd.md +0 -204
  366. package/skills/devops/references/containers.md +0 -272
  367. package/skills/devops/references/deploy.md +0 -201
  368. package/skills/devops/references/iac.md +0 -252
  369. package/skills/devops/references/observability.md +0 -228
  370. package/skills/devops/references/secrets.md +0 -178
  371. package/skills/devops-automator/SKILL.md +0 -164
  372. package/skills/frontend/SKILL.md +0 -52
  373. package/skills/frontend/references/accessibility.md +0 -222
  374. package/skills/frontend/references/components.md +0 -206
  375. package/skills/frontend/references/performance.md +0 -219
  376. package/skills/frontend/references/routing.md +0 -209
  377. package/skills/frontend/references/state.md +0 -190
  378. package/skills/frontend/references/testing.md +0 -216
  379. package/skills/frontend-developer/SKILL.md +0 -115
  380. package/skills/git-workflow/SKILL.md +0 -355
  381. package/skills/golang/SKILL.md +0 -49
  382. package/skills/golang/references/concurrency.md +0 -284
  383. package/skills/golang/references/errors.md +0 -241
  384. package/skills/golang/references/idioms.md +0 -285
  385. package/skills/golang/references/testing.md +0 -238
  386. package/skills/java/SKILL.md +0 -50
  387. package/skills/java/references/concurrency.md +0 -194
  388. package/skills/java/references/idioms.md +0 -283
  389. package/skills/java/references/testing.md +0 -228
  390. package/skills/kotlin/SKILL.md +0 -47
  391. package/skills/kotlin/references/coroutines.md +0 -240
  392. package/skills/kotlin/references/idioms.md +0 -268
  393. package/skills/kotlin/references/testing.md +0 -219
  394. package/skills/mobile/SKILL.md +0 -50
  395. package/skills/mobile/references/architecture.md +0 -204
  396. package/skills/mobile/references/navigation.md +0 -158
  397. package/skills/mobile/references/performance.md +0 -152
  398. package/skills/mobile/references/platform.md +0 -166
  399. package/skills/mobile/references/state-and-data.md +0 -174
  400. package/skills/python/SKILL.md +0 -51
  401. package/skills/python/THIRD_PARTY.md +0 -14
  402. package/skills/python/references/async.md +0 -218
  403. package/skills/python/references/error-handling.md +0 -254
  404. package/skills/python/references/idioms.md +0 -279
  405. package/skills/python/references/packaging.md +0 -233
  406. package/skills/python/references/testing.md +0 -269
  407. package/skills/python/references/typing.md +0 -292
  408. package/skills/qa-tester/SKILL.md +0 -186
  409. package/skills/rust/SKILL.md +0 -50
  410. package/skills/rust/references/async.md +0 -224
  411. package/skills/rust/references/errors.md +0 -240
  412. package/skills/rust/references/ownership.md +0 -263
  413. package/skills/rust/references/testing.md +0 -274
  414. package/skills/rust/references/traits.md +0 -250
  415. package/skills/security-engineer/SKILL.md +0 -157
  416. package/skills/sps-memory/SKILL.md +0 -213
  417. package/skills/sps-pipeline/SKILL.md +0 -476
  418. package/skills/swift/SKILL.md +0 -48
  419. package/skills/swift/references/concurrency.md +0 -280
  420. package/skills/swift/references/idioms.md +0 -334
  421. package/skills/swift/references/testing.md +0 -229
  422. package/skills/tax-worker/SKILL.md +0 -150
  423. package/skills/tax-worker/references/account-codes.md +0 -165
  424. package/skills/typescript/SKILL.md +0 -51
  425. package/skills/typescript/references/async.md +0 -241
  426. package/skills/typescript/references/errors.md +0 -208
  427. package/skills/typescript/references/idioms.md +0 -246
  428. package/skills/typescript/references/testing.md +0 -225
  429. package/skills/typescript/references/tooling.md +0 -208
  430. package/skills/typescript/references/types.md +0 -259
  431. 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.