ccjk 14.2.2 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +58 -341
  3. package/dist/cli.js +59 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/detect.js +15 -0
  6. package/dist/commands/detect.js.map +1 -0
  7. package/dist/commands/doctor.js +68 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/git-install.js +50 -0
  10. package/dist/commands/git-install.js.map +1 -0
  11. package/dist/commands/init.js +102 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/mcp.js +66 -0
  14. package/dist/commands/mcp.js.map +1 -0
  15. package/dist/commands/menu.js +33 -0
  16. package/dist/commands/menu.js.map +1 -0
  17. package/dist/core/detect.js +24 -0
  18. package/dist/core/detect.js.map +1 -0
  19. package/dist/core/lint.js +49 -0
  20. package/dist/core/lint.js.map +1 -0
  21. package/dist/core/mcp.js +41 -0
  22. package/dist/core/mcp.js.map +1 -0
  23. package/dist/core/paths.js +9 -0
  24. package/dist/core/paths.js.map +1 -0
  25. package/dist/core/providers.js +53 -0
  26. package/dist/core/providers.js.map +1 -0
  27. package/dist/core/settings.js +31 -0
  28. package/dist/core/settings.js.map +1 -0
  29. package/dist/core/slash-templates.js +56 -0
  30. package/dist/core/slash-templates.js.map +1 -0
  31. package/dist/core/tools.js +27 -0
  32. package/dist/core/tools.js.map +1 -0
  33. package/package.json +43 -164
  34. package/README.HONEST.md +0 -176
  35. package/README.en.md +0 -67
  36. package/README.ja.md +0 -67
  37. package/README.ko.md +0 -67
  38. package/README.zh-CN.md +0 -86
  39. package/bin/ccjk.mjs +0 -5
  40. package/bin/ccjk.ts +0 -222
  41. package/dist/chunks/agent-teams.mjs +0 -145
  42. package/dist/chunks/agent.mjs +0 -1439
  43. package/dist/chunks/agents.mjs +0 -3783
  44. package/dist/chunks/api-cli.mjs +0 -135
  45. package/dist/chunks/api-config-selector.mjs +0 -159
  46. package/dist/chunks/api-providers.mjs +0 -144
  47. package/dist/chunks/api.mjs +0 -115
  48. package/dist/chunks/auto-bootstrap.mjs +0 -358
  49. package/dist/chunks/auto-fixer.mjs +0 -95
  50. package/dist/chunks/auto-updater.mjs +0 -507
  51. package/dist/chunks/banner.mjs +0 -173
  52. package/dist/chunks/bash.mjs +0 -187
  53. package/dist/chunks/boost.mjs +0 -474
  54. package/dist/chunks/brain-config.mjs +0 -75
  55. package/dist/chunks/brain-status.mjs +0 -89
  56. package/dist/chunks/ccjk-agents.mjs +0 -416
  57. package/dist/chunks/ccjk-all.mjs +0 -1046
  58. package/dist/chunks/ccjk-config.mjs +0 -445
  59. package/dist/chunks/ccjk-hooks.mjs +0 -1074
  60. package/dist/chunks/ccjk-mcp.mjs +0 -763
  61. package/dist/chunks/ccjk-setup.mjs +0 -765
  62. package/dist/chunks/ccjk-skills.mjs +0 -518
  63. package/dist/chunks/ccr.mjs +0 -109
  64. package/dist/chunks/ccu.mjs +0 -40
  65. package/dist/chunks/check-updates.mjs +0 -117
  66. package/dist/chunks/claude-code-incremental-manager.mjs +0 -761
  67. package/dist/chunks/claude-config.mjs +0 -606
  68. package/dist/chunks/claude-config2.mjs +0 -62
  69. package/dist/chunks/claude-wrapper.mjs +0 -85
  70. package/dist/chunks/clavue-config.mjs +0 -1454
  71. package/dist/chunks/cleanup-migration.mjs +0 -20
  72. package/dist/chunks/cli-hook.mjs +0 -4096
  73. package/dist/chunks/cloud-sync.mjs +0 -29
  74. package/dist/chunks/code-type-resolver.mjs +0 -880
  75. package/dist/chunks/codex-config-switch.mjs +0 -452
  76. package/dist/chunks/codex-provider-manager.mjs +0 -238
  77. package/dist/chunks/codex-uninstaller.mjs +0 -404
  78. package/dist/chunks/codex.mjs +0 -2141
  79. package/dist/chunks/commands.mjs +0 -108
  80. package/dist/chunks/commands2.mjs +0 -421
  81. package/dist/chunks/commit.mjs +0 -140
  82. package/dist/chunks/completion.mjs +0 -517
  83. package/dist/chunks/config-consolidator.mjs +0 -172
  84. package/dist/chunks/config-switch.mjs +0 -334
  85. package/dist/chunks/config.mjs +0 -558
  86. package/dist/chunks/config2.mjs +0 -484
  87. package/dist/chunks/config3.mjs +0 -486
  88. package/dist/chunks/constants.mjs +0 -323
  89. package/dist/chunks/context-opt.mjs +0 -444
  90. package/dist/chunks/context.mjs +0 -974
  91. package/dist/chunks/dashboard.mjs +0 -481
  92. package/dist/chunks/doctor.mjs +0 -1301
  93. package/dist/chunks/eval.mjs +0 -502
  94. package/dist/chunks/evolution.mjs +0 -322
  95. package/dist/chunks/features.mjs +0 -715
  96. package/dist/chunks/fish.mjs +0 -181
  97. package/dist/chunks/fs-operations.mjs +0 -180
  98. package/dist/chunks/health-alerts.mjs +0 -830
  99. package/dist/chunks/help.mjs +0 -341
  100. package/dist/chunks/hook-installer.mjs +0 -48
  101. package/dist/chunks/impact.mjs +0 -651
  102. package/dist/chunks/index.mjs +0 -23
  103. package/dist/chunks/index10.mjs +0 -19
  104. package/dist/chunks/index11.mjs +0 -1171
  105. package/dist/chunks/index12.mjs +0 -218
  106. package/dist/chunks/index13.mjs +0 -679
  107. package/dist/chunks/index14.mjs +0 -1009
  108. package/dist/chunks/index15.mjs +0 -194
  109. package/dist/chunks/index2.mjs +0 -7637
  110. package/dist/chunks/index3.mjs +0 -171
  111. package/dist/chunks/index4.mjs +0 -26
  112. package/dist/chunks/index5.mjs +0 -19
  113. package/dist/chunks/index6.mjs +0 -19092
  114. package/dist/chunks/index7.mjs +0 -616
  115. package/dist/chunks/index8.mjs +0 -1602
  116. package/dist/chunks/index9.mjs +0 -5384
  117. package/dist/chunks/init.mjs +0 -1911
  118. package/dist/chunks/installer.mjs +0 -757
  119. package/dist/chunks/installer2.mjs +0 -103
  120. package/dist/chunks/interview.mjs +0 -2927
  121. package/dist/chunks/json-config.mjs +0 -60
  122. package/dist/chunks/linux.mjs +0 -3863
  123. package/dist/chunks/macos.mjs +0 -69
  124. package/dist/chunks/main.mjs +0 -635
  125. package/dist/chunks/manager.mjs +0 -1048
  126. package/dist/chunks/marketplace.mjs +0 -265
  127. package/dist/chunks/mcp-cli.mjs +0 -205
  128. package/dist/chunks/mcp-performance.mjs +0 -187
  129. package/dist/chunks/mcp.mjs +0 -667
  130. package/dist/chunks/memory-check.mjs +0 -2973
  131. package/dist/chunks/memory-paths.mjs +0 -259
  132. package/dist/chunks/memory-sync.mjs +0 -209
  133. package/dist/chunks/memory.mjs +0 -354
  134. package/dist/chunks/metrics-display.mjs +0 -153
  135. package/dist/chunks/monitor.mjs +0 -1856
  136. package/dist/chunks/notification.mjs +0 -1864
  137. package/dist/chunks/onboarding.mjs +0 -386
  138. package/dist/chunks/package.mjs +0 -3
  139. package/dist/chunks/paradigm.mjs +0 -74
  140. package/dist/chunks/permission-manager.mjs +0 -250
  141. package/dist/chunks/permissions.mjs +0 -265
  142. package/dist/chunks/persistence-manager.mjs +0 -801
  143. package/dist/chunks/persistence.mjs +0 -707
  144. package/dist/chunks/platform.mjs +0 -395
  145. package/dist/chunks/plugin.mjs +0 -1936
  146. package/dist/chunks/powershell.mjs +0 -213
  147. package/dist/chunks/prompts.mjs +0 -244
  148. package/dist/chunks/providers.mjs +0 -263
  149. package/dist/chunks/quick-actions.mjs +0 -335
  150. package/dist/chunks/quick-provider.mjs +0 -755
  151. package/dist/chunks/quick-setup.mjs +0 -421
  152. package/dist/chunks/remote.mjs +0 -497
  153. package/dist/chunks/research.mjs +0 -1904
  154. package/dist/chunks/rollback.mjs +0 -38
  155. package/dist/chunks/session-manager.mjs +0 -1371
  156. package/dist/chunks/session.mjs +0 -878
  157. package/dist/chunks/sessions.mjs +0 -106
  158. package/dist/chunks/silent-updater.mjs +0 -396
  159. package/dist/chunks/simple-config.mjs +0 -122
  160. package/dist/chunks/skill.mjs +0 -117
  161. package/dist/chunks/skill2.mjs +0 -9052
  162. package/dist/chunks/skills-sync.mjs +0 -1343
  163. package/dist/chunks/skills.mjs +0 -577
  164. package/dist/chunks/slash-commands.mjs +0 -208
  165. package/dist/chunks/smart-guide.mjs +0 -247
  166. package/dist/chunks/snapshot.mjs +0 -58
  167. package/dist/chunks/startup.mjs +0 -487
  168. package/dist/chunks/stats.mjs +0 -191
  169. package/dist/chunks/status.mjs +0 -471
  170. package/dist/chunks/team.mjs +0 -63
  171. package/dist/chunks/thinking.mjs +0 -626
  172. package/dist/chunks/trace.mjs +0 -57
  173. package/dist/chunks/uninstall.mjs +0 -852
  174. package/dist/chunks/update.mjs +0 -174
  175. package/dist/chunks/upgrade-manager.mjs +0 -204
  176. package/dist/chunks/upgrade.mjs +0 -133
  177. package/dist/chunks/version-checker.mjs +0 -891
  178. package/dist/chunks/vim.mjs +0 -903
  179. package/dist/chunks/windows.mjs +0 -14
  180. package/dist/chunks/workflows.mjs +0 -633
  181. package/dist/chunks/wsl.mjs +0 -129
  182. package/dist/chunks/zero-config.mjs +0 -871
  183. package/dist/chunks/zsh.mjs +0 -182
  184. package/dist/cli.d.mts +0 -1
  185. package/dist/cli.d.ts +0 -1
  186. package/dist/cli.mjs +0 -2684
  187. package/dist/i18n/locales/en/agent-teams.json +0 -18
  188. package/dist/i18n/locales/en/agentBrowser.json +0 -80
  189. package/dist/i18n/locales/en/agents.json +0 -135
  190. package/dist/i18n/locales/en/api.json +0 -63
  191. package/dist/i18n/locales/en/ccjk-agents.json +0 -33
  192. package/dist/i18n/locales/en/ccjk-all.json +0 -23
  193. package/dist/i18n/locales/en/ccjk-skills.json +0 -22
  194. package/dist/i18n/locales/en/ccjk.json +0 -276
  195. package/dist/i18n/locales/en/ccr.json +0 -65
  196. package/dist/i18n/locales/en/claude-md.json +0 -73
  197. package/dist/i18n/locales/en/cli.json +0 -148
  198. package/dist/i18n/locales/en/cloud-setup.json +0 -31
  199. package/dist/i18n/locales/en/cloud-sync.json +0 -147
  200. package/dist/i18n/locales/en/cloud.json +0 -40
  201. package/dist/i18n/locales/en/cloudPlugins.json +0 -118
  202. package/dist/i18n/locales/en/codex.json +0 -184
  203. package/dist/i18n/locales/en/cometix.json +0 -29
  204. package/dist/i18n/locales/en/common.json +0 -68
  205. package/dist/i18n/locales/en/config.json +0 -108
  206. package/dist/i18n/locales/en/configuration.json +0 -236
  207. package/dist/i18n/locales/en/context.json +0 -85
  208. package/dist/i18n/locales/en/dashboard.json +0 -78
  209. package/dist/i18n/locales/en/errors.json +0 -26
  210. package/dist/i18n/locales/en/evolution.json +0 -54
  211. package/dist/i18n/locales/en/hooks.json +0 -74
  212. package/dist/i18n/locales/en/hooksSync.json +0 -133
  213. package/dist/i18n/locales/en/installation.json +0 -83
  214. package/dist/i18n/locales/en/interview.json +0 -104
  215. package/dist/i18n/locales/en/language.json +0 -19
  216. package/dist/i18n/locales/en/lsp.json +0 -78
  217. package/dist/i18n/locales/en/marketplace.json +0 -116
  218. package/dist/i18n/locales/en/mcp.json +0 -180
  219. package/dist/i18n/locales/en/memory.json +0 -23
  220. package/dist/i18n/locales/en/menu.json +0 -299
  221. package/dist/i18n/locales/en/multi-config.json +0 -79
  222. package/dist/i18n/locales/en/notification.json +0 -307
  223. package/dist/i18n/locales/en/permissions.json +0 -95
  224. package/dist/i18n/locales/en/persistence.json +0 -127
  225. package/dist/i18n/locales/en/plugins.json +0 -146
  226. package/dist/i18n/locales/en/quick-actions.json +0 -78
  227. package/dist/i18n/locales/en/registry.json +0 -54
  228. package/dist/i18n/locales/en/remote.json +0 -93
  229. package/dist/i18n/locales/en/sandbox.json +0 -44
  230. package/dist/i18n/locales/en/setup.json +0 -44
  231. package/dist/i18n/locales/en/shencha.json +0 -14
  232. package/dist/i18n/locales/en/skills.json +0 -100
  233. package/dist/i18n/locales/en/skillsSync.json +0 -74
  234. package/dist/i18n/locales/en/smartGuide.json +0 -49
  235. package/dist/i18n/locales/en/stats.json +0 -20
  236. package/dist/i18n/locales/en/subagent.json +0 -69
  237. package/dist/i18n/locales/en/superpowers.json +0 -117
  238. package/dist/i18n/locales/en/team.json +0 -7
  239. package/dist/i18n/locales/en/thinking.json +0 -65
  240. package/dist/i18n/locales/en/tools.json +0 -42
  241. package/dist/i18n/locales/en/uninstall.json +0 -56
  242. package/dist/i18n/locales/en/updater.json +0 -29
  243. package/dist/i18n/locales/en/vim.json +0 -169
  244. package/dist/i18n/locales/en/workflow.json +0 -55
  245. package/dist/i18n/locales/en/workspace.json +0 -108
  246. package/dist/i18n/locales/zh-CN/agent-teams.json +0 -18
  247. package/dist/i18n/locales/zh-CN/agentBrowser.json +0 -80
  248. package/dist/i18n/locales/zh-CN/agents.json +0 -135
  249. package/dist/i18n/locales/zh-CN/api.json +0 -63
  250. package/dist/i18n/locales/zh-CN/ccjk-agents.json +0 -33
  251. package/dist/i18n/locales/zh-CN/ccjk-all.json +0 -23
  252. package/dist/i18n/locales/zh-CN/ccjk-skills.json +0 -22
  253. package/dist/i18n/locales/zh-CN/ccjk.json +0 -276
  254. package/dist/i18n/locales/zh-CN/ccr.json +0 -65
  255. package/dist/i18n/locales/zh-CN/claude-md.json +0 -73
  256. package/dist/i18n/locales/zh-CN/cli.json +0 -148
  257. package/dist/i18n/locales/zh-CN/cloud-setup.json +0 -31
  258. package/dist/i18n/locales/zh-CN/cloud-sync.json +0 -147
  259. package/dist/i18n/locales/zh-CN/cloud.json +0 -40
  260. package/dist/i18n/locales/zh-CN/cloudPlugins.json +0 -118
  261. package/dist/i18n/locales/zh-CN/codex.json +0 -184
  262. package/dist/i18n/locales/zh-CN/cometix.json +0 -29
  263. package/dist/i18n/locales/zh-CN/common.json +0 -68
  264. package/dist/i18n/locales/zh-CN/config.json +0 -108
  265. package/dist/i18n/locales/zh-CN/configuration.json +0 -234
  266. package/dist/i18n/locales/zh-CN/context.json +0 -85
  267. package/dist/i18n/locales/zh-CN/dashboard.json +0 -78
  268. package/dist/i18n/locales/zh-CN/errors.json +0 -26
  269. package/dist/i18n/locales/zh-CN/evolution.json +0 -54
  270. package/dist/i18n/locales/zh-CN/hooks.json +0 -74
  271. package/dist/i18n/locales/zh-CN/hooksSync.json +0 -133
  272. package/dist/i18n/locales/zh-CN/installation.json +0 -83
  273. package/dist/i18n/locales/zh-CN/interview.json +0 -104
  274. package/dist/i18n/locales/zh-CN/language.json +0 -19
  275. package/dist/i18n/locales/zh-CN/lsp.json +0 -78
  276. package/dist/i18n/locales/zh-CN/marketplace.json +0 -116
  277. package/dist/i18n/locales/zh-CN/mcp.json +0 -180
  278. package/dist/i18n/locales/zh-CN/memory.json +0 -23
  279. package/dist/i18n/locales/zh-CN/menu.json +0 -299
  280. package/dist/i18n/locales/zh-CN/multi-config.json +0 -79
  281. package/dist/i18n/locales/zh-CN/notification.json +0 -307
  282. package/dist/i18n/locales/zh-CN/permissions.json +0 -95
  283. package/dist/i18n/locales/zh-CN/persistence.json +0 -127
  284. package/dist/i18n/locales/zh-CN/plugins.json +0 -146
  285. package/dist/i18n/locales/zh-CN/quick-actions.json +0 -78
  286. package/dist/i18n/locales/zh-CN/registry.json +0 -54
  287. package/dist/i18n/locales/zh-CN/remote.json +0 -93
  288. package/dist/i18n/locales/zh-CN/sandbox.json +0 -44
  289. package/dist/i18n/locales/zh-CN/setup.json +0 -44
  290. package/dist/i18n/locales/zh-CN/shencha.json +0 -14
  291. package/dist/i18n/locales/zh-CN/skills.json +0 -100
  292. package/dist/i18n/locales/zh-CN/skillsSync.json +0 -74
  293. package/dist/i18n/locales/zh-CN/smartGuide.json +0 -49
  294. package/dist/i18n/locales/zh-CN/stats.json +0 -20
  295. package/dist/i18n/locales/zh-CN/subagent.json +0 -69
  296. package/dist/i18n/locales/zh-CN/superpowers.json +0 -117
  297. package/dist/i18n/locales/zh-CN/team.json +0 -7
  298. package/dist/i18n/locales/zh-CN/thinking.json +0 -65
  299. package/dist/i18n/locales/zh-CN/tools.json +0 -42
  300. package/dist/i18n/locales/zh-CN/uninstall.json +0 -56
  301. package/dist/i18n/locales/zh-CN/updater.json +0 -29
  302. package/dist/i18n/locales/zh-CN/vim.json +0 -169
  303. package/dist/i18n/locales/zh-CN/workflow.json +0 -55
  304. package/dist/i18n/locales/zh-CN/workspace.json +0 -108
  305. package/dist/index.d.mts +0 -5658
  306. package/dist/index.d.ts +0 -5658
  307. package/dist/index.mjs +0 -3732
  308. package/dist/shared/ccjk.5bEolFrk.mjs +0 -254
  309. package/dist/shared/ccjk.8oaxX4iR.mjs +0 -90
  310. package/dist/shared/ccjk.B2U7DsPy.mjs +0 -31
  311. package/dist/shared/ccjk.B2f-cwUP.mjs +0 -468
  312. package/dist/shared/ccjk.BAGoDD49.mjs +0 -36
  313. package/dist/shared/ccjk.BBtCGd_g.mjs +0 -899
  314. package/dist/shared/ccjk.BFQ7yr5S.mjs +0 -16
  315. package/dist/shared/ccjk.BLsIiTqO.mjs +0 -449
  316. package/dist/shared/ccjk.BXv8aYs1.mjs +0 -170
  317. package/dist/shared/ccjk.BnsY5WxD.mjs +0 -171
  318. package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
  319. package/dist/shared/ccjk.Bq8TqZG_.mjs +0 -189
  320. package/dist/shared/ccjk.BtrioX1Z.mjs +0 -25
  321. package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
  322. package/dist/shared/ccjk.BzPbSEP2.mjs +0 -115
  323. package/dist/shared/ccjk.C0WLUnFV.mjs +0 -293
  324. package/dist/shared/ccjk.C1hANZTu.mjs +0 -19
  325. package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
  326. package/dist/shared/ccjk.CNhnT6uQ.mjs +0 -636
  327. package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
  328. package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
  329. package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
  330. package/dist/shared/ccjk.CoCHVXl3.mjs +0 -3951
  331. package/dist/shared/ccjk.CwGZSTAK.mjs +0 -319
  332. package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
  333. package/dist/shared/ccjk.D-magaEx.mjs +0 -763
  334. package/dist/shared/ccjk.D0g2ABGg.mjs +0 -171
  335. package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
  336. package/dist/shared/ccjk.D75wivnp.mjs +0 -142
  337. package/dist/shared/ccjk.DDL-4C-k.mjs +0 -100
  338. package/dist/shared/ccjk.DFRPtmK_.mjs +0 -75
  339. package/dist/shared/ccjk.DMV3x5Sd.mjs +0 -299
  340. package/dist/shared/ccjk.DZ2LLOa-.mjs +0 -2195
  341. package/dist/shared/ccjk.DbigonEQ.mjs +0 -698
  342. package/dist/shared/ccjk.DcMvE7lf.mjs +0 -618
  343. package/dist/shared/ccjk.DeWpAShp.mjs +0 -1828
  344. package/dist/shared/ccjk.DhJ1kyDR.mjs +0 -30
  345. package/dist/shared/ccjk.DlTXS9rP.mjs +0 -224
  346. package/dist/shared/ccjk.DopKzo3z.mjs +0 -305
  347. package/dist/shared/ccjk.DsZsc4LR.mjs +0 -1280
  348. package/dist/shared/ccjk.DuzJZlgj.mjs +0 -418
  349. package/dist/shared/ccjk.Dxgd2vjc.mjs +0 -444
  350. package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
  351. package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
  352. package/dist/shared/ccjk.L7yC58_i.mjs +0 -225
  353. package/dist/shared/ccjk.MwtjAULc.mjs +0 -1447
  354. package/dist/shared/ccjk.OJKHVSOb.mjs +0 -2005
  355. package/dist/shared/ccjk.OTnevPNE.mjs +0 -225
  356. package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
  357. package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
  358. package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
  359. package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
  360. package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
  361. package/dist/shared/ccjk.i_vn-9C3.mjs +0 -317
  362. package/dist/shared/ccjk.lG3ccFjm.mjs +0 -885
  363. package/dist/shared/ccjk.wLJHO0Af.mjs +0 -244
  364. package/dist/shared/ccjk.y-a_1vK4.mjs +0 -5127
  365. package/dist/templates/agents/README.md +0 -78
  366. package/dist/templates/agents/fullstack-developer.json +0 -70
  367. package/dist/templates/agents/go-expert.json +0 -69
  368. package/dist/templates/agents/index.json +0 -64
  369. package/dist/templates/agents/python-expert.json +0 -69
  370. package/dist/templates/agents/react-specialist.json +0 -69
  371. package/dist/templates/agents/testing-automation-expert.json +0 -70
  372. package/dist/templates/agents/typescript-architect.json +0 -69
  373. package/dist/templates/claude-code/common/settings.json +0 -109
  374. package/dist/templates/common/error-prevention.md +0 -267
  375. package/dist/templates/common/karpathy-baseline.md +0 -83
  376. package/dist/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
  377. package/dist/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
  378. package/dist/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
  379. package/dist/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
  380. package/dist/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
  381. package/dist/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
  382. package/dist/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
  383. package/dist/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
  384. package/dist/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
  385. package/dist/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
  386. package/dist/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
  387. package/dist/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
  388. package/dist/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
  389. package/dist/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
  390. package/dist/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
  391. package/dist/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
  392. package/dist/templates/common/workflow/essential/en/feat.md +0 -92
  393. package/dist/templates/common/workflow/essential/en/goal.md +0 -147
  394. package/dist/templates/common/workflow/essential/en/init-project.md +0 -53
  395. package/dist/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
  396. package/dist/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
  397. package/dist/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
  398. package/dist/templates/common/workflow/essential/zh-CN/feat.md +0 -315
  399. package/dist/templates/common/workflow/essential/zh-CN/goal.md +0 -146
  400. package/dist/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
  401. package/dist/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
  402. package/dist/templates/common/workflow/git/en/git-commit.md +0 -205
  403. package/dist/templates/common/workflow/git/en/git-rollback.md +0 -90
  404. package/dist/templates/common/workflow/git/en/git-worktree.md +0 -276
  405. package/dist/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
  406. package/dist/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
  407. package/dist/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
  408. package/dist/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
  409. package/dist/templates/common/workflow/interview/en/interview.md +0 -67
  410. package/dist/templates/common/workflow/interview/zh-CN/interview.md +0 -67
  411. package/dist/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
  412. package/dist/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
  413. package/dist/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
  414. package/dist/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
  415. package/dist/templates/common/workflow/sixStep/en/workflow.md +0 -83
  416. package/dist/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
  417. package/dist/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
  418. package/dist/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
  419. package/dist/templates/hooks/README.md +0 -212
  420. package/dist/templates/hooks/git-workflow-hooks.md +0 -551
  421. package/dist/templates/hooks/post-test/coverage.json +0 -21
  422. package/dist/templates/hooks/post-test/summary.json +0 -21
  423. package/dist/templates/hooks/post-test-coverage.md +0 -434
  424. package/dist/templates/hooks/pre-commit/eslint.json +0 -22
  425. package/dist/templates/hooks/pre-commit/prettier.json +0 -22
  426. package/dist/templates/hooks/pre-commit-black.md +0 -274
  427. package/dist/templates/hooks/pre-commit-eslint.md +0 -153
  428. package/dist/templates/hooks/pre-commit-gofmt.md +0 -284
  429. package/dist/templates/hooks/pre-commit-prettier.md +0 -212
  430. package/dist/templates/hooks/pre-commit-type-check.md +0 -377
  431. package/dist/templates/skills/ccjk-init.md +0 -154
  432. package/dist/templates/skills/ccjk-mcp-setup.md +0 -205
  433. package/dist/templates/skills/ccjk-troubleshoot.md +0 -228
  434. package/dist/templates/skills/django-patterns.md +0 -1016
  435. package/dist/templates/skills/git-workflow.md +0 -748
  436. package/dist/templates/skills/go-idioms.md +0 -963
  437. package/dist/templates/skills/index.json +0 -132
  438. package/dist/templates/skills/nextjs-optimization.md +0 -694
  439. package/dist/templates/skills/python-pep8.md +0 -852
  440. package/dist/templates/skills/react-patterns.md +0 -686
  441. package/dist/templates/skills/rust-patterns.md +0 -1057
  442. package/dist/templates/skills/security-best-practices.md +0 -1413
  443. package/dist/templates/skills/testing-best-practices.md +0 -1315
  444. package/dist/templates/skills/ts-best-practices.md +0 -354
  445. package/templates/agents/README.md +0 -78
  446. package/templates/agents/fullstack-developer.json +0 -70
  447. package/templates/agents/go-expert.json +0 -69
  448. package/templates/agents/index.json +0 -64
  449. package/templates/agents/python-expert.json +0 -69
  450. package/templates/agents/react-specialist.json +0 -69
  451. package/templates/agents/testing-automation-expert.json +0 -70
  452. package/templates/agents/typescript-architect.json +0 -69
  453. package/templates/claude-code/common/settings.json +0 -109
  454. package/templates/common/error-prevention.md +0 -267
  455. package/templates/common/karpathy-baseline.md +0 -83
  456. package/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
  457. package/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
  458. package/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
  459. package/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
  460. package/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
  461. package/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
  462. package/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
  463. package/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
  464. package/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
  465. package/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
  466. package/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
  467. package/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
  468. package/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
  469. package/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
  470. package/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
  471. package/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
  472. package/templates/common/workflow/essential/en/feat.md +0 -92
  473. package/templates/common/workflow/essential/en/goal.md +0 -147
  474. package/templates/common/workflow/essential/en/init-project.md +0 -53
  475. package/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
  476. package/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
  477. package/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
  478. package/templates/common/workflow/essential/zh-CN/feat.md +0 -315
  479. package/templates/common/workflow/essential/zh-CN/goal.md +0 -146
  480. package/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
  481. package/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
  482. package/templates/common/workflow/git/en/git-commit.md +0 -205
  483. package/templates/common/workflow/git/en/git-rollback.md +0 -90
  484. package/templates/common/workflow/git/en/git-worktree.md +0 -276
  485. package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
  486. package/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
  487. package/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
  488. package/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
  489. package/templates/common/workflow/interview/en/interview.md +0 -67
  490. package/templates/common/workflow/interview/zh-CN/interview.md +0 -67
  491. package/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
  492. package/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
  493. package/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
  494. package/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
  495. package/templates/common/workflow/sixStep/en/workflow.md +0 -83
  496. package/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
  497. package/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
  498. package/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
  499. package/templates/hooks/README.md +0 -212
  500. package/templates/hooks/git-workflow-hooks.md +0 -551
  501. package/templates/hooks/post-test/coverage.json +0 -21
  502. package/templates/hooks/post-test/summary.json +0 -21
  503. package/templates/hooks/post-test-coverage.md +0 -434
  504. package/templates/hooks/pre-commit/eslint.json +0 -22
  505. package/templates/hooks/pre-commit/prettier.json +0 -22
  506. package/templates/hooks/pre-commit-black.md +0 -274
  507. package/templates/hooks/pre-commit-eslint.md +0 -153
  508. package/templates/hooks/pre-commit-gofmt.md +0 -284
  509. package/templates/hooks/pre-commit-prettier.md +0 -212
  510. package/templates/hooks/pre-commit-type-check.md +0 -377
  511. package/templates/skills/basic.hbs +0 -72
  512. package/templates/skills/ccjk-init.md +0 -154
  513. package/templates/skills/ccjk-mcp-setup.md +0 -205
  514. package/templates/skills/ccjk-troubleshoot.md +0 -228
  515. package/templates/skills/code-refactor.hbs +0 -133
  516. package/templates/skills/code-review.hbs +0 -141
  517. package/templates/skills/django-patterns.md +0 -1016
  518. package/templates/skills/git-workflow.md +0 -748
  519. package/templates/skills/go-idioms.md +0 -963
  520. package/templates/skills/index.json +0 -132
  521. package/templates/skills/nextjs-optimization.md +0 -694
  522. package/templates/skills/python-pep8.md +0 -852
  523. package/templates/skills/react-patterns.md +0 -686
  524. package/templates/skills/rust-patterns.md +0 -1057
  525. package/templates/skills/security-best-practices.md +0 -1413
  526. package/templates/skills/testing-best-practices.md +0 -1315
  527. package/templates/skills/ts-best-practices.md +0 -354
  528. package/templates/skills/type-fix.hbs +0 -132
@@ -1,1016 +0,0 @@
1
- ---
2
- name: django-patterns
3
- description: Django best practices, model design, view patterns, and ORM optimization
4
- description_zh: Django 最佳实践、模型设计、视图模式和 ORM 优化
5
- version: 1.0.0
6
- category: backend
7
- triggers: ['/django-patterns', '/django', '/django-orm', '/django-views']
8
- use_when:
9
- - Building Django applications with best practices
10
- - Designing Django models and database schemas
11
- - Implementing Django views and URL patterns
12
- - Optimizing Django ORM queries and performance
13
- use_when_zh:
14
- - 使用最佳实践构建 Django 应用程序
15
- - 设计 Django 模型和数据库架构
16
- - 实现 Django 视图和 URL 模式
17
- - 优化 Django ORM 查询和性能
18
- auto_activate: true
19
- priority: 8
20
- agents: [django-expert, backend-architect]
21
- tags: [django, orm, models, views, performance]
22
- ---
23
-
24
- # Django Patterns | Django 模式
25
-
26
- ## Context | 上下文
27
-
28
- Use this skill when developing Django applications that require scalable architecture, optimized database queries, and maintainable code structure. Essential for production-ready Django development.
29
-
30
- 在开发需要可扩展架构、优化数据库查询和可维护代码结构的 Django 应用程序时使用此技能。对于生产就绪的 Django 开发至关重要。
31
-
32
- ## Model Design Patterns | 模型设计模式
33
-
34
- ### 1. Model Best Practices | 模型最佳实践
35
-
36
- ```python
37
- from django.db import models
38
- from django.contrib.auth.models import AbstractUser
39
- from django.core.validators import MinValueValidator, MaxValueValidator
40
- from django.utils import timezone
41
- from django.urls import reverse
42
- from typing import Optional
43
- import uuid
44
-
45
- # ✅ Good: Well-designed models with proper relationships
46
-
47
- class TimeStampedModel(models.Model):
48
- """Abstract base model with timestamp fields."""
49
- created_at = models.DateTimeField(auto_now_add=True)
50
- updated_at = models.DateTimeField(auto_now=True)
51
-
52
- class Meta:
53
- abstract = True
54
-
55
- class User(AbstractUser):
56
- """Custom user model extending AbstractUser."""
57
- id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
58
- email = models.EmailField(unique=True)
59
- first_name = models.CharField(max_length=150)
60
- last_name = models.CharField(max_length=150)
61
- date_of_birth = models.DateField(null=True, blank=True)
62
- is_verified = models.BooleanField(default=False)
63
-
64
- USERNAME_FIELD = 'email'
65
- REQUIRED_FIELDS = ['username', 'first_name', 'last_name']
66
-
67
- class Meta:
68
- db_table = 'users'
69
- indexes = [
70
- models.Index(fields=['email']),
71
- models.Index(fields=['is_active', 'is_verified']),
72
- ]
73
-
74
- def __str__(self) -> str:
75
- return f"{self.first_name} {self.last_name} ({self.email})"
76
-
77
- def get_full_name(self) -> str:
78
- """Return the full name of the user."""
79
- return f"{self.first_name} {self.last_name}".strip()
80
-
81
- class Category(TimeStampedModel):
82
- """Product category model."""
83
- name = models.CharField(max_length=100, unique=True)
84
- slug = models.SlugField(max_length=100, unique=True)
85
- description = models.TextField(blank=True)
86
- parent = models.ForeignKey(
87
- 'self',
88
- on_delete=models.CASCADE,
89
- null=True,
90
- blank=True,
91
- related_name='children'
92
- )
93
- is_active = models.BooleanField(default=True)
94
-
95
- class Meta:
96
- verbose_name_plural = "categories"
97
- ordering = ['name']
98
- indexes = [
99
- models.Index(fields=['slug']),
100
- models.Index(fields=['is_active']),
101
- ]
102
-
103
- def __str__(self) -> str:
104
- return self.name
105
-
106
- def get_absolute_url(self) -> str:
107
- return reverse('category-detail', kwargs={'slug': self.slug})
108
-
109
- class Product(TimeStampedModel):
110
- """Product model with proper relationships and validation."""
111
- name = models.CharField(max_length=200)
112
- slug = models.SlugField(max_length=200, unique=True)
113
- description = models.TextField()
114
- price = models.DecimalField(
115
- max_digits=10,
116
- decimal_places=2,
117
- validators=[MinValueValidator(0)]
118
- )
119
- stock_quantity = models.PositiveIntegerField(default=0)
120
- category = models.ForeignKey(
121
- Category,
122
- on_delete=models.PROTECT,
123
- related_name='products'
124
- )
125
- tags = models.ManyToManyField('Tag', blank=True, related_name='products')
126
- is_active = models.BooleanField(default=True)
127
- featured = models.BooleanField(default=False)
128
-
129
- class Meta:
130
- ordering = ['-created_at']
131
- indexes = [
132
- models.Index(fields=['slug']),
133
- models.Index(fields=['category', 'is_active']),
134
- models.Index(fields=['featured', 'is_active']),
135
- models.Index(fields=['-created_at']),
136
- ]
137
-
138
- def __str__(self) -> str:
139
- return self.name
140
-
141
- def get_absolute_url(self) -> str:
142
- return reverse('product-detail', kwargs={'slug': self.slug})
143
-
144
- @property
145
- def is_in_stock(self) -> bool:
146
- """Check if product is in stock."""
147
- return self.stock_quantity > 0
148
-
149
- def reduce_stock(self, quantity: int) -> None:
150
- """Reduce stock quantity."""
151
- if quantity > self.stock_quantity:
152
- raise ValueError("Insufficient stock")
153
- self.stock_quantity -= quantity
154
- self.save(update_fields=['stock_quantity'])
155
-
156
- class Order(TimeStampedModel):
157
- """Order model with proper status management."""
158
-
159
- class Status(models.TextChoices):
160
- PENDING = 'pending', 'Pending'
161
- CONFIRMED = 'confirmed', 'Confirmed'
162
- SHIPPED = 'shipped', 'Shipped'
163
- DELIVERED = 'delivered', 'Delivered'
164
- CANCELLED = 'cancelled', 'Cancelled'
165
-
166
- id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
167
- user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='orders')
168
- status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING)
169
- total_amount = models.DecimalField(max_digits=10, decimal_places=2)
170
- shipping_address = models.TextField()
171
- notes = models.TextField(blank=True)
172
-
173
- class Meta:
174
- ordering = ['-created_at']
175
- indexes = [
176
- models.Index(fields=['user', 'status']),
177
- models.Index(fields=['status', '-created_at']),
178
- ]
179
-
180
- def __str__(self) -> str:
181
- return f"Order {self.id} - {self.user.email}"
182
-
183
- class OrderItem(models.Model):
184
- """Order item model for many-to-many relationship with additional fields."""
185
- order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
186
- product = models.ForeignKey(Product, on_delete=models.CASCADE)
187
- quantity = models.PositiveIntegerField(validators=[MinValueValidator(1)])
188
- unit_price = models.DecimalField(max_digits=10, decimal_places=2)
189
-
190
- class Meta:
191
- unique_together = ['order', 'product']
192
-
193
- def __str__(self) -> str:
194
- return f"{self.quantity}x {self.product.name}"
195
-
196
- @property
197
- def total_price(self) -> float:
198
- """Calculate total price for this item."""
199
- return float(self.quantity * self.unit_price)
200
-
201
- # ❌ Bad: Poor model design
202
- class BadProduct(models.Model):
203
- name = models.CharField(max_length=1000) # Too long
204
- price = models.FloatField() # Use DecimalField for money
205
- category_name = models.CharField(max_length=100) # Should be ForeignKey
206
- # Missing indexes, validation, and proper relationships
207
- ```
208
-
209
- ### 2. Custom Managers and QuerySets | 自定义管理器和查询集
210
-
211
- ```python
212
- from django.db import models
213
- from django.db.models import Q, Count, Avg
214
- from typing import Optional
215
-
216
- # ✅ Good: Custom QuerySet and Manager
217
-
218
- class ProductQuerySet(models.QuerySet):
219
- """Custom QuerySet for Product model."""
220
-
221
- def active(self):
222
- """Filter active products."""
223
- return self.filter(is_active=True)
224
-
225
- def in_stock(self):
226
- """Filter products that are in stock."""
227
- return self.filter(stock_quantity__gt=0)
228
-
229
- def by_category(self, category_slug: str):
230
- """Filter products by category slug."""
231
- return self.filter(category__slug=category_slug)
232
-
233
- def featured(self):
234
- """Filter featured products."""
235
- return self.filter(featured=True)
236
-
237
- def search(self, query: str):
238
- """Search products by name or description."""
239
- return self.filter(
240
- Q(name__icontains=query) | Q(description__icontains=query)
241
- )
242
-
243
- def with_category(self):
244
- """Select related category to avoid N+1 queries."""
245
- return self.select_related('category')
246
-
247
- def with_tags(self):
248
- """Prefetch tags to avoid N+1 queries."""
249
- return self.prefetch_related('tags')
250
-
251
- def popular(self, limit: int = 10):
252
- """Get popular products based on order count."""
253
- return self.annotate(
254
- order_count=Count('orderitem')
255
- ).order_by('-order_count')[:limit]
256
-
257
- class ProductManager(models.Manager):
258
- """Custom manager for Product model."""
259
-
260
- def get_queryset(self):
261
- """Return custom QuerySet."""
262
- return ProductQuerySet(self.model, using=self._db)
263
-
264
- def active(self):
265
- """Get active products."""
266
- return self.get_queryset().active()
267
-
268
- def available(self):
269
- """Get active products that are in stock."""
270
- return self.get_queryset().active().in_stock()
271
-
272
- def featured(self):
273
- """Get featured products."""
274
- return self.get_queryset().active().featured()
275
-
276
- # Add to Product model
277
- class Product(TimeStampedModel):
278
- # ... other fields ...
279
-
280
- objects = ProductManager() # Custom manager
281
-
282
- # ... rest of the model ...
283
-
284
- # Usage examples
285
- # Get all active products with categories
286
- products = Product.objects.active().with_category()
287
-
288
- # Search for products
289
- search_results = Product.objects.active().search("laptop")
290
-
291
- # Get featured products by category
292
- featured_laptops = Product.objects.featured().by_category("laptops")
293
-
294
- # Get popular products
295
- popular_products = Product.objects.popular(limit=5)
296
- ```
297
-
298
- ## View Patterns | 视图模式
299
-
300
- ### 1. Class-Based Views (CBVs) | 基于类的视图
301
-
302
- ```python
303
- from django.views.generic import ListView, DetailView, CreateView, UpdateView
304
- from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
305
- from django.db.models import Q, Prefetch
306
- from django.http import JsonResponse
307
- from django.shortcuts import get_object_or_404
308
- from django.urls import reverse_lazy
309
- from django.contrib import messages
310
- from typing import Any, Dict
311
-
312
- # ✅ Good: Well-structured CBVs with mixins
313
-
314
- class ProductListView(ListView):
315
- """List view for products with filtering and pagination."""
316
- model = Product
317
- template_name = 'products/list.html'
318
- context_object_name = 'products'
319
- paginate_by = 20
320
-
321
- def get_queryset(self):
322
- """Get filtered and optimized queryset."""
323
- queryset = Product.objects.active().with_category().with_tags()
324
-
325
- # Apply filters
326
- category_slug = self.request.GET.get('category')
327
- if category_slug:
328
- queryset = queryset.by_category(category_slug)
329
-
330
- search_query = self.request.GET.get('q')
331
- if search_query:
332
- queryset = queryset.search(search_query)
333
-
334
- # Apply ordering
335
- ordering = self.request.GET.get('ordering', '-created_at')
336
- if ordering in ['name', '-name', 'price', '-price', '-created_at']:
337
- queryset = queryset.order_by(ordering)
338
-
339
- return queryset
340
-
341
- def get_context_data(self, **kwargs) -> Dict[str, Any]:
342
- """Add additional context data."""
343
- context = super().get_context_data(**kwargs)
344
- context['categories'] = Category.objects.filter(is_active=True)
345
- context['current_category'] = self.request.GET.get('category', '')
346
- context['search_query'] = self.request.GET.get('q', '')
347
- context['current_ordering'] = self.request.GET.get('ordering', '-created_at')
348
- return context
349
-
350
- class ProductDetailView(DetailView):
351
- """Detail view for a single product."""
352
- model = Product
353
- template_name = 'products/detail.html'
354
- context_object_name = 'product'
355
- slug_field = 'slug'
356
- slug_url_kwarg = 'slug'
357
-
358
- def get_queryset(self):
359
- """Optimize queryset with related objects."""
360
- return Product.objects.active().with_category().with_tags().select_related('category')
361
-
362
- def get_context_data(self, **kwargs) -> Dict[str, Any]:
363
- """Add related products to context."""
364
- context = super().get_context_data(**kwargs)
365
- product = self.object
366
-
367
- # Get related products from same category
368
- context['related_products'] = Product.objects.active().filter(
369
- category=product.category
370
- ).exclude(id=product.id)[:4]
371
-
372
- return context
373
-
374
- class ProductCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
375
- """Create view for products (admin only)."""
376
- model = Product
377
- template_name = 'products/create.html'
378
- fields = ['name', 'slug', 'description', 'price', 'stock_quantity', 'category', 'tags']
379
- success_url = reverse_lazy('product-list')
380
-
381
- def test_func(self) -> bool:
382
- """Check if user is staff."""
383
- return self.request.user.is_staff
384
-
385
- def form_valid(self, form):
386
- """Add success message."""
387
- messages.success(self.request, 'Product created successfully!')
388
- return super().form_valid(form)
389
-
390
- class OrderListView(LoginRequiredMixin, ListView):
391
- """List view for user's orders."""
392
- model = Order
393
- template_name = 'orders/list.html'
394
- context_object_name = 'orders'
395
- paginate_by = 10
396
-
397
- def get_queryset(self):
398
- """Get orders for current user."""
399
- return Order.objects.filter(
400
- user=self.request.user
401
- ).prefetch_related(
402
- Prefetch(
403
- 'items',
404
- queryset=OrderItem.objects.select_related('product')
405
- )
406
- ).order_by('-created_at')
407
-
408
- # ✅ Good: API views with proper error handling
409
- from django.views import View
410
- from django.http import JsonResponse
411
- from django.views.decorators.csrf import csrf_exempt
412
- from django.utils.decorators import method_decorator
413
- import json
414
-
415
- @method_decorator(csrf_exempt, name='dispatch')
416
- class ProductAPIView(View):
417
- """API view for products."""
418
-
419
- def get(self, request, *args, **kwargs):
420
- """Get products as JSON."""
421
- try:
422
- products = Product.objects.active().with_category()
423
-
424
- # Apply filters
425
- category = request.GET.get('category')
426
- if category:
427
- products = products.by_category(category)
428
-
429
- data = [
430
- {
431
- 'id': str(product.id),
432
- 'name': product.name,
433
- 'slug': product.slug,
434
- 'price': str(product.price),
435
- 'category': product.category.name,
436
- 'in_stock': product.is_in_stock,
437
- }
438
- for product in products[:20] # Limit results
439
- ]
440
-
441
- return JsonResponse({'products': data})
442
-
443
- except Exception as e:
444
- return JsonResponse({'error': str(e)}, status=500)
445
-
446
- def post(self, request, *args, **kwargs):
447
- """Create new product via API."""
448
- if not request.user.is_authenticated or not request.user.is_staff:
449
- return JsonResponse({'error': 'Unauthorized'}, status=401)
450
-
451
- try:
452
- data = json.loads(request.body)
453
-
454
- # Validate required fields
455
- required_fields = ['name', 'slug', 'description', 'price', 'category_id']
456
- for field in required_fields:
457
- if field not in data:
458
- return JsonResponse({'error': f'Missing field: {field}'}, status=400)
459
-
460
- # Create product
461
- product = Product.objects.create(
462
- name=data['name'],
463
- slug=data['slug'],
464
- description=data['description'],
465
- price=data['price'],
466
- category_id=data['category_id'],
467
- stock_quantity=data.get('stock_quantity', 0),
468
- )
469
-
470
- return JsonResponse({
471
- 'id': str(product.id),
472
- 'name': product.name,
473
- 'slug': product.slug,
474
- }, status=201)
475
-
476
- except json.JSONDecodeError:
477
- return JsonResponse({'error': 'Invalid JSON'}, status=400)
478
- except Exception as e:
479
- return JsonResponse({'error': str(e)}, status=500)
480
- ```
481
-
482
- ### 2. Function-Based Views (FBVs) | 基于函数的视图
483
-
484
- ```python
485
- from django.shortcuts import render, redirect, get_object_or_404
486
- from django.contrib.auth.decorators import login_required
487
- from django.contrib import messages
488
- from django.db import transaction
489
- from django.http import HttpRequest, HttpResponse
490
- from django.core.paginator import Paginator
491
-
492
- # ✅ Good: Well-structured FBVs
493
-
494
- def product_list(request: HttpRequest) -> HttpResponse:
495
- """List products with filtering and pagination."""
496
- # Get base queryset
497
- products = Product.objects.active().with_category()
498
-
499
- # Apply filters
500
- category_slug = request.GET.get('category')
501
- if category_slug:
502
- products = products.by_category(category_slug)
503
-
504
- search_query = request.GET.get('q')
505
- if search_query:
506
- products = products.search(search_query)
507
-
508
- # Pagination
509
- paginator = Paginator(products, 20)
510
- page_number = request.GET.get('page')
511
- page_obj = paginator.get_page(page_number)
512
-
513
- context = {
514
- 'page_obj': page_obj,
515
- 'categories': Category.objects.filter(is_active=True),
516
- 'current_category': category_slug or '',
517
- 'search_query': search_query or '',
518
- }
519
-
520
- return render(request, 'products/list.html', context)
521
-
522
- @login_required
523
- @transaction.atomic
524
- def create_order(request: HttpRequest) -> HttpResponse:
525
- """Create a new order with items."""
526
- if request.method == 'POST':
527
- try:
528
- # Get cart items from session
529
- cart_items = request.session.get('cart', {})
530
- if not cart_items:
531
- messages.error(request, 'Your cart is empty.')
532
- return redirect('cart')
533
-
534
- # Calculate total
535
- total_amount = 0
536
- order_items = []
537
-
538
- for product_id, quantity in cart_items.items():
539
- product = get_object_or_404(Product, id=product_id, is_active=True)
540
-
541
- if product.stock_quantity < quantity:
542
- messages.error(
543
- request,
544
- f'Insufficient stock for {product.name}. Available: {product.stock_quantity}'
545
- )
546
- return redirect('cart')
547
-
548
- item_total = product.price * quantity
549
- total_amount += item_total
550
-
551
- order_items.append({
552
- 'product': product,
553
- 'quantity': quantity,
554
- 'unit_price': product.price,
555
- })
556
-
557
- # Create order
558
- order = Order.objects.create(
559
- user=request.user,
560
- total_amount=total_amount,
561
- shipping_address=request.POST.get('shipping_address', ''),
562
- notes=request.POST.get('notes', ''),
563
- )
564
-
565
- # Create order items and update stock
566
- for item_data in order_items:
567
- OrderItem.objects.create(
568
- order=order,
569
- product=item_data['product'],
570
- quantity=item_data['quantity'],
571
- unit_price=item_data['unit_price'],
572
- )
573
-
574
- # Reduce stock
575
- item_data['product'].reduce_stock(item_data['quantity'])
576
-
577
- # Clear cart
578
- request.session['cart'] = {}
579
-
580
- messages.success(request, f'Order {order.id} created successfully!')
581
- return redirect('order-detail', pk=order.id)
582
-
583
- except Exception as e:
584
- messages.error(request, f'Error creating order: {str(e)}')
585
- return redirect('cart')
586
-
587
- # GET request - show order form
588
- cart_items = request.session.get('cart', {})
589
- if not cart_items:
590
- messages.info(request, 'Your cart is empty.')
591
- return redirect('product-list')
592
-
593
- # Calculate cart total
594
- cart_products = []
595
- total = 0
596
-
597
- for product_id, quantity in cart_items.items():
598
- try:
599
- product = Product.objects.get(id=product_id, is_active=True)
600
- item_total = product.price * quantity
601
- total += item_total
602
-
603
- cart_products.append({
604
- 'product': product,
605
- 'quantity': quantity,
606
- 'total': item_total,
607
- })
608
- except Product.DoesNotExist:
609
- continue
610
-
611
- context = {
612
- 'cart_products': cart_products,
613
- 'total': total,
614
- }
615
-
616
- return render(request, 'orders/create.html', context)
617
-
618
- def add_to_cart(request: HttpRequest, product_id: int) -> HttpResponse:
619
- """Add product to cart."""
620
- product = get_object_or_404(Product, id=product_id, is_active=True)
621
-
622
- if not product.is_in_stock:
623
- messages.error(request, f'{product.name} is out of stock.')
624
- return redirect('product-detail', slug=product.slug)
625
-
626
- # Get or initialize cart
627
- cart = request.session.get('cart', {})
628
-
629
- # Add or update quantity
630
- if str(product_id) in cart:
631
- cart[str(product_id)] += 1
632
- else:
633
- cart[str(product_id)] = 1
634
-
635
- # Check stock limit
636
- if cart[str(product_id)] > product.stock_quantity:
637
- cart[str(product_id)] = product.stock_quantity
638
- messages.warning(
639
- request,
640
- f'Only {product.stock_quantity} items available for {product.name}.'
641
- )
642
- else:
643
- messages.success(request, f'{product.name} added to cart.')
644
-
645
- # Save cart to session
646
- request.session['cart'] = cart
647
-
648
- return redirect('product-detail', slug=product.slug)
649
- ```
650
-
651
- ## ORM Optimization | ORM 优化
652
-
653
- ### 1. Query Optimization | 查询优化
654
-
655
- ```python
656
- from django.db.models import Prefetch, Count, Sum, Avg, F, Q
657
- from django.db import connection
658
-
659
- # ✅ Good: Optimized queries
660
-
661
- def get_products_with_categories():
662
- """Get products with categories in a single query."""
663
- return Product.objects.select_related('category').filter(is_active=True)
664
-
665
- def get_orders_with_items():
666
- """Get orders with items and products in optimized queries."""
667
- return Order.objects.prefetch_related(
668
- Prefetch(
669
- 'items',
670
- queryset=OrderItem.objects.select_related('product__category')
671
- )
672
- ).select_related('user')
673
-
674
- def get_category_stats():
675
- """Get category statistics with aggregation."""
676
- return Category.objects.annotate(
677
- product_count=Count('products', filter=Q(products__is_active=True)),
678
- avg_price=Avg('products__price', filter=Q(products__is_active=True)),
679
- total_stock=Sum('products__stock_quantity', filter=Q(products__is_active=True))
680
- ).filter(is_active=True)
681
-
682
- def get_user_order_summary(user_id: int):
683
- """Get user order summary with aggregation."""
684
- return User.objects.filter(id=user_id).aggregate(
685
- total_orders=Count('orders'),
686
- total_spent=Sum('orders__total_amount'),
687
- avg_order_value=Avg('orders__total_amount')
688
- )
689
-
690
- def bulk_update_prices(category_id: int, percentage_increase: float):
691
- """Bulk update product prices using F expressions."""
692
- Product.objects.filter(category_id=category_id).update(
693
- price=F('price') * (1 + percentage_increase / 100)
694
- )
695
-
696
- def get_popular_products_by_category():
697
- """Get popular products grouped by category."""
698
- return Product.objects.select_related('category').annotate(
699
- order_count=Count('orderitem')
700
- ).filter(
701
- is_active=True,
702
- order_count__gt=0
703
- ).order_by('category__name', '-order_count')
704
-
705
- # ✅ Good: Using raw SQL when necessary
706
- def get_monthly_sales_report():
707
- """Get monthly sales report using raw SQL."""
708
- with connection.cursor() as cursor:
709
- cursor.execute("""
710
- SELECT
711
- DATE_TRUNC('month', created_at) as month,
712
- COUNT(*) as order_count,
713
- SUM(total_amount) as total_revenue
714
- FROM orders
715
- WHERE created_at >= %s
716
- GROUP BY DATE_TRUNC('month', created_at)
717
- ORDER BY month DESC
718
- """, [timezone.now() - timedelta(days=365)])
719
-
720
- columns = [col[0] for col in cursor.description]
721
- return [dict(zip(columns, row)) for row in cursor.fetchall()]
722
-
723
- # ❌ Bad: N+1 queries
724
- def bad_get_products_with_categories():
725
- products = Product.objects.filter(is_active=True)
726
- for product in products:
727
- print(product.category.name) # N+1 query!
728
-
729
- def bad_get_order_totals():
730
- orders = Order.objects.all()
731
- for order in orders:
732
- total = sum(item.total_price for item in order.items.all()) # N+1 query!
733
- ```
734
-
735
- ### 2. Database Indexes and Performance | 数据库索引和性能
736
-
737
- ```python
738
- # ✅ Good: Proper indexing in models
739
-
740
- class Product(TimeStampedModel):
741
- name = models.CharField(max_length=200)
742
- slug = models.SlugField(max_length=200, unique=True)
743
- price = models.DecimalField(max_digits=10, decimal_places=2)
744
- category = models.ForeignKey(Category, on_delete=models.PROTECT)
745
- is_active = models.BooleanField(default=True)
746
- featured = models.BooleanField(default=False)
747
-
748
- class Meta:
749
- indexes = [
750
- # Single column indexes
751
- models.Index(fields=['slug']),
752
- models.Index(fields=['is_active']),
753
- models.Index(fields=['featured']),
754
-
755
- # Composite indexes for common query patterns
756
- models.Index(fields=['category', 'is_active']),
757
- models.Index(fields=['is_active', 'featured']),
758
- models.Index(fields=['category', 'is_active', '-created_at']),
759
-
760
- # Partial indexes (PostgreSQL)
761
- models.Index(
762
- fields=['price'],
763
- condition=models.Q(is_active=True),
764
- name='active_products_price_idx'
765
- ),
766
- ]
767
-
768
- # ✅ Good: Database-specific optimizations
769
- from django.contrib.postgres.indexes import GinIndex
770
- from django.contrib.postgres.search import SearchVectorField
771
-
772
- class Article(TimeStampedModel):
773
- """Article model with full-text search (PostgreSQL)."""
774
- title = models.CharField(max_length=200)
775
- content = models.TextField()
776
- search_vector = SearchVectorField(null=True)
777
-
778
- class Meta:
779
- indexes = [
780
- GinIndex(fields=['search_vector']),
781
- ]
782
-
783
- # Custom migration for search vector
784
- # migrations/xxxx_add_search_vector.py
785
- from django.contrib.postgres.search import SearchVector
786
- from django.db import migrations
787
-
788
- def update_search_vector(apps, schema_editor):
789
- Article = apps.get_model('myapp', 'Article')
790
- Article.objects.update(
791
- search_vector=SearchVector('title', weight='A') + SearchVector('content', weight='B')
792
- )
793
-
794
- class Migration(migrations.Migration):
795
- dependencies = [
796
- ('myapp', '0001_initial'),
797
- ]
798
-
799
- operations = [
800
- migrations.RunPython(update_search_vector),
801
- ]
802
- ```
803
-
804
- ## Testing Django Applications | 测试 Django 应用程序
805
-
806
- ### 1. Model and View Testing | 模型和视图测试
807
-
808
- ```python
809
- from django.test import TestCase, Client
810
- from django.contrib.auth import get_user_model
811
- from django.urls import reverse
812
- from django.core.exceptions import ValidationError
813
- from decimal import Decimal
814
-
815
- User = get_user_model()
816
-
817
- class ProductModelTest(TestCase):
818
- """Test cases for Product model."""
819
-
820
- def setUp(self):
821
- """Set up test data."""
822
- self.category = Category.objects.create(
823
- name="Electronics",
824
- slug="electronics"
825
- )
826
- self.user = User.objects.create_user(
827
- username="testuser",
828
- email="test@example.com",
829
- password="testpass123"
830
- )
831
-
832
- def test_product_creation(self):
833
- """Test product creation with valid data."""
834
- product = Product.objects.create(
835
- name="Test Product",
836
- slug="test-product",
837
- description="Test description",
838
- price=Decimal('99.99'),
839
- stock_quantity=10,
840
- category=self.category
841
- )
842
-
843
- self.assertEqual(product.name, "Test Product")
844
- self.assertEqual(product.slug, "test-product")
845
- self.assertTrue(product.is_in_stock)
846
- self.assertEqual(str(product), "Test Product")
847
-
848
- def test_product_reduce_stock(self):
849
- """Test stock reduction functionality."""
850
- product = Product.objects.create(
851
- name="Test Product",
852
- slug="test-product",
853
- description="Test description",
854
- price=Decimal('99.99'),
855
- stock_quantity=10,
856
- category=self.category
857
- )
858
-
859
- # Test successful stock reduction
860
- product.reduce_stock(5)
861
- self.assertEqual(product.stock_quantity, 5)
862
-
863
- # Test insufficient stock error
864
- with self.assertRaises(ValueError):
865
- product.reduce_stock(10)
866
-
867
- def test_product_absolute_url(self):
868
- """Test product absolute URL."""
869
- product = Product.objects.create(
870
- name="Test Product",
871
- slug="test-product",
872
- description="Test description",
873
- price=Decimal('99.99'),
874
- category=self.category
875
- )
876
-
877
- expected_url = reverse('product-detail', kwargs={'slug': 'test-product'})
878
- self.assertEqual(product.get_absolute_url(), expected_url)
879
-
880
- class ProductViewTest(TestCase):
881
- """Test cases for Product views."""
882
-
883
- def setUp(self):
884
- """Set up test data."""
885
- self.client = Client()
886
- self.category = Category.objects.create(
887
- name="Electronics",
888
- slug="electronics"
889
- )
890
- self.product = Product.objects.create(
891
- name="Test Product",
892
- slug="test-product",
893
- description="Test description",
894
- price=Decimal('99.99'),
895
- stock_quantity=10,
896
- category=self.category
897
- )
898
-
899
- def test_product_list_view(self):
900
- """Test product list view."""
901
- response = self.client.get(reverse('product-list'))
902
-
903
- self.assertEqual(response.status_code, 200)
904
- self.assertContains(response, "Test Product")
905
- self.assertIn('products', response.context)
906
-
907
- def test_product_detail_view(self):
908
- """Test product detail view."""
909
- response = self.client.get(
910
- reverse('product-detail', kwargs={'slug': 'test-product'})
911
- )
912
-
913
- self.assertEqual(response.status_code, 200)
914
- self.assertEqual(response.context['product'], self.product)
915
- self.assertContains(response, "Test Product")
916
-
917
- def test_product_list_filtering(self):
918
- """Test product list filtering by category."""
919
- response = self.client.get(
920
- reverse('product-list'),
921
- {'category': 'electronics'}
922
- )
923
-
924
- self.assertEqual(response.status_code, 200)
925
- self.assertContains(response, "Test Product")
926
-
927
- def test_product_search(self):
928
- """Test product search functionality."""
929
- response = self.client.get(
930
- reverse('product-list'),
931
- {'q': 'Test'}
932
- )
933
-
934
- self.assertEqual(response.status_code, 200)
935
- self.assertContains(response, "Test Product")
936
-
937
- class OrderViewTest(TestCase):
938
- """Test cases for Order views."""
939
-
940
- def setUp(self):
941
- """Set up test data."""
942
- self.client = Client()
943
- self.user = User.objects.create_user(
944
- username="testuser",
945
- email="test@example.com",
946
- password="testpass123"
947
- )
948
- self.category = Category.objects.create(
949
- name="Electronics",
950
- slug="electronics"
951
- )
952
- self.product = Product.objects.create(
953
- name="Test Product",
954
- slug="test-product",
955
- description="Test description",
956
- price=Decimal('99.99'),
957
- stock_quantity=10,
958
- category=self.category
959
- )
960
-
961
- def test_create_order_requires_login(self):
962
- """Test that creating order requires authentication."""
963
- response = self.client.post(reverse('create-order'))
964
- self.assertEqual(response.status_code, 302) # Redirect to login
965
-
966
- def test_create_order_success(self):
967
- """Test successful order creation."""
968
- self.client.login(username="testuser", password="testpass123")
969
-
970
- # Add item to cart
971
- session = self.client.session
972
- session['cart'] = {str(self.product.id): 2}
973
- session.save()
974
-
975
- response = self.client.post(reverse('create-order'), {
976
- 'shipping_address': '123 Test St, Test City',
977
- 'notes': 'Test order'
978
- })
979
-
980
- self.assertEqual(response.status_code, 302) # Redirect after success
981
-
982
- # Check order was created
983
- order = Order.objects.get(user=self.user)
984
- self.assertEqual(order.total_amount, Decimal('199.98'))
985
- self.assertEqual(order.items.count(), 1)
986
-
987
- # Check stock was reduced
988
- self.product.refresh_from_db()
989
- self.assertEqual(self.product.stock_quantity, 8)
990
- ```
991
-
992
- ## Performance Checklist | 性能检查清单
993
-
994
- - [ ] Database queries are optimized with select_related and prefetch_related
995
- - [ ] Proper indexes are defined for common query patterns
996
- - [ ] N+1 query problems are avoided
997
- - [ ] Bulk operations are used for large data sets
998
- - [ ] Database-level constraints and validations are implemented
999
- - [ ] Caching is implemented for expensive queries
1000
- - [ ] Database connection pooling is configured
1001
- - [ ] Query performance is monitored and analyzed
1002
- - [ ] Raw SQL is used judiciously for complex queries
1003
- - [ ] Database migrations are optimized for production
1004
-
1005
- ## 性能检查清单
1006
-
1007
- - [ ] 使用 select_related 和 prefetch_related 优化数据库查询
1008
- - [ ] 为常见查询模式定义适当的索引
1009
- - [ ] 避免 N+1 查询问题
1010
- - [ ] 对大数据集使用批量操作
1011
- - [ ] 实现数据库级约束和验证
1012
- - [ ] 为昂贵的查询实现缓存
1013
- - [ ] 配置数据库连接池
1014
- - [ ] 监控和分析查询性能
1015
- - [ ] 明智地使用原始 SQL 进行复杂查询
1016
- - [ ] 为生产环境优化数据库迁移