@ngockhoale/ukit 1.1.6

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 (344) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/bin/ukit +30 -0
  5. package/manifests/platform.full.yaml +1194 -0
  6. package/package.json +71 -0
  7. package/scripts/bug/triage.mjs +37 -0
  8. package/scripts/index/build-index.mjs +35 -0
  9. package/scripts/index/query-index.mjs +92 -0
  10. package/scripts/index/refresh-index.mjs +85 -0
  11. package/scripts/release/verify-release.mjs +56 -0
  12. package/src/bug/triageBug.js +123 -0
  13. package/src/cli/adapters.js +148 -0
  14. package/src/cli/commands/diff.js +51 -0
  15. package/src/cli/commands/doctor.js +125 -0
  16. package/src/cli/commands/indexArgs.js +73 -0
  17. package/src/cli/commands/indexTools.js +509 -0
  18. package/src/cli/commands/install.js +293 -0
  19. package/src/cli/commands/memory.js +126 -0
  20. package/src/cli/commands/status.js +8 -0
  21. package/src/cli/commands/uninstall.js +51 -0
  22. package/src/cli/index.js +109 -0
  23. package/src/context/detectProjectContext.js +49 -0
  24. package/src/context/detectProviders.js +12 -0
  25. package/src/core/applyPlan.js +89 -0
  26. package/src/core/buildPlan.js +228 -0
  27. package/src/core/compact/index.js +294 -0
  28. package/src/core/compact/threshold.js +936 -0
  29. package/src/core/diffPlan.js +73 -0
  30. package/src/core/ensureGitignore.js +117 -0
  31. package/src/core/fileOps.js +188 -0
  32. package/src/core/memory/hygiene.js +160 -0
  33. package/src/core/memory/index.js +2 -0
  34. package/src/core/memory/retrieval.js +476 -0
  35. package/src/core/memory/store.js +202 -0
  36. package/src/core/metadata.js +132 -0
  37. package/src/core/migrateLegacy.js +139 -0
  38. package/src/core/output/index.js +1309 -0
  39. package/src/core/paths.js +13 -0
  40. package/src/core/report.js +17 -0
  41. package/src/core/router/advisor.js +42 -0
  42. package/src/core/router/index.js +2 -0
  43. package/src/core/router/router.js +164 -0
  44. package/src/core/runInstallPipeline.js +365 -0
  45. package/src/core/runtimeConfig.js +190 -0
  46. package/src/core/runtimePaths.js +24 -0
  47. package/src/core/status.js +186 -0
  48. package/src/core/token/index.js +328 -0
  49. package/src/core/uninstall.js +246 -0
  50. package/src/core/validation/confidence.js +89 -0
  51. package/src/core/validation/index.js +2 -0
  52. package/src/core/validation/validator.js +165 -0
  53. package/src/index/buildIndex.js +1392 -0
  54. package/src/index/gitHooks.js +109 -0
  55. package/src/index/importResolution.js +377 -0
  56. package/src/index/languageTools.js +127 -0
  57. package/src/index/paths.js +27 -0
  58. package/src/index/queryIndex.js +637 -0
  59. package/src/index/relatedTests.js +237 -0
  60. package/src/index/resolveContext.js +345 -0
  61. package/src/index/routeCatalog.js +258 -0
  62. package/src/index/taskRouting.js +677 -0
  63. package/src/index/verificationPlan.js +437 -0
  64. package/src/manifest/loadManifest.js +22 -0
  65. package/src/manifest/selectItems.js +78 -0
  66. package/src/manifest/validateManifest.js +115 -0
  67. package/src/render/buildVariables.js +39 -0
  68. package/src/render/renderTemplate.js +44 -0
  69. package/src/stack/detectStack.js +213 -0
  70. package/templates/.claude/agents/bug-debugger.md +57 -0
  71. package/templates/.claude/agents/feature-implementer.md +55 -0
  72. package/templates/.claude/config/providers.md +25 -0
  73. package/templates/.claude/hooks/auto-allow-bash.sh +155 -0
  74. package/templates/.claude/hooks/auto-prune-bash.sh +75 -0
  75. package/templates/.claude/hooks/block-dangerous.sh +54 -0
  76. package/templates/.claude/hooks/compress-output.sh +17 -0
  77. package/templates/.claude/hooks/protect-files.sh +37 -0
  78. package/templates/.claude/hooks/reinject-context.sh +28 -0
  79. package/templates/.claude/hooks/session-start.md +13 -0
  80. package/templates/.claude/hooks/skill-router.sh +1681 -0
  81. package/templates/.claude/hooks/verification-guard.sh +271 -0
  82. package/templates/.claude/settings.json +144 -0
  83. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  84. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  85. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  86. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  87. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  88. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  89. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  90. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  91. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  92. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  93. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  94. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  95. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  96. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  97. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  98. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  99. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  100. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  101. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  102. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  103. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  104. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  105. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  106. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  107. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  108. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  109. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  110. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  111. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  112. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  113. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  114. package/templates/.claude/skills/_shared/ooxml/schemas/mce/mc.xsd +75 -0
  115. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  116. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  117. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  118. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  119. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  120. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  121. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  122. package/templates/.claude/skills/_shared/ooxml/scripts/pack.py +159 -0
  123. package/templates/.claude/skills/_shared/ooxml/scripts/unpack.py +29 -0
  124. package/templates/.claude/skills/_shared/ooxml/scripts/validate.py +69 -0
  125. package/templates/.claude/skills/_shared/ooxml/scripts/validation/__init__.py +15 -0
  126. package/templates/.claude/skills/_shared/ooxml/scripts/validation/base.py +951 -0
  127. package/templates/.claude/skills/_shared/ooxml/scripts/validation/docx.py +274 -0
  128. package/templates/.claude/skills/_shared/ooxml/scripts/validation/pptx.py +315 -0
  129. package/templates/.claude/skills/_shared/ooxml/scripts/validation/redlining.py +279 -0
  130. package/templates/.claude/skills/backend-api/SKILL.md +26 -0
  131. package/templates/.claude/skills/canvas-design/LICENSE.txt +202 -0
  132. package/templates/.claude/skills/canvas-design/SKILL.md +130 -0
  133. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  134. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  135. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  136. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  137. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  138. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  139. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  140. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  141. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  142. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  143. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  144. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  145. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  146. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  147. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  148. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  149. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  150. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  151. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  152. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  153. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  154. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  155. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  156. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  157. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  158. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  159. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  160. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  161. package/templates/.claude/skills/code-review/SKILL.md +97 -0
  162. package/templates/.claude/skills/debugging-toolkit/SKILL.md +156 -0
  163. package/templates/.claude/skills/delivery/SKILL.md +92 -0
  164. package/templates/.claude/skills/discover-security/SKILL.md +86 -0
  165. package/templates/.claude/skills/docker-packaging/SKILL.md +60 -0
  166. package/templates/.claude/skills/docs-manager/SKILL.md +465 -0
  167. package/templates/.claude/skills/docs-manager/init-project-docs.sh +70 -0
  168. package/templates/.claude/skills/docs-manager/templates/README.md.template +50 -0
  169. package/templates/.claude/skills/docs-manager/templates/agent-roles.md.template +24 -0
  170. package/templates/.claude/skills/docs-manager/templates/coding-conventions.md.template +28 -0
  171. package/templates/.claude/skills/docs-manager/templates/memory.md.template +30 -0
  172. package/templates/.claude/skills/docs-manager/templates/onboarding.md.template +20 -0
  173. package/templates/.claude/skills/docs-manager/templates/project.md.template +26 -0
  174. package/templates/.claude/skills/docs-quality/SKILL.md +148 -0
  175. package/templates/.claude/skills/docx/LICENSE.txt +30 -0
  176. package/templates/.claude/skills/docx/SKILL.md +197 -0
  177. package/templates/.claude/skills/docx/docx-js.md +350 -0
  178. package/templates/.claude/skills/docx/ooxml.md +610 -0
  179. package/templates/.claude/skills/docx/scripts/__init__.py +1 -0
  180. package/templates/.claude/skills/docx/scripts/document.py +1276 -0
  181. package/templates/.claude/skills/docx/scripts/templates/comments.xml +3 -0
  182. package/templates/.claude/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  183. package/templates/.claude/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  184. package/templates/.claude/skills/docx/scripts/templates/commentsIds.xml +3 -0
  185. package/templates/.claude/skills/docx/scripts/templates/people.xml +3 -0
  186. package/templates/.claude/skills/docx/scripts/utilities.py +374 -0
  187. package/templates/.claude/skills/duraone/SKILL.md +204 -0
  188. package/templates/.claude/skills/duraone/references/backend.md +636 -0
  189. package/templates/.claude/skills/duraone/references/frontend.md +1506 -0
  190. package/templates/.claude/skills/duraone/references/sql.md +631 -0
  191. package/templates/.claude/skills/duraone/references/workflow.md +520 -0
  192. package/templates/.claude/skills/executing-plans/SKILL.md +76 -0
  193. package/templates/.claude/skills/file-organizer/SKILL.md +433 -0
  194. package/templates/.claude/skills/frontend/SKILL.md +26 -0
  195. package/templates/.claude/skills/frontend-design/LICENSE.txt +177 -0
  196. package/templates/.claude/skills/frontend-design/SKILL.md +42 -0
  197. package/templates/.claude/skills/frontend-vue/SKILL.md +127 -0
  198. package/templates/.claude/skills/frontend-vue/components/Control/Box.vue +137 -0
  199. package/templates/.claude/skills/frontend-vue/components/Control/Button.vue +93 -0
  200. package/templates/.claude/skills/frontend-vue/components/Control/ButtonBar.vue +29 -0
  201. package/templates/.claude/skills/frontend-vue/components/Control/ButtonFloat.vue +62 -0
  202. package/templates/.claude/skills/frontend-vue/components/Control/CheckButton.vue +75 -0
  203. package/templates/.claude/skills/frontend-vue/components/Control/Checkbox.vue +58 -0
  204. package/templates/.claude/skills/frontend-vue/components/Control/Datetime.vue +148 -0
  205. package/templates/.claude/skills/frontend-vue/components/Control/Dropdownlist.vue +156 -0
  206. package/templates/.claude/skills/frontend-vue/components/Control/Input.vue +106 -0
  207. package/templates/.claude/skills/frontend-vue/components/Control/Label.vue +38 -0
  208. package/templates/.claude/skills/frontend-vue/components/Control/Master/BoxColumn.vue +24 -0
  209. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Confirm.vue +33 -0
  210. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Info.vue +32 -0
  211. package/templates/.claude/skills/frontend-vue/components/Control/Popup/ModalInfo.vue +39 -0
  212. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Reject.vue +64 -0
  213. package/templates/.claude/skills/frontend-vue/components/Control/Tag.vue +82 -0
  214. package/templates/.claude/skills/frontend-vue/components/Control/Upload.vue +61 -0
  215. package/templates/.claude/skills/frontend-vue/components/ControlMobile/Dropdownlist.vue +103 -0
  216. package/templates/.claude/skills/frontend-vue/components/ControlMobile/PagingBar.vue +108 -0
  217. package/templates/.claude/skills/frontend-vue/components/ControlMobile/UploadImage.vue +137 -0
  218. package/templates/.claude/skills/frontend-vue/components/Grid/AG.vue +806 -0
  219. package/templates/.claude/skills/frontend-vue/components/Grid/AntTable.vue +253 -0
  220. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditor.vue +43 -0
  221. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditorEnable.vue +55 -0
  222. package/templates/.claude/skills/frontend-vue/components/Grid/HtmlTable.vue +40 -0
  223. package/templates/.claude/skills/frontend-vue/components/PDFViewer.vue +25 -0
  224. package/templates/.claude/skills/frontend-vue/components/Panel/FormView.vue +309 -0
  225. package/templates/.claude/skills/frontend-vue/components/Partial/Footer.vue +23 -0
  226. package/templates/.claude/skills/frontend-vue/components/Partial/Header.vue +265 -0
  227. package/templates/.claude/skills/frontend-vue/components/Partial/Sidebar.vue +122 -0
  228. package/templates/.claude/skills/frontend-vue/components/Template.vue +16 -0
  229. package/templates/.claude/skills/frontend-vue/components/View/Form.vue +89 -0
  230. package/templates/.claude/skills/frontend-vue/composables/indexDBStore.js +140 -0
  231. package/templates/.claude/skills/frontend-vue/composables/masterApi.js +362 -0
  232. package/templates/.claude/skills/frontend-vue/composables/state.js +578 -0
  233. package/templates/.claude/skills/frontend-vue/composables/useRequest.js +221 -0
  234. package/templates/.claude/skills/frontend-vue/composables/useSession.js +179 -0
  235. package/templates/.claude/skills/frontend-vue/composables/useTranslation.js +54 -0
  236. package/templates/.claude/skills/frontend-vue/composables/useWebSocket.js +257 -0
  237. package/templates/.claude/skills/frontend-vue/composables/userObj.js +111 -0
  238. package/templates/.claude/skills/frontend-vue/composables/utils.js +322 -0
  239. package/templates/.claude/skills/frontend-vue/reference/composables-example.vue +320 -0
  240. package/templates/.claude/skills/frontend-vue/reference/form-example.vue +183 -0
  241. package/templates/.claude/skills/frontend-vue/reference/grid-example.vue +147 -0
  242. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/[id].vue +106 -0
  243. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/index.vue +58 -0
  244. package/templates/.claude/skills/frontend-vue/reference/popup-example.vue +159 -0
  245. package/templates/.claude/skills/pdf/LICENSE.txt +30 -0
  246. package/templates/.claude/skills/pdf/SKILL.md +294 -0
  247. package/templates/.claude/skills/pdf/forms.md +205 -0
  248. package/templates/.claude/skills/pdf/reference.md +612 -0
  249. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  250. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  251. package/templates/.claude/skills/pdf/scripts/check_fillable_fields.py +12 -0
  252. package/templates/.claude/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  253. package/templates/.claude/skills/pdf/scripts/create_validation_image.py +41 -0
  254. package/templates/.claude/skills/pdf/scripts/extract_form_field_info.py +152 -0
  255. package/templates/.claude/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  256. package/templates/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  257. package/templates/.claude/skills/pdf-processing/SKILL.md +107 -0
  258. package/templates/.claude/skills/pdf-processing-pro/FORMS.md +610 -0
  259. package/templates/.claude/skills/pdf-processing-pro/OCR.md +137 -0
  260. package/templates/.claude/skills/pdf-processing-pro/SKILL.md +296 -0
  261. package/templates/.claude/skills/pdf-processing-pro/TABLES.md +626 -0
  262. package/templates/.claude/skills/pdf-processing-pro/scripts/analyze_form.py +307 -0
  263. package/templates/.claude/skills/postgres/SKILL.md +69 -0
  264. package/templates/.claude/skills/postgres/reference/fn_get_examples.sql +208 -0
  265. package/templates/.claude/skills/postgres/reference/fn_rpt_examples.sql +239 -0
  266. package/templates/.claude/skills/postgres/reference/utility_functions.sql +94 -0
  267. package/templates/.claude/skills/pptx/LICENSE.txt +30 -0
  268. package/templates/.claude/skills/pptx/SKILL.md +484 -0
  269. package/templates/.claude/skills/pptx/html2pptx.md +625 -0
  270. package/templates/.claude/skills/pptx/ooxml.md +427 -0
  271. package/templates/.claude/skills/pptx/scripts/html2pptx.js +979 -0
  272. package/templates/.claude/skills/pptx/scripts/inventory.py +1020 -0
  273. package/templates/.claude/skills/pptx/scripts/rearrange.py +231 -0
  274. package/templates/.claude/skills/pptx/scripts/replace.py +385 -0
  275. package/templates/.claude/skills/pptx/scripts/thumbnail.py +450 -0
  276. package/templates/.claude/skills/repo-maintenance/SKILL.md +97 -0
  277. package/templates/.claude/skills/research/EXAMPLES.md +434 -0
  278. package/templates/.claude/skills/research/REFERENCE.md +399 -0
  279. package/templates/.claude/skills/research/SKILL.md +136 -0
  280. package/templates/.claude/skills/root-cause-tracing/SKILL.md +174 -0
  281. package/templates/.claude/skills/root-cause-tracing/find-polluter.sh +63 -0
  282. package/templates/.claude/skills/sharing-skills/SKILL.md +194 -0
  283. package/templates/.claude/skills/sql-optimization-patterns/SKILL.md +493 -0
  284. package/templates/.claude/skills/subagent-driven-development/SKILL.md +189 -0
  285. package/templates/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
  286. package/templates/.claude/skills/systematic-debugging/SKILL.md +295 -0
  287. package/templates/.claude/skills/systematic-debugging/test-academic.md +14 -0
  288. package/templates/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
  289. package/templates/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
  290. package/templates/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
  291. package/templates/.claude/skills/test-driven-development/SKILL.md +364 -0
  292. package/templates/.claude/skills/testing-anti-patterns/SKILL.md +302 -0
  293. package/templates/.claude/skills/testing-quality/SKILL.md +97 -0
  294. package/templates/.claude/skills/verification-before-completion/SKILL.md +139 -0
  295. package/templates/.claude/skills/webapp-testing/LICENSE.txt +202 -0
  296. package/templates/.claude/skills/webapp-testing/SKILL.md +96 -0
  297. package/templates/.claude/skills/webapp-testing/examples/console_logging.py +35 -0
  298. package/templates/.claude/skills/webapp-testing/examples/element_discovery.py +40 -0
  299. package/templates/.claude/skills/webapp-testing/examples/static_html_automation.py +33 -0
  300. package/templates/.claude/skills/webapp-testing/scripts/with_server.py +106 -0
  301. package/templates/.claude/ukit/index/build-index.mjs +28 -0
  302. package/templates/.claude/ukit/index/cache-utils.mjs +140 -0
  303. package/templates/.claude/ukit/index/lib/index-core.mjs +2800 -0
  304. package/templates/.claude/ukit/index/query-index.mjs +150 -0
  305. package/templates/.claude/ukit/index/refresh-index.mjs +57 -0
  306. package/templates/.claude/ukit/index/reset-auto-permissions.mjs +76 -0
  307. package/templates/.claude/ukit/index/resolve-context.mjs +279 -0
  308. package/templates/.claude/ukit/index/route-catalog.mjs +258 -0
  309. package/templates/.claude/ukit/index/route-task.mjs +1994 -0
  310. package/templates/.claude/ukit/index/triage.mjs +133 -0
  311. package/templates/.claude/ukit/index/verify-context.mjs +689 -0
  312. package/templates/.claude/ukit/runtime/compact-threshold.mjs +1013 -0
  313. package/templates/.claude/ukit/runtime/output-compression.mjs +1340 -0
  314. package/templates/.claude/ukit/runtime/reinject-context.mjs +874 -0
  315. package/templates/.claude/ukit/runtime/token-utils.mjs +500 -0
  316. package/templates/.codex/README.md +83 -0
  317. package/templates/.codex/settings.json +187 -0
  318. package/templates/.gitignore +75 -0
  319. package/templates/AGENTS.md +116 -0
  320. package/templates/CLAUDE.md +93 -0
  321. package/templates/adapter-presets/antigravity/README.md +22 -0
  322. package/templates/adapter-presets/antigravity/rules.md +49 -0
  323. package/templates/adapter-presets/claude/settings.local.json +42 -0
  324. package/templates/adapter-presets/codex/settings.local.json +6 -0
  325. package/templates/adapter-presets/opencode/opencode.template.json +1 -0
  326. package/templates/docs/BUGFIX.md +20 -0
  327. package/templates/docs/BUG_INDEX.md +12 -0
  328. package/templates/docs/BUG_METRICS.md +7 -0
  329. package/templates/docs/BUG_TEMPLATE.md +13 -0
  330. package/templates/docs/CODE_MAP.md +35 -0
  331. package/templates/docs/INSTALL.md +113 -0
  332. package/templates/docs/MEMORY.md +49 -0
  333. package/templates/docs/PROJECT.md +50 -0
  334. package/templates/docs/UKIT_USAGE_GUIDE.md +147 -0
  335. package/templates/docs/WORKLOG.md +10 -0
  336. package/templates/ukit/README.md +14 -0
  337. package/templates/ukit/storage/cache/compact-history.json +3 -0
  338. package/templates/ukit/storage/cache/compact-pressure.json +1 -0
  339. package/templates/ukit/storage/cache/output-history.json +3 -0
  340. package/templates/ukit/storage/cache/prompt-cache.json +3 -0
  341. package/templates/ukit/storage/config.json +37 -0
  342. package/templates/ukit/storage/memory/projects/.gitkeep +2 -0
  343. package/templates/ukit/storage/memory/sessions/.gitkeep +0 -0
  344. package/templates/ukit/storage/memory/user.json +5 -0
@@ -0,0 +1,257 @@
1
+ /**
2
+ * @file useWebSocket.js
3
+ * @description WebSocket composable — quản lý kết nối realtime với auto-retry.
4
+ *
5
+ * Có 2 hàm chính:
6
+ * - useWebSocket() → Composable đầy đủ (auto connect onMounted, disconnect onUnmounted, retry, debug)
7
+ * - subscribeWebSocket() → Phiên bản đơn giản, chỉ cần truyền URL + callback onMessage
8
+ */
9
+ import { ref, onMounted, onUnmounted } from 'vue'
10
+
11
+ /**
12
+ * Vue composable quản lý WebSocket connection với auto-retry.
13
+ * Tự connect khi component mounted, disconnect khi unmounted.
14
+ *
15
+ * @param {string} url - WebSocket URL (vd: "wss://qas.duraoneportal.com/ws")
16
+ * @param {Object} [options={}] - Cấu hình
17
+ * @param {number} [options.maxRetries=5] - Số lần retry tối đa khi mất kết nối
18
+ * @param {number} [options.retryDelay=3000] - Khoảng cách giữa các lần retry (ms)
19
+ * @returns {Object} WebSocket controls:
20
+ * - connect() → Kết nối thủ công
21
+ * - disconnect() → Ngắt kết nối
22
+ * - send(data) → Gửi data (auto JSON.stringify), trả true/false
23
+ * - setupEventListeners(onMsg) → Đăng ký callback nhận message (data đã parse JSON)
24
+ * - isConnected {Ref<boolean>} → Trạng thái kết nối
25
+ * - error {Ref<string|null>} → Lỗi hiện tại
26
+ * - retryCount {Ref<number>} → Số lần đã retry
27
+ * - connectionStatus {Ref<string>} → 'initial'|'connecting'|'connected'|'disconnected'|'error'
28
+ * - lastError {Ref<Object|null>} → Chi tiết lỗi cuối cùng
29
+ * - getDebugInfo() → Object debug info đầy đủ
30
+ *
31
+ * @example
32
+ * const { send, isConnected, setupEventListeners } = useWebSocket("wss://example.com/ws")
33
+ * setupEventListeners((data) => { console.log("Received:", data) })
34
+ * send({ type: "ping" })
35
+ */
36
+ export function useWebSocket(url, options = {}) {
37
+ const socket = ref(null)
38
+ const isConnected = ref(false)
39
+ const error = ref(null)
40
+ const retryCount = ref(0)
41
+ const MAX_RETRIES = options.maxRetries || 5
42
+ const RETRY_DELAY = options.retryDelay || 3000
43
+ const connectionStatus = ref('initial') // 'initial', 'connecting', 'connected', 'disconnected', 'error'
44
+ const lastError = ref(null)
45
+
46
+ // Debug logging function
47
+ const debugLog = (type, message, data = null) => {
48
+ const timestamp = new Date().toISOString()
49
+ console.log(`[WebSocket ${type}] ${timestamp} - ${message}`, data)
50
+ }
51
+
52
+ const connect = () => {
53
+ if (!url) {
54
+ debugLog('ERROR', 'WebSocket URL is required')
55
+ error.value = 'WebSocket URL is required'
56
+ return
57
+ }
58
+
59
+ connectionStatus.value = 'connecting'
60
+ debugLog('INFO', `Attempting to connect to: ${url}`)
61
+
62
+ try {
63
+ socket.value = new WebSocket(url)
64
+
65
+ socket.value.onopen = () => {
66
+ connectionStatus.value = 'connected'
67
+ debugLog('SUCCESS', 'WebSocket connection opened successfully')
68
+ isConnected.value = true
69
+ retryCount.value = 0
70
+ error.value = null
71
+ lastError.value = null
72
+ }
73
+
74
+ socket.value.onclose = (event) => {
75
+ connectionStatus.value = 'disconnected'
76
+ debugLog('ERROR', 'WebSocket connection closed', event)
77
+ isConnected.value = false
78
+ error.value = `WebSocket closed: ${event.code} - ${event.reason}`
79
+ lastError.value = {
80
+ code: event.code,
81
+ reason: event.reason,
82
+ wasClean: event.wasClean
83
+ }
84
+ retryConnection()
85
+ }
86
+
87
+ socket.value.onerror = (err) => {
88
+ connectionStatus.value = 'error'
89
+ debugLog('ERROR', 'WebSocket error', err)
90
+ error.value = `WebSocket error: ${err.message}`
91
+ lastError.value = err
92
+ retryConnection()
93
+ }
94
+
95
+ socket.value.onmessage = (event) => {
96
+ debugLog('MESSAGE', 'Received message', event.data)
97
+ }
98
+
99
+ } catch (err) {
100
+ connectionStatus.value = 'error'
101
+ debugLog('ERROR', 'Failed to create WebSocket', err)
102
+ error.value = `Failed to create WebSocket: ${err.message}`
103
+ lastError.value = err
104
+ retryConnection()
105
+ }
106
+ }
107
+
108
+ const retryConnection = () => {
109
+ if (retryCount.value < MAX_RETRIES) {
110
+ retryCount.value++
111
+ debugLog('INFO', `Retrying connection (${retryCount.value}/${MAX_RETRIES})...`)
112
+ setTimeout(connect, RETRY_DELAY)
113
+ } else {
114
+ connectionStatus.value = 'error'
115
+ debugLog('ERROR', 'Max retry attempts reached')
116
+ error.value = 'Max retry attempts reached'
117
+ }
118
+ }
119
+
120
+ const getDebugInfo = () => ({
121
+ isConnected: isConnected.value,
122
+ error: error.value,
123
+ retryCount: retryCount.value,
124
+ url,
125
+ options,
126
+ connectionStatus: connectionStatus.value,
127
+ socketStatus: socket.value ? socket.value.readyState : null,
128
+ lastError: lastError.value
129
+ })
130
+
131
+ onMounted(connect)
132
+ onUnmounted(() => {
133
+ if (socket.value) {
134
+ debugLog('INFO', 'Disconnecting WebSocket')
135
+ socket.value.close()
136
+ socket.value = null
137
+ isConnected.value = false
138
+ error.value = null
139
+ connectionStatus.value = 'disconnected'
140
+ }
141
+ })
142
+
143
+ return {
144
+ connect,
145
+ disconnect: () => {
146
+ if (socket.value) {
147
+ debugLog('INFO', 'Disconnecting WebSocket')
148
+ socket.value.close()
149
+ socket.value = null
150
+ isConnected.value = false
151
+ error.value = null
152
+ connectionStatus.value = 'disconnected'
153
+ }
154
+ },
155
+ send: (data) => {
156
+ if (!socket.value || !isConnected.value) {
157
+ debugLog('ERROR', 'WebSocket is not connected')
158
+ return false
159
+ }
160
+
161
+ try {
162
+ debugLog('MESSAGE', 'Sending message', data)
163
+ socket.value.send(JSON.stringify(data))
164
+ return true
165
+ } catch (err) {
166
+ debugLog('ERROR', 'Failed to send message', err)
167
+ error.value = `Failed to send message: ${err.message}`
168
+ return false
169
+ }
170
+ },
171
+ setupEventListeners: (onMessage) => {
172
+ if (socket.value) {
173
+ socket.value.onmessage = (event) => {
174
+ try {
175
+ const data = JSON.parse(event.data)
176
+ debugLog('MESSAGE', 'Parsed message', data)
177
+ onMessage(data)
178
+ } catch (error) {
179
+ debugLog('ERROR', 'Error parsing message', error)
180
+ error.value = `Error parsing message: ${error.message}`
181
+ }
182
+ }
183
+ }
184
+ },
185
+ isConnected,
186
+ error,
187
+ retryCount,
188
+ getDebugInfo,
189
+ connectionStatus,
190
+ lastError
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Phiên bản đơn giản của WebSocket — chỉ subscribe nhận message.
196
+ * KHÔNG có auto-retry, KHÔNG bind vào lifecycle component.
197
+ * Phải gọi disconnect() thủ công khi không dùng nữa.
198
+ *
199
+ * @param {string} url - WebSocket URL
200
+ * @param {function(Object): void} onMessage - Callback nhận message (data đã parse JSON)
201
+ * @returns {Object} { isConnected: Ref<boolean>, disconnect: Function }
202
+ * @example
203
+ * const { isConnected, disconnect } = subscribeWebSocket("wss://example.com/ws", (data) => {
204
+ * console.log("New message:", data)
205
+ * })
206
+ * // Khi không dùng nữa:
207
+ * disconnect()
208
+ */
209
+ export function subscribeWebSocket(url, onMessage) {
210
+ const socket = ref(null)
211
+ const isConnected = ref(false)
212
+
213
+ // Create WebSocket connection
214
+ socket.value = new WebSocket(url)
215
+
216
+ // Handle connection open
217
+ socket.value.onopen = () => {
218
+ console.log('WebSocket connected')
219
+ isConnected.value = true
220
+ }
221
+
222
+ // Handle incoming messages
223
+ socket.value.onmessage = (event) => {
224
+ console.log('Received message:', event.data)
225
+ try {
226
+ const data = JSON.parse(event.data)
227
+ onMessage(data)
228
+ } catch (error) {
229
+ console.error('Error parsing message:', error)
230
+ }
231
+ }
232
+
233
+ // Handle connection close
234
+ socket.value.onclose = () => {
235
+ console.log('WebSocket disconnected')
236
+ isConnected.value = false
237
+ }
238
+
239
+ // Handle errors
240
+ socket.value.onerror = (error) => {
241
+ console.error('WebSocket error:', error)
242
+ }
243
+
244
+ // Return cleanup function
245
+ const disconnect = () => {
246
+ if (socket.value) {
247
+ socket.value.close()
248
+ socket.value = null
249
+ isConnected.value = false
250
+ }
251
+ }
252
+
253
+ return {
254
+ isConnected,
255
+ disconnect
256
+ }
257
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @file userObj.js
3
+ * @description Các hàm truy vấn thông tin nhân viên và gửi notification.
4
+ * Dữ liệu từ table "nhanvien" (nhân viên).
5
+ *
6
+ * @requires request - từ useRequest.js
7
+ * @requires get_schema - từ state.js
8
+ * @requires dayjs - từ utils.js
9
+ */
10
+
11
+ /**
12
+ * Lấy toàn bộ thông tin nhân viên theo username
13
+ * @param {string} manhanvien - Username (mã nhân viên)
14
+ * @returns {Promise<Object>} Object nhân viên hoặc {} nếu không tìm thấy
15
+ * @example const user = await getUserObjByUsername("nguyenvana")
16
+ */
17
+ export const getUserObjByUsername = async (manhanvien) => {
18
+ let to_return = {};
19
+ let data = {
20
+ schema: get_schema(),
21
+ table: "nhanvien",
22
+ conditions: JSON.stringify({ username: manhanvien }),
23
+ };
24
+ const resp = await request("/select", data, "get");
25
+ if (resp.length > 0) {
26
+ to_return = resp[0];
27
+ }
28
+ return to_return;
29
+ };
30
+
31
+ /**
32
+ * Lấy mã sales supervisor của nhân viên
33
+ * @param {string} manhanvien - Username
34
+ * @returns {Promise<string>} Mã salesup hoặc "" nếu không tìm thấy
35
+ */
36
+ export const getSalesupByUsername = async (manhanvien) => {
37
+ let masalesup = "";
38
+ let data = {
39
+ schema: get_schema(),
40
+ table: "nhanvien",
41
+ columns: ["masalesup"],
42
+ conditions: JSON.stringify({ username: manhanvien }),
43
+ };
44
+ const resp = await request("/select", data, "get");
45
+ if (resp.length > 0) {
46
+ masalesup = resp[0].masalesup;
47
+ }
48
+ return masalesup;
49
+ };
50
+
51
+ /**
52
+ * Lấy tên đầy đủ nhân viên theo username
53
+ * @param {string} manhanvien - Username
54
+ * @returns {Promise<string>} Tên nhân viên hoặc "" nếu không tìm thấy
55
+ */
56
+ export const getFullnameByUsername = async (manhanvien) => {
57
+ let tennhanvien = "";
58
+ let data = {
59
+ schema: get_schema(),
60
+ table: "nhanvien",
61
+ columns: ["tennhanvien"],
62
+ conditions: JSON.stringify({ username: manhanvien }),
63
+ };
64
+ const resp = await request("/select", data, "get");
65
+ if (resp.length > 0) {
66
+ tennhanvien = resp[0].tennhanvien;
67
+ }
68
+ return tennhanvien;
69
+ };
70
+
71
+ /**
72
+ * Gửi push notification đến user qua cả Android và iOS.
73
+ * Tự lấy danh sách token thiết bị, gửi noti, và lưu lịch sử vào DB.
74
+ * @param {string} username - Username người nhận
75
+ * @param {Object} [data={}] - Nội dung notification
76
+ * @param {string} data.title - Tiêu đề notification
77
+ * @param {string} data.message - Nội dung notification
78
+ * @example await sendNotiToUser("nguyenvana", { title: "Thông báo", message: "Bạn có agreement mới" })
79
+ */
80
+ export const sendNotiToUser = async (username, data = {}) => {
81
+ let noti_send = data;
82
+ let notiobj = await get_noti_token_list(username);
83
+ const android_list = notiobj.android;
84
+ const ios_list = notiobj.ios;
85
+ noti_send['os'] = 'android3';
86
+ noti_send['token'] = android_list;
87
+ requestSendnoti(noti_send);
88
+ noti_send['os'] = 'ios';
89
+ noti_send['token'] = ios_list;
90
+ requestSendnoti(noti_send);
91
+ let to_save_noti = {
92
+ username: username,
93
+ title: data.title,
94
+ message: data.message,
95
+ os: data.os,
96
+ token: data.token,
97
+ }
98
+ saveNotiToServer(to_save_noti);
99
+ };
100
+
101
+ /**
102
+ * Lưu lịch sử notification vào DB (table "notification")
103
+ * @param {Object} [data={}] - { username, title, message, os, token }
104
+ * @returns {Promise<Object>}
105
+ */
106
+ export const saveNotiToServer = async (data = {}) => {
107
+ data['send_time'] = dayjs().format("YYYY-MM-DD HH:mm:ss");
108
+ data['schema'] = get_schema();
109
+ data['table'] = 'notification';
110
+ await request("/save", data);
111
+ };
@@ -0,0 +1,322 @@
1
+ /**
2
+ * @file utils.js
3
+ * @description Utility functions dùng chung — auto-import toàn cục.
4
+ * Gồm: format date/number, validation, navigation, UI helpers, data transformation.
5
+ *
6
+ * Tất cả đều là pure functions (trừ go_to_page, go_back, show_message dùng side-effect).
7
+ */
8
+ import _dayjs from 'dayjs';
9
+
10
+ /**
11
+ * Wrapper dayjs — dùng thay cho import dayjs trực tiếp
12
+ * @param {...*} args - Tham số truyền vào dayjs (date string, Date object, ...)
13
+ * @returns {import('dayjs').Dayjs} dayjs instance
14
+ */
15
+ export function dayjs(...args) {
16
+ return _dayjs(...args)
17
+ };
18
+
19
+ /**
20
+ * Format ngày tháng theo type chỉ định
21
+ * @param {string|Date} date - Ngày cần format
22
+ * @param {"time"|"datetime"|"date"|"read_date"|"read_datetime"} [type] - Kiểu format
23
+ * - "time" → "HH:mm:ss"
24
+ * - "datetime" → "YYYY-MM-DD HH:mm:ss"
25
+ * - "date" → "YYYY-MM-DD"
26
+ * - "read_date" → "DD/MM/YYYY" (hiển thị cho user)
27
+ * - "read_datetime" → "DD/MM/YYYY HH:mm:ss"
28
+ * - mặc định → "YYYY-MM-DD"
29
+ * @returns {string} Chuỗi ngày đã format, trả "" nếu date null/blank
30
+ */
31
+ export const formatDate = (date, type) => {
32
+ if (check_is_null_or_blank(date)) {
33
+ return "";
34
+ }
35
+ if (type === "time") {
36
+ return dayjs(date).format("HH:mm:ss");
37
+ }
38
+ if (type === "datetime") {
39
+ return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
40
+ }
41
+ if (type === "date") {
42
+ return dayjs(date).format("YYYY-MM-DD");
43
+ }
44
+ if (type === "read_date") {
45
+ return dayjs(date).format("DD/MM/YYYY");
46
+ }
47
+ if (type === "read_datetime") {
48
+ return dayjs(date).format("DD/MM/YYYY HH:mm:ss");
49
+ }
50
+ return dayjs(date).format("YYYY-MM-DD");
51
+ };
52
+
53
+ /**
54
+ * Tạo mảng các ngày liên tiếp từ fromDate đến toDate
55
+ * @param {string|Date} fromDate - Ngày bắt đầu
56
+ * @param {string|Date} toDate - Ngày kết thúc
57
+ * @returns {Array<string>} Mảng ngày format "YYYY-MM-DD"
58
+ * @example getDateList("2024-01-01", "2024-01-03") → ["2024-01-01", "2024-01-02", "2024-01-03"]
59
+ */
60
+ export const getDateList = (fromDate, toDate) => {
61
+ const end = dayjs(toDate);
62
+ const dateArray = [];
63
+ let currentDate = dayjs(fromDate);
64
+ while (currentDate.isBefore(end) || currentDate.isSame(end, "day")) {
65
+ let formattedDate = currentDate.format("YYYY-MM-DD");
66
+ dateArray.push(formattedDate);
67
+ currentDate = currentDate.add(1, "day");
68
+ }
69
+ return dateArray;
70
+ };
71
+
72
+ /**
73
+ * Format số với dấu phân cách hàng nghìn và số thập phân
74
+ * @param {number|string} num - Số cần format
75
+ * @param {string} [separator="."] - Ký tự phân cách hàng nghìn
76
+ * @param {number} [decimal=2] - Số chữ số thập phân
77
+ * @returns {string} Số đã format, trả "" nếu num null/blank
78
+ * @example formatNumber(1234567.8) → "1.234.567.80"
79
+ */
80
+ export const formatNumber = (num, separator = ".", decimal = 2) => {
81
+ if (check_is_null_or_blank(num)) {
82
+ return "";
83
+ }
84
+ num = parseFloat(num);
85
+ return num.toFixed(decimal).replace(/\B(?=(\d{3})+(?!\d))/g, separator);
86
+ };
87
+
88
+ /**
89
+ * Lấy chiều cao màn hình (chỉ chạy client-side)
90
+ * @returns {number|undefined} window.innerHeight
91
+ */
92
+ export const screen_height = () => {
93
+ if (process.client) {
94
+ return window.innerHeight;
95
+ }
96
+ };
97
+
98
+ /**
99
+ * Kiểm tra arr1 có chứa tất cả phần tử của arr2 không
100
+ * @param {Array} arr1 - Mảng nguồn
101
+ * @param {Array} arr2 - Mảng cần kiểm tra
102
+ * @returns {boolean} true nếu arr1 chứa tất cả phần tử arr2
103
+ */
104
+ export const arraysContainAllElements = (arr1, arr2) => {
105
+ return arr2.every((element) => arr1.includes(element));
106
+ };
107
+
108
+ /**
109
+ * Bỏ dấu tiếng Việt — chuyển chuỗi có dấu thành không dấu (dùng cho search/filter)
110
+ * @param {string} str - Chuỗi tiếng Việt có dấu
111
+ * @returns {string} Chuỗi lowercase không dấu, đã loại ký tự đặc biệt
112
+ * @example bodautiengviet("Nguyễn Văn A") → "nguyen van a"
113
+ */
114
+ export const bodautiengviet = (str) => {
115
+ str = str.toString().toLowerCase();
116
+ str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, "a");
117
+ str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, "e");
118
+ str = str.replace(/ì|í|ị|ỉ|ĩ/g, "i");
119
+ str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, "o");
120
+ str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, "u");
121
+ str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, "y");
122
+ str = str.replace(/đ/g, "d");
123
+ str = str.replace(/!|@|%|\^|\*|\(|\)|\+|\=|\<|\>|\?|\/|,|\.|\:|\;|\'|\"|\&|\#|\[|\]|~|\$|_|`|-|{|}|\||\\/g, " ");
124
+ str = str.replace(/ + /g, " ");
125
+ str = str.trim();
126
+ return str;
127
+ };
128
+
129
+ /**
130
+ * Loại bỏ thẻ <a> trong các cột chỉ định của danh sách (mutate trực tiếp)
131
+ * @param {Array<Object>} lst - Mảng objects cần xử lý
132
+ * @param {Array<string>} col - Danh sách tên cột cần loại HTML
133
+ * @returns {Array<Object>} Mảng đã xử lý (cùng reference)
134
+ */
135
+ export const remove_html = (lst, col) => {
136
+ for (let i = 0; i < lst.length; i++) {
137
+ for (let j = 0; j < col.length; j++) {
138
+ if (!check_is_null_or_blank(lst[i][col[j]])) {
139
+ if (typeof lst[i][col[j]] === "string") {
140
+ if (lst[i][col[j]].includes("<a")) {
141
+ lst[i][col[j]] = remove_a_tag(lst[i][col[j]]);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ return lst;
148
+ };
149
+
150
+ /**
151
+ * Kiểm tra giá trị null, undefined, rỗng, hoặc object/array trống
152
+ * @param {*} value - Giá trị cần kiểm tra
153
+ * @returns {boolean} true nếu value là null/undefined/""/[]/{}
154
+ * @example
155
+ * check_is_null_or_blank(null) → true
156
+ * check_is_null_or_blank("") → true
157
+ * check_is_null_or_blank([]) → true
158
+ * check_is_null_or_blank({}) → true
159
+ * check_is_null_or_blank("abc") → false
160
+ */
161
+ export const check_is_null_or_blank = (value) => {
162
+ if (value == null) {
163
+ return true;
164
+ }
165
+ let to_return = typeof value === "undefined" || value === "undefined" || value === undefined || value === "" || value == {};
166
+ if (typeof value === "object") {
167
+ if (value.length == 0) {
168
+ to_return = true;
169
+ }
170
+ if (Object.keys(value).length === 0) {
171
+ to_return = true;
172
+ }
173
+ }
174
+ return to_return;
175
+ };
176
+
177
+ /**
178
+ * Kiểm tra giá trị bằng 0 (bao gồm cả string "0", "0.00")
179
+ * @param {*} value - Giá trị cần kiểm tra
180
+ * @returns {boolean} true nếu value là 0/"0"/"0.00"/undefined
181
+ */
182
+ export const check_is_zero = (value) => {
183
+ if (isNaN(value)) {
184
+ return false;
185
+ }
186
+ return typeof value === "undefined" || value === "0" || value === "0.00" || value === 0 || value == 0;
187
+ };
188
+
189
+ /**
190
+ * Cuộn trang lên đầu (smooth scroll)
191
+ */
192
+ export const move_to_top = () => {
193
+ window.scrollTo({
194
+ top: 0,
195
+ behavior: "smooth",
196
+ });
197
+ };
198
+
199
+ /**
200
+ * Chuyển trang bằng Vue Router
201
+ * @param {string} page - Đường dẫn trang (vd: "/master/branch")
202
+ * @param {Object|string} [query=""] - Query params (vd: { id: 123 })
203
+ */
204
+ export const go_to_page = (page, query = "") => {
205
+ const router = useRouter();
206
+ if (query === "") {
207
+ router.push({ path: page });
208
+ } else {
209
+ router.push({ path: page, query: query });
210
+ }
211
+ };
212
+
213
+ /**
214
+ * Quay lại trang trước. Nếu không có history → về page chỉ định hoặc "/"
215
+ * @param {string} [page] - Trang fallback nếu không có history
216
+ */
217
+ export const go_back = (page) => {
218
+ const router = useRouter();
219
+ if (window.history.length > 1) {
220
+ router.back(); // Go back to the previous page
221
+ } else {
222
+ if (check_is_null_or_blank(page)) {
223
+ go_to_page("/");
224
+ } else {
225
+ go_to_page(page);
226
+ }
227
+ }
228
+ };
229
+
230
+ /**
231
+ * Tạm dừng thực thi trong khoảng thời gian chỉ định
232
+ * @param {number} ms - Thời gian chờ (milliseconds)
233
+ * @returns {Promise<void>}
234
+ * @example await sleep(1000) // chờ 1 giây
235
+ */
236
+ export const sleep = (ms) => {
237
+ return new Promise((resolve) => setTimeout(resolve, ms));
238
+ };
239
+
240
+ import { message } from "ant-design-vue";
241
+ /**
242
+ * Hiển thị thông báo toast (Ant Design Vue message)
243
+ * @param {"success"|"error"|"warning"|"info"|"loading"} type - Loại thông báo
244
+ * @param {string} content - Nội dung hiển thị
245
+ * @param {number} [duration=3] - Thời gian hiển thị (giây)
246
+ * @example show_message("success", "Lưu thành công!")
247
+ * @example show_message("error", "Có lỗi xảy ra", 5)
248
+ */
249
+ export const show_message = (type, content, duration = 3) => {
250
+ message[type]({
251
+ content: content,
252
+ duration: duration,
253
+ });
254
+ };
255
+
256
+ /**
257
+ * Chuyển đổi mảng object thành format dropdown {value, label}
258
+ * Label tự động dịch qua hàm t().
259
+ * @param {Array<Object>} lst - Mảng dữ liệu gốc
260
+ * @param {string} value_col - Tên cột làm value
261
+ * @param {string} label_col - Tên cột làm label
262
+ * @returns {Array<{value: *, label: string}>} Mảng dropdown options
263
+ * @example
264
+ * convertToDropdownValue([{code: "VN", name: "Vietnam"}], "code", "name")
265
+ * → [{value: "VN", label: "Vietnam"}]
266
+ */
267
+ export const convertToDropdownValue = (lst, value_col, label_col) => {
268
+ let to_return = lst.map((obj) => {
269
+ return {
270
+ value: obj[value_col],
271
+ label: t(obj[label_col]),
272
+ };
273
+ });
274
+ return to_return;
275
+ };
276
+
277
+ /**
278
+ * Chuyển mảng objects thành object key-value (lookup map)
279
+ * @param {Array<Object>} lst - Mảng dữ liệu gốc
280
+ * @param {string} key_col - Tên cột làm key
281
+ * @param {string} value_col - Tên cột làm value
282
+ * @returns {Object} Object dạng { [key]: value }
283
+ * @example
284
+ * convertListToObject([{id: 1, name: "A"}, {id: 2, name: "B"}], "id", "name")
285
+ * → { 1: "A", 2: "B" }
286
+ */
287
+ export const convertListToObject = (lst, key_col, value_col) => {
288
+ let to_return = {};
289
+ lst.map((obj) => {
290
+ to_return[obj[key_col]] = obj[value_col];
291
+ });
292
+ return to_return;
293
+ };
294
+
295
+ /**
296
+ * Trích xuất 1 field từ mảng objects thành mảng giá trị (pluck)
297
+ * @param {Array<Object>} lst - Mảng dữ liệu gốc
298
+ * @param {string} key_col - Tên cột cần trích
299
+ * @returns {Array} Mảng giá trị của field đó
300
+ * @example
301
+ * convertListToListOfField([{id: 1, name: "A"}, {id: 2, name: "B"}], "name")
302
+ * → ["A", "B"]
303
+ */
304
+ export const convertListToListOfField = (lst, key_col) => {
305
+ let to_return = [];
306
+ lst.map((obj) => {
307
+ to_return.push(obj[key_col]);
308
+ });
309
+ return to_return;
310
+ };
311
+ /**
312
+ * Sắp xếp mảng dropdown theo value tăng dần (parse int)
313
+ * @param {Array<{value: string|number}>} list - Mảng dropdown options
314
+ * @returns {Array<{value: string|number}>} Mảng đã sắp xếp
315
+ */
316
+ export function sortListByValueAsc(list) {
317
+ return list.sort((a, b) => {
318
+ const aValue = parseInt(a.value);
319
+ const bValue = parseInt(b.value);
320
+ return aValue - bValue;
321
+ });
322
+ }