upfynai-code 0.1.0 → 2.2.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 (340) hide show
  1. package/client/dist/api-docs.html +879 -0
  2. package/client/dist/assets/AppContent-CTSHQdyq.js +513 -0
  3. package/client/dist/assets/CanvasPanel-Cig0Mo9s.js +6 -0
  4. package/client/dist/assets/CanvasPanel-q4HEqNtV.css +1 -0
  5. package/client/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  6. package/client/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  7. package/client/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  8. package/client/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  9. package/client/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  10. package/client/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  11. package/client/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  12. package/client/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  13. package/client/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  14. package/client/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  15. package/client/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  16. package/client/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  17. package/client/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  18. package/client/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  19. package/client/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  20. package/client/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  21. package/client/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  22. package/client/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  23. package/client/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  24. package/client/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  25. package/client/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  26. package/client/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  27. package/client/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  28. package/client/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  29. package/client/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  30. package/client/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  31. package/client/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  32. package/client/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  33. package/client/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  34. package/client/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  35. package/client/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  36. package/client/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  37. package/client/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  38. package/client/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  39. package/client/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  40. package/client/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  41. package/client/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  42. package/client/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  43. package/client/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  44. package/client/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  45. package/client/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  46. package/client/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  47. package/client/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  48. package/client/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  49. package/client/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  50. package/client/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  51. package/client/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  52. package/client/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  53. package/client/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  54. package/client/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  55. package/client/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  56. package/client/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  57. package/client/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  58. package/client/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  59. package/client/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  60. package/client/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  61. package/client/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  62. package/client/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  63. package/client/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  64. package/client/dist/assets/LoginModal-silya-zP.js +11 -0
  65. package/client/dist/assets/MarkdownPreview-B3c7OEj6.js +1 -0
  66. package/client/dist/assets/Onboarding-Coxo6mFA.js +1 -0
  67. package/client/dist/assets/SetupForm-BzYOsbji.js +1 -0
  68. package/client/dist/assets/Tableau10-B-NsZVaP.js +1 -0
  69. package/client/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
  70. package/client/dist/assets/ar-SA-G6X2FPQ2-Bmw2-hDt.js +10 -0
  71. package/client/dist/assets/arc-BMqY7_Ci.js +1 -0
  72. package/client/dist/assets/array-BKyUJesY.js +1 -0
  73. package/client/dist/assets/az-AZ-76LH7QW2-Dh1le_qs.js +1 -0
  74. package/client/dist/assets/bg-BG-XCXSNQG7-Cbav8Z9z.js +5 -0
  75. package/client/dist/assets/blockDiagram-38ab4fdb-ChHJxsXw.js +118 -0
  76. package/client/dist/assets/bn-BD-2XOGV67Q-DCNjOaWz.js +5 -0
  77. package/client/dist/assets/c4Diagram-3d4e48cf-b8Xue4Z6.js +10 -0
  78. package/client/dist/assets/ca-ES-6MX7JW3Y-Dl_vM7NS.js +8 -0
  79. package/client/dist/assets/channel-CSnvHe_M.js +1 -0
  80. package/client/dist/assets/classDiagram-70f12bd4-BheP7Ggo.js +2 -0
  81. package/client/dist/assets/classDiagram-v2-f2320105-xtym7GEZ.js +2 -0
  82. package/client/dist/assets/clone-B75abXxS.js +1 -0
  83. package/client/dist/assets/createText-2e5e7dd3-_n4jI_fO.js +5 -0
  84. package/client/dist/assets/cs-CZ-2BRQDIVT-ftsKDdz4.js +11 -0
  85. package/client/dist/assets/da-DK-5WZEPLOC-DAjdwGRO.js +5 -0
  86. package/client/dist/assets/de-DE-XR44H4JA-BJXczHGT.js +8 -0
  87. package/client/dist/assets/directory-open-01563666-DWU9wJ6I.js +1 -0
  88. package/client/dist/assets/directory-open-4ed118d0-CunoC1EB.js +1 -0
  89. package/client/dist/assets/edges-e0da2a9e-CfPZr4YM.js +4 -0
  90. package/client/dist/assets/el-GR-BZB4AONW-DW2p_uy7.js +10 -0
  91. package/client/dist/assets/erDiagram-9861fffd-CF33V-Of.js +51 -0
  92. package/client/dist/assets/es-ES-U4NZUMDT-DLOIGnrl.js +9 -0
  93. package/client/dist/assets/eu-ES-A7QVB2H4-LJXbf89m.js +11 -0
  94. package/client/dist/assets/fa-IR-HGAKTJCU-Dvx65fgW.js +8 -0
  95. package/client/dist/assets/fi-FI-Z5N7JZ37-EoL65BQh.js +6 -0
  96. package/client/dist/assets/file-open-002ab408-DIuFHtCF.js +1 -0
  97. package/client/dist/assets/file-open-7c801643-684qeFg4.js +1 -0
  98. package/client/dist/assets/file-save-3189631c-C1wFhQhH.js +1 -0
  99. package/client/dist/assets/file-save-745eba88-Bb9F9Kg7.js +1 -0
  100. package/client/dist/assets/flowDb-956e92f1-HgoXVy2H.js +10 -0
  101. package/client/dist/assets/flowDiagram-66a62f08-tffoET0H.js +4 -0
  102. package/client/dist/assets/flowDiagram-v2-96b9c2cf-Byc3JCHh.js +1 -0
  103. package/client/dist/assets/flowchart-elk-definition-4a651766-DJbI2dpv.js +139 -0
  104. package/client/dist/assets/fr-FR-RHASNOE6-DNk_jdDs.js +9 -0
  105. package/client/dist/assets/ganttDiagram-c361ad54-2XX670FU.js +257 -0
  106. package/client/dist/assets/gitGraphDiagram-72cf32ee-CcUfruAo.js +70 -0
  107. package/client/dist/assets/gl-ES-HMX3MZ6V-dxzFjZlG.js +10 -0
  108. package/client/dist/assets/graph-BSbiMSBC.js +1 -0
  109. package/client/dist/assets/he-IL-6SHJWFNN-Cogsfdt1.js +10 -0
  110. package/client/dist/assets/hi-IN-IWLTKZ5I-L6wbgi4F.js +4 -0
  111. package/client/dist/assets/hu-HU-A5ZG7DT2-DSA6ZDsH.js +7 -0
  112. package/client/dist/assets/id-ID-SAP4L64H-BK_vGGS6.js +10 -0
  113. package/client/dist/assets/image-blob-reduce.esm-BLtmMM_J.js +2 -0
  114. package/client/dist/assets/index-3862675e-Bv32HUgT.js +1 -0
  115. package/client/dist/assets/index-B8wwD_Xo.css +1 -0
  116. package/client/dist/assets/index-BPwf8Fw3.js +27 -0
  117. package/client/dist/assets/index-D1urGMYu.js +95 -0
  118. package/client/dist/assets/infoDiagram-f8f76790-w4mR4pxn.js +7 -0
  119. package/client/dist/assets/init-Gi6I4Gst.js +1 -0
  120. package/client/dist/assets/it-IT-JPQ66NNP-BLdHYMhn.js +11 -0
  121. package/client/dist/assets/ja-JP-DBVTYXUO-B_vmexl_.js +8 -0
  122. package/client/dist/assets/journeyDiagram-49397b02-D9nmO17e.js +139 -0
  123. package/client/dist/assets/kaa-6HZHGXH3-5s-3jl6F.js +1 -0
  124. package/client/dist/assets/kab-KAB-ZGHBKWFO-2QaVDuSf.js +8 -0
  125. package/client/dist/assets/kk-KZ-P5N5QNE5-CTC52Vbi.js +1 -0
  126. package/client/dist/assets/km-KH-HSX4SM5Z-DxawH8UZ.js +11 -0
  127. package/client/dist/assets/ko-KR-MTYHY66A-CmosEM8_.js +9 -0
  128. package/client/dist/assets/ku-TR-6OUDTVRD-DbiLen4y.js +9 -0
  129. package/client/dist/assets/layout-jmt3H9tA.js +1 -0
  130. package/client/dist/assets/line-JTlRayUJ.js +1 -0
  131. package/client/dist/assets/linear-DJeB5p7x.js +1 -0
  132. package/client/dist/assets/lt-LT-XHIRWOB4-CH15wrjA.js +3 -0
  133. package/client/dist/assets/lv-LV-5QDEKY6T-dhgfPuCQ.js +7 -0
  134. package/client/dist/assets/mindmap-definition-fc14e90a-BOOrexmz.js +415 -0
  135. package/client/dist/assets/mr-IN-CRQNXWMA-3Gi6iq7A.js +13 -0
  136. package/client/dist/assets/my-MM-5M5IBNSE-CpH4rdJj.js +1 -0
  137. package/client/dist/assets/nb-NO-T6EIAALU-Du6iiGql.js +10 -0
  138. package/client/dist/assets/nl-NL-IS3SIHDZ-BGvsd1MT.js +8 -0
  139. package/client/dist/assets/nn-NO-6E72VCQL-B-odvJZW.js +8 -0
  140. package/client/dist/assets/oc-FR-POXYY2M6-COC8xNjo.js +8 -0
  141. package/client/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  142. package/client/dist/assets/pa-IN-N4M65BXN-CE21PUQH.js +4 -0
  143. package/client/dist/assets/path-CbwjOpE9.js +1 -0
  144. package/client/dist/assets/pdf-TYrZqVzP.js +12 -0
  145. package/client/dist/assets/pdf.worker-BA9kU3Pw.mjs +61080 -0
  146. package/client/dist/assets/percentages-BXMCSKIN-C9GT0OD3.js +199 -0
  147. package/client/dist/assets/pica-VkdyTzi8.js +2 -0
  148. package/client/dist/assets/pieDiagram-8a3498a8-Cvfh7Qr5.js +35 -0
  149. package/client/dist/assets/pl-PL-T2D74RX3-D4xFVSoT.js +9 -0
  150. package/client/dist/assets/pt-BR-5N22H2LF-CCq257gA.js +9 -0
  151. package/client/dist/assets/pt-PT-UZXXM6DQ-1l8gt5vA.js +9 -0
  152. package/client/dist/assets/quadrantDiagram-120e2f19-BA0js1aD.js +7 -0
  153. package/client/dist/assets/requirementDiagram-deff3bca-B0QNFfIn.js +52 -0
  154. package/client/dist/assets/ro-RO-JPDTUUEW-yosBW01E.js +11 -0
  155. package/client/dist/assets/roundRect-mAH3dD0p.js +1 -0
  156. package/client/dist/assets/ru-RU-B4JR7IUQ-8LkEJUix.js +9 -0
  157. package/client/dist/assets/sankeyDiagram-04a897e0-D4T9eCXn.js +8 -0
  158. package/client/dist/assets/sequenceDiagram-704730f1-CfBUTCrO.js +122 -0
  159. package/client/dist/assets/si-LK-N5RQ5JYF-D8rjbqtd.js +1 -0
  160. package/client/dist/assets/sk-SK-C5VTKIMK-Bg14sAzN.js +6 -0
  161. package/client/dist/assets/sl-SI-NN7IZMDC-CMTib6Zs.js +6 -0
  162. package/client/dist/assets/stateDiagram-587899a1-BGgvmVSZ.js +1 -0
  163. package/client/dist/assets/stateDiagram-v2-d93cdb3a-Qn3DpYuO.js +1 -0
  164. package/client/dist/assets/styles-6aaf32cf-IdVZLPrD.js +207 -0
  165. package/client/dist/assets/styles-9a916d00-BAC3L45X.js +160 -0
  166. package/client/dist/assets/styles-c10674c1-COhXxX8c.js +116 -0
  167. package/client/dist/assets/subset-shared.chunk-BWHnFai4.js +22 -0
  168. package/client/dist/assets/subset-worker.chunk-C8QUSruZ.js +1 -0
  169. package/client/dist/assets/sv-SE-XGPEYMSR-C1425rOF.js +10 -0
  170. package/client/dist/assets/svgDrawCommon-08f97a94-Cfk-fgnN.js +1 -0
  171. package/client/dist/assets/ta-IN-2NMHFXQM-BHHo1zpF.js +9 -0
  172. package/client/dist/assets/th-TH-HPSO5L25-CZVzm_WT.js +2 -0
  173. package/client/dist/assets/timeline-definition-85554ec2-VAvuJith.js +61 -0
  174. package/client/dist/assets/tr-TR-DEFEU3FU-DE1lclCq.js +7 -0
  175. package/client/dist/assets/uk-UA-QMV73CPH-D4lJZ85O.js +6 -0
  176. package/client/dist/assets/vendor-codemirror-BARtJV1V.js +16 -0
  177. package/client/dist/assets/vendor-codemirror-langs-52_y1wip.js +20 -0
  178. package/client/dist/assets/vendor-i18n-ByAl-gdx.js +1 -0
  179. package/client/dist/assets/vendor-icons-D33IkSIf.js +1 -0
  180. package/client/dist/assets/vendor-markdown-CIVH08vJ.js +298 -0
  181. package/client/dist/assets/vendor-react-CHoMc7ka.js +8 -0
  182. package/client/dist/assets/vendor-syntax-Djb62v3a.js +9 -0
  183. package/client/dist/assets/vendor-xterm-DBb3RXlu.js +66 -0
  184. package/client/dist/assets/vendor-xterm-DrlLKa8f.css +1 -0
  185. package/client/dist/assets/vi-VN-M7AON7JQ-Dgc_SShk.js +5 -0
  186. package/client/dist/assets/xychartDiagram-e933f94c-BeyVBJhb.js +7 -0
  187. package/client/dist/assets/zh-CN-LNUGB5OW-MH4Yh8in.js +10 -0
  188. package/client/dist/assets/zh-HK-E62DVLB3-D4XHehjx.js +1 -0
  189. package/client/dist/assets/zh-TW-RAJ6MFWO--efj3evj.js +9 -0
  190. package/client/dist/clear-cache.html +85 -0
  191. package/client/dist/convert-icons.md +53 -0
  192. package/client/dist/favicon.png +0 -0
  193. package/client/dist/favicon.svg +9 -0
  194. package/client/dist/generate-icons.js +49 -0
  195. package/client/dist/icons/claude-ai-icon.svg +1 -0
  196. package/client/dist/icons/codex-white.svg +3 -0
  197. package/client/dist/icons/codex.svg +3 -0
  198. package/client/dist/icons/cursor-white.svg +12 -0
  199. package/client/dist/icons/cursor.svg +1 -0
  200. package/client/dist/icons/icon-128x128.png +0 -0
  201. package/client/dist/icons/icon-128x128.svg +12 -0
  202. package/client/dist/icons/icon-144x144.png +0 -0
  203. package/client/dist/icons/icon-144x144.svg +12 -0
  204. package/client/dist/icons/icon-152x152.png +0 -0
  205. package/client/dist/icons/icon-152x152.svg +12 -0
  206. package/client/dist/icons/icon-192x192.png +0 -0
  207. package/client/dist/icons/icon-192x192.svg +12 -0
  208. package/client/dist/icons/icon-384x384.png +0 -0
  209. package/client/dist/icons/icon-384x384.svg +12 -0
  210. package/client/dist/icons/icon-512x512.png +0 -0
  211. package/client/dist/icons/icon-512x512.svg +12 -0
  212. package/client/dist/icons/icon-72x72.png +0 -0
  213. package/client/dist/icons/icon-72x72.svg +12 -0
  214. package/client/dist/icons/icon-96x96.png +0 -0
  215. package/client/dist/icons/icon-96x96.svg +12 -0
  216. package/client/dist/icons/icon-template.svg +12 -0
  217. package/client/dist/index.html +128 -0
  218. package/client/dist/logo-128.png +0 -0
  219. package/client/dist/logo-256.png +0 -0
  220. package/client/dist/logo-32.png +0 -0
  221. package/client/dist/logo-512.png +0 -0
  222. package/client/dist/logo-64.png +0 -0
  223. package/client/dist/logo.svg +17 -0
  224. package/client/dist/manifest.json +61 -0
  225. package/client/dist/mcp-docs.html +119 -0
  226. package/client/dist/screenshots/cli-selection.png +0 -0
  227. package/client/dist/screenshots/desktop-main.png +0 -0
  228. package/client/dist/screenshots/mobile-chat.png +0 -0
  229. package/client/dist/screenshots/tools-modal.png +0 -0
  230. package/client/dist/sw.js +19 -0
  231. package/commands/upfynai-connect.md +46 -0
  232. package/commands/upfynai-disconnect.md +31 -0
  233. package/commands/upfynai-doctor.md +99 -0
  234. package/commands/upfynai-export.md +49 -0
  235. package/commands/upfynai-local.md +82 -0
  236. package/commands/upfynai-status.md +75 -0
  237. package/commands/upfynai-stop.md +49 -0
  238. package/commands/upfynai-uninstall.md +58 -0
  239. package/commands/upfynai.md +50 -0
  240. package/package.json +106 -47
  241. package/scripts/build-client.js +17 -0
  242. package/scripts/fix-node-pty.js +67 -0
  243. package/scripts/install-commands.js +78 -0
  244. package/server/claude-sdk.js +714 -0
  245. package/server/cli.js +419 -0
  246. package/server/constants/config.js +5 -0
  247. package/server/cursor-cli.js +270 -0
  248. package/server/database/auth.db +0 -0
  249. package/server/database/db.js +606 -0
  250. package/server/database/init.sql +70 -0
  251. package/server/index.js +2269 -0
  252. package/server/load-env.js +26 -0
  253. package/server/mcp-server.js +620 -0
  254. package/server/middleware/auth.js +158 -0
  255. package/server/openai-codex.js +403 -0
  256. package/server/projects.js +1849 -0
  257. package/server/relay-client.js +314 -0
  258. package/server/routes/agent.js +1231 -0
  259. package/server/routes/auth.js +220 -0
  260. package/server/routes/cli-auth.js +263 -0
  261. package/server/routes/codex.js +344 -0
  262. package/server/routes/commands.js +601 -0
  263. package/server/routes/cursor.js +808 -0
  264. package/server/routes/git.js +1165 -0
  265. package/server/routes/mcp-utils.js +48 -0
  266. package/server/routes/mcp.js +552 -0
  267. package/server/routes/payments.js +172 -0
  268. package/server/routes/projects.js +549 -0
  269. package/server/routes/settings.js +178 -0
  270. package/server/routes/taskmaster.js +1964 -0
  271. package/server/routes/user.js +106 -0
  272. package/server/utils/commandParser.js +303 -0
  273. package/server/utils/gitConfig.js +24 -0
  274. package/server/utils/mcp-detector.js +198 -0
  275. package/server/utils/taskmaster-websocket.js +129 -0
  276. package/shared/modelConstants.js +67 -0
  277. package/LICENSE +0 -22
  278. package/bin/cli.js +0 -86
  279. package/dist/assets/CanvasPanel-B48gAKVY.js +0 -538
  280. package/dist/assets/CanvasPanel-B48gAKVY.js.map +0 -1
  281. package/dist/assets/CanvasPanel-BsOG3EVs.css +0 -1
  282. package/dist/assets/index-CEhTwG68.css +0 -1
  283. package/dist/assets/index-GqAGWpJI.js +0 -70
  284. package/dist/assets/index-GqAGWpJI.js.map +0 -1
  285. package/dist/index.html +0 -18
  286. package/index.html +0 -17
  287. package/src/App.tsx +0 -226
  288. package/src/components/canvas/CanvasPanel.tsx +0 -62
  289. package/src/components/canvas/layout/graph-builder.ts +0 -136
  290. package/src/components/canvas/shapes/CompactionNodeShape.tsx +0 -76
  291. package/src/components/canvas/shapes/SessionNodeShape.tsx +0 -93
  292. package/src/components/canvas/shapes/StatuslineWidgetShape.tsx +0 -125
  293. package/src/components/canvas/shapes/TextResponseNodeShape.tsx +0 -86
  294. package/src/components/canvas/shapes/ToolCallNodeShape.tsx +0 -107
  295. package/src/components/canvas/shapes/ToolResultNodeShape.tsx +0 -87
  296. package/src/components/canvas/shapes/shared-styles.ts +0 -35
  297. package/src/components/chat/ChatPanel.tsx +0 -96
  298. package/src/components/chat/InputBar.tsx +0 -81
  299. package/src/components/chat/MessageList.tsx +0 -130
  300. package/src/components/chat/PermissionDialog.tsx +0 -70
  301. package/src/components/layout/FolderSelector.tsx +0 -152
  302. package/src/components/layout/ModelSelector.tsx +0 -65
  303. package/src/components/layout/SessionManager.tsx +0 -115
  304. package/src/components/statusline/StatuslineBar.tsx +0 -114
  305. package/src/main.tsx +0 -10
  306. package/src/server/claude-session.ts +0 -156
  307. package/src/server/index.ts +0 -149
  308. package/src/services/stream-consumer.ts +0 -330
  309. package/src/statusline-core/bin/statusline.sh +0 -121
  310. package/src/statusline-core/commands/sls-config.md +0 -42
  311. package/src/statusline-core/commands/sls-doctor.md +0 -35
  312. package/src/statusline-core/commands/sls-help.md +0 -48
  313. package/src/statusline-core/commands/sls-layout.md +0 -38
  314. package/src/statusline-core/commands/sls-preview.md +0 -34
  315. package/src/statusline-core/commands/sls-theme.md +0 -40
  316. package/src/statusline-core/installer.js +0 -228
  317. package/src/statusline-core/layouts/compact.sh +0 -21
  318. package/src/statusline-core/layouts/full.sh +0 -62
  319. package/src/statusline-core/layouts/standard.sh +0 -39
  320. package/src/statusline-core/lib/core.sh +0 -389
  321. package/src/statusline-core/lib/helpers.sh +0 -81
  322. package/src/statusline-core/lib/json-parser.sh +0 -71
  323. package/src/statusline-core/themes/catppuccin.sh +0 -32
  324. package/src/statusline-core/themes/default.sh +0 -37
  325. package/src/statusline-core/themes/gruvbox.sh +0 -32
  326. package/src/statusline-core/themes/nord.sh +0 -32
  327. package/src/statusline-core/themes/tokyo-night.sh +0 -32
  328. package/src/store/canvas-store.ts +0 -50
  329. package/src/store/chat-store.ts +0 -60
  330. package/src/store/permission-store.ts +0 -29
  331. package/src/store/session-store.ts +0 -52
  332. package/src/store/statusline-store.ts +0 -160
  333. package/src/styles/global.css +0 -117
  334. package/src/themes/index.ts +0 -149
  335. package/src/types/canvas-graph.ts +0 -24
  336. package/src/types/sdk-messages.ts +0 -156
  337. package/src/types/statusline-fields.ts +0 -67
  338. package/src/vite-env.d.ts +0 -1
  339. package/tsconfig.json +0 -26
  340. package/vite.config.ts +0 -24
@@ -0,0 +1,606 @@
1
+ import { createClient } from '@libsql/client';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import crypto from 'crypto';
5
+ import { fileURLToPath } from 'url';
6
+ import { dirname } from 'path';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ // ANSI color codes
12
+ const colors = { reset: '\x1b[0m', bright: '\x1b[1m', cyan: '\x1b[36m', dim: '\x1b[2m' };
13
+ const c = {
14
+ info: (t) => `${colors.cyan}${t}${colors.reset}`,
15
+ bright: (t) => `${colors.bright}${t}${colors.reset}`,
16
+ dim: (t) => `${colors.dim}${t}${colors.reset}`,
17
+ };
18
+
19
+ // Database URL resolution (lazy — resolved on first access)
20
+ let _db = null;
21
+ let _dbUrl = null;
22
+ let _dbAuthToken = null;
23
+
24
+ function resolveDbConfig() {
25
+ if (_dbUrl) return;
26
+
27
+ if (process.env.TURSO_DATABASE_URL) {
28
+ _dbUrl = process.env.TURSO_DATABASE_URL.trim();
29
+ _dbAuthToken = process.env.TURSO_AUTH_TOKEN?.trim();
30
+ console.log(`${c.info('[DB]')} Using Turso: ${_dbUrl}`);
31
+ } else if (process.env.DATABASE_PATH) {
32
+ const dbPath = process.env.DATABASE_PATH.trim();
33
+ try { if (!fs.existsSync(path.dirname(dbPath))) fs.mkdirSync(path.dirname(dbPath), { recursive: true }); } catch { /* Vercel read-only */ }
34
+ _dbUrl = `file:${dbPath}`;
35
+ console.log(`${c.info('[DB]')} Using custom path: ${dbPath}`);
36
+ } else if (process.env.VERCEL) {
37
+ _dbUrl = 'file:/tmp/auth.db';
38
+ console.warn(`${c.info('[DB]')} WARNING: Ephemeral /tmp on Vercel. Set TURSO_DATABASE_URL for persistent data.`);
39
+ } else {
40
+ _dbUrl = `file:${path.join(__dirname, 'auth.db')}`;
41
+ console.log(`${c.info('[DB]')} Using local: ${_dbUrl}`);
42
+ }
43
+ }
44
+
45
+ function getDb() {
46
+ if (!_db) {
47
+ resolveDbConfig();
48
+ _db = createClient({ url: _dbUrl, ...(_dbAuthToken ? { authToken: _dbAuthToken } : {}) });
49
+ }
50
+ return _db;
51
+ }
52
+
53
+ // Lazy Proxy — defers createClient() until first DB call
54
+ const db = new Proxy({}, {
55
+ get(_, prop) {
56
+ const client = getDb();
57
+ const val = client[prop];
58
+ return typeof val === 'function' ? val.bind(client) : val;
59
+ }
60
+ });
61
+
62
+ // ─── Schema ─────────────────────────────────────────────────────────────────────
63
+
64
+ const INIT_SQL = `
65
+ CREATE TABLE IF NOT EXISTS users (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ username TEXT UNIQUE NOT NULL,
68
+ password_hash TEXT NOT NULL,
69
+ first_name TEXT,
70
+ last_name TEXT,
71
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
72
+ last_login DATETIME,
73
+ is_active BOOLEAN DEFAULT 1,
74
+ email TEXT,
75
+ phone TEXT,
76
+ git_name TEXT,
77
+ git_email TEXT,
78
+ has_completed_onboarding BOOLEAN DEFAULT 0,
79
+ access_override TEXT DEFAULT NULL,
80
+ user_code TEXT UNIQUE
81
+ );
82
+
83
+ CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
84
+ CREATE INDEX IF NOT EXISTS idx_users_active ON users(is_active);
85
+ CREATE INDEX IF NOT EXISTS idx_users_user_code ON users(user_code);
86
+
87
+ CREATE TABLE IF NOT EXISTS api_keys (
88
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
89
+ user_id INTEGER NOT NULL,
90
+ key_name TEXT NOT NULL,
91
+ api_key TEXT UNIQUE NOT NULL,
92
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
93
+ last_used DATETIME,
94
+ is_active BOOLEAN DEFAULT 1,
95
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
96
+ );
97
+
98
+ CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(api_key);
99
+ CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
100
+ CREATE INDEX IF NOT EXISTS idx_api_keys_active ON api_keys(is_active);
101
+
102
+ CREATE TABLE IF NOT EXISTS user_credentials (
103
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
104
+ user_id INTEGER NOT NULL,
105
+ credential_name TEXT NOT NULL,
106
+ credential_type TEXT NOT NULL,
107
+ credential_value TEXT NOT NULL,
108
+ description TEXT,
109
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
110
+ is_active BOOLEAN DEFAULT 1,
111
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
112
+ );
113
+
114
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_user_id ON user_credentials(user_id);
115
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_type ON user_credentials(credential_type);
116
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_active ON user_credentials(is_active);
117
+
118
+ CREATE TABLE IF NOT EXISTS relay_tokens (
119
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
120
+ user_id INTEGER NOT NULL,
121
+ token TEXT UNIQUE NOT NULL,
122
+ name TEXT NOT NULL DEFAULT 'default',
123
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
124
+ last_connected DATETIME,
125
+ is_active BOOLEAN DEFAULT 1,
126
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
127
+ );
128
+
129
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_token ON relay_tokens(token);
130
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_user_id ON relay_tokens(user_id);
131
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_active ON relay_tokens(is_active);
132
+
133
+ CREATE TABLE IF NOT EXISTS subscriptions (
134
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
135
+ user_id INTEGER NOT NULL,
136
+ plan_id TEXT NOT NULL,
137
+ status TEXT NOT NULL DEFAULT 'active',
138
+ amount INTEGER NOT NULL,
139
+ currency TEXT NOT NULL DEFAULT 'INR',
140
+ starts_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
141
+ expires_at DATETIME NOT NULL,
142
+ razorpay_order_id TEXT,
143
+ razorpay_payment_id TEXT,
144
+ razorpay_signature TEXT,
145
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
146
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
147
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
148
+ );
149
+
150
+ CREATE INDEX IF NOT EXISTS idx_subscriptions_user_id ON subscriptions(user_id);
151
+ CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);
152
+ CREATE INDEX IF NOT EXISTS idx_subscriptions_expires ON subscriptions(expires_at);
153
+
154
+ CREATE TABLE IF NOT EXISTS payments (
155
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
156
+ user_id INTEGER NOT NULL,
157
+ subscription_id INTEGER,
158
+ plan_id TEXT NOT NULL,
159
+ amount INTEGER NOT NULL,
160
+ currency TEXT NOT NULL DEFAULT 'INR',
161
+ status TEXT NOT NULL DEFAULT 'pending',
162
+ razorpay_order_id TEXT UNIQUE,
163
+ razorpay_payment_id TEXT,
164
+ razorpay_signature TEXT,
165
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
166
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
167
+ FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE SET NULL
168
+ );
169
+
170
+ CREATE INDEX IF NOT EXISTS idx_payments_user_id ON payments(user_id);
171
+ CREATE INDEX IF NOT EXISTS idx_payments_order_id ON payments(razorpay_order_id);
172
+ CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
173
+ `;
174
+
175
+ // ─── Migrations ─────────────────────────────────────────────────────────────────
176
+
177
+ const runMigrations = async () => {
178
+ try {
179
+ const result = await db.execute("PRAGMA table_info(users)");
180
+ const cols = result.rows.map(r => r.name);
181
+
182
+ const addCol = async (col, def) => {
183
+ if (!cols.includes(col)) {
184
+ await db.execute(`ALTER TABLE users ADD COLUMN ${col} ${def}`);
185
+ }
186
+ };
187
+
188
+ await addCol('git_name', 'TEXT');
189
+ await addCol('git_email', 'TEXT');
190
+ await addCol('has_completed_onboarding', 'BOOLEAN DEFAULT 0');
191
+ await addCol('email', 'TEXT');
192
+ await addCol('phone', 'TEXT');
193
+ await addCol('first_name', 'TEXT');
194
+ await addCol('last_name', 'TEXT');
195
+ await addCol('access_override', 'TEXT DEFAULT NULL');
196
+ await addCol('user_code', 'TEXT');
197
+ try { await db.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_users_user_code ON users(user_code)'); } catch { /* ignore */ }
198
+
199
+ // Backfill user_code (upc-001, upc-002, ...) for users missing it
200
+ try {
201
+ const noCode = await db.execute("SELECT id FROM users WHERE user_code IS NULL ORDER BY id ASC");
202
+ for (const row of noCode.rows) {
203
+ const code = `upc-${String(row.id).padStart(3, '0')}`;
204
+ await db.execute({ sql: 'UPDATE users SET user_code = ? WHERE id = ?', args: [code, row.id] });
205
+ }
206
+ if (noCode.rows.length > 0) console.log(`${c.info('[DB]')} Assigned user_code to ${noCode.rows.length} users`);
207
+ } catch (e) { console.warn('[DB] user_code backfill:', e.message); }
208
+
209
+ // Migrate old ck_ API keys → up-cli- prefix
210
+ try {
211
+ const migrated = await db.execute("UPDATE api_keys SET api_key = 'up-cli-' || SUBSTR(api_key, 4) WHERE api_key LIKE 'ck_%'");
212
+ if (migrated.rowsAffected > 0) console.log(`${c.info('[DB]')} Migrated ${migrated.rowsAffected} API keys: ck_ → up-cli-`);
213
+ } catch { /* empty table or already migrated */ }
214
+
215
+ // Backfill: ensure every user has records in all tables (relay_tokens, api_keys, subscriptions, payments, access_override)
216
+ try {
217
+ const allUsers = await db.execute('SELECT id, username, access_override FROM users WHERE is_active = 1');
218
+ let backfilled = 0;
219
+ for (const user of allUsers.rows) {
220
+ // Relay token
221
+ const tokens = await db.execute({ sql: 'SELECT id FROM relay_tokens WHERE user_id = ? LIMIT 1', args: [user.id] });
222
+ if (tokens.rows.length === 0) {
223
+ const token = 'upfyn_' + crypto.randomBytes(32).toString('hex');
224
+ await db.execute({ sql: 'INSERT INTO relay_tokens (user_id, token, name) VALUES (?, ?, ?)', args: [user.id, token, 'default'] });
225
+ backfilled++;
226
+ }
227
+ // API key
228
+ const keys = await db.execute({ sql: 'SELECT id FROM api_keys WHERE user_id = ? LIMIT 1', args: [user.id] });
229
+ if (keys.rows.length === 0) {
230
+ const apiKey = 'up-cli-' + crypto.randomBytes(32).toString('hex');
231
+ await db.execute({ sql: 'INSERT INTO api_keys (user_id, key_name, api_key) VALUES (?, ?, ?)', args: [user.id, 'default', apiKey] });
232
+ backfilled++;
233
+ }
234
+ // Yearly subscription (if none exists)
235
+ const subs = await db.execute({ sql: 'SELECT id FROM subscriptions WHERE user_id = ? LIMIT 1', args: [user.id] });
236
+ if (subs.rows.length === 0) {
237
+ const now = new Date();
238
+ const expiresAt = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000).toISOString();
239
+ const subResult = await db.execute({
240
+ sql: `INSERT INTO subscriptions (user_id, plan_id, status, amount, currency, starts_at, expires_at) VALUES (?, 'yearly', 'active', 49900, 'INR', ?, ?)`,
241
+ args: [user.id, now.toISOString(), expiresAt]
242
+ });
243
+ // Payment record for the subscription
244
+ const subId = Number(subResult.lastInsertRowid);
245
+ await db.execute({
246
+ sql: `INSERT INTO payments (user_id, subscription_id, plan_id, amount, currency, status, razorpay_order_id) VALUES (?, ?, 'yearly', 49900, 'INR', 'paid', ?)`,
247
+ args: [user.id, subId, `seed_order_${user.id}_${Date.now()}`]
248
+ });
249
+ backfilled++;
250
+ }
251
+ // Set access_override = 'paid' if not already set
252
+ if (!user.access_override || user.access_override !== 'paid') {
253
+ await db.execute({ sql: "UPDATE users SET access_override = 'paid' WHERE id = ?", args: [user.id] });
254
+ backfilled++;
255
+ }
256
+ }
257
+ if (backfilled > 0) console.log(`${c.info('[DB]')} Backfilled ${backfilled} records for existing users`);
258
+ } catch (e) { console.warn('[DB] Backfill warning:', e.message); }
259
+
260
+ console.log(`${c.info('[DB]')} Migrations complete`);
261
+ } catch (error) {
262
+ console.error('Migration error:', error.message);
263
+ throw error;
264
+ }
265
+ };
266
+
267
+ // ─── Initialize ─────────────────────────────────────────────────────────────────
268
+
269
+ const initializeDatabase = async () => {
270
+ try {
271
+ try { await db.execute('PRAGMA foreign_keys = ON'); } catch (e) { console.warn('[DB] PRAGMA foreign_keys not supported:', e.message); }
272
+
273
+ const stmts = INIT_SQL.split(';').map(s => s.trim()).filter(s => s.length > 0 && !s.startsWith('--'));
274
+ for (const stmt of stmts) {
275
+ try { await db.execute(stmt); } catch (e) { console.error('[DB] Statement failed:', stmt.substring(0, 80), e.message); throw e; }
276
+ }
277
+
278
+ console.log(`${c.info('[DB]')} Initialized`);
279
+ await runMigrations();
280
+ } catch (error) {
281
+ console.error('DB init error:', error.message);
282
+ throw error;
283
+ }
284
+ };
285
+
286
+ // ─── Helpers ────────────────────────────────────────────────────────────────────
287
+
288
+ const getRow = (result) => result.rows.length > 0 ? result.rows[0] : null;
289
+ const ensureForeignKeys = async () => { try { await db.execute('PRAGMA foreign_keys = ON'); } catch { /* Turso */ } };
290
+
291
+ // ─── User DB ────────────────────────────────────────────────────────────────────
292
+
293
+ const userDb = {
294
+ hasUsers: async () => {
295
+ const result = await db.execute('SELECT COUNT(*) as count FROM users');
296
+ return Number(getRow(result).count) > 0;
297
+ },
298
+
299
+ createUser: async (username, passwordHash, email = null, phone = null, firstName = null, lastName = null) => {
300
+ const result = await db.execute({
301
+ sql: 'INSERT INTO users (username, password_hash, email, phone, first_name, last_name) VALUES (?, ?, ?, ?, ?, ?)',
302
+ args: [username, passwordHash, email, phone, firstName, lastName]
303
+ });
304
+ const userId = Number(result.lastInsertRowid);
305
+ // Auto-assign user_code (upc-001, upc-002, ...)
306
+ const userCode = `upc-${String(userId).padStart(3, '0')}`;
307
+ try { await db.execute({ sql: 'UPDATE users SET user_code = ? WHERE id = ?', args: [userCode, userId] }); } catch { /* non-critical */ }
308
+ return { id: userId, username, first_name: firstName, last_name: lastName, user_code: userCode };
309
+ },
310
+
311
+ getUserByUsername: async (username) => {
312
+ const lower = (username || '').toLowerCase();
313
+ const result = await db.execute({
314
+ sql: 'SELECT * FROM users WHERE (LOWER(username) = ? OR LOWER(email) = ? OR phone = ?) AND is_active = 1',
315
+ args: [lower, lower, username]
316
+ });
317
+ return getRow(result);
318
+ },
319
+
320
+ updateLastLogin: async (userId) => {
321
+ await db.execute({ sql: 'UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?', args: [userId] });
322
+ },
323
+
324
+ getUserById: async (userId) => {
325
+ const result = await db.execute({
326
+ sql: 'SELECT id, username, first_name, last_name, email, phone, created_at, last_login, access_override, user_code FROM users WHERE id = ? AND is_active = 1',
327
+ args: [userId]
328
+ });
329
+ return getRow(result);
330
+ },
331
+
332
+ getFirstUser: async () => {
333
+ const result = await db.execute('SELECT id, username, first_name, last_name, email, phone, created_at, last_login, access_override, user_code FROM users WHERE is_active = 1 LIMIT 1');
334
+ return getRow(result);
335
+ },
336
+
337
+ updateGitConfig: async (userId, gitName, gitEmail) => {
338
+ await db.execute({ sql: 'UPDATE users SET git_name = ?, git_email = ? WHERE id = ?', args: [gitName, gitEmail, userId] });
339
+ },
340
+
341
+ getGitConfig: async (userId) => {
342
+ const result = await db.execute({ sql: 'SELECT git_name, git_email FROM users WHERE id = ?', args: [userId] });
343
+ return getRow(result);
344
+ },
345
+
346
+ completeOnboarding: async (userId) => {
347
+ await db.execute({ sql: 'UPDATE users SET has_completed_onboarding = 1 WHERE id = ?', args: [userId] });
348
+ },
349
+
350
+ hasCompletedOnboarding: async (userId) => {
351
+ const result = await db.execute({ sql: 'SELECT has_completed_onboarding FROM users WHERE id = ?', args: [userId] });
352
+ const row = getRow(result);
353
+ return row?.has_completed_onboarding === 1;
354
+ },
355
+
356
+ setAccessOverride: async (userId, value) => {
357
+ await db.execute({
358
+ sql: 'UPDATE users SET access_override = ? WHERE id = ?',
359
+ args: [value, userId]
360
+ });
361
+ }
362
+ };
363
+
364
+ // ─── API Keys DB ────────────────────────────────────────────────────────────────
365
+
366
+ const apiKeysDb = {
367
+ generateApiKey: () => 'up-cli-' + crypto.randomBytes(32).toString('hex'),
368
+
369
+ createApiKey: async (userId, keyName) => {
370
+ const apiKey = apiKeysDb.generateApiKey();
371
+ const result = await db.execute({
372
+ sql: 'INSERT INTO api_keys (user_id, key_name, api_key) VALUES (?, ?, ?)',
373
+ args: [userId, keyName, apiKey]
374
+ });
375
+ return { id: Number(result.lastInsertRowid), keyName, apiKey };
376
+ },
377
+
378
+ getApiKeys: async (userId) => {
379
+ const result = await db.execute({
380
+ sql: 'SELECT id, key_name, api_key, created_at, last_used, is_active FROM api_keys WHERE user_id = ? ORDER BY created_at DESC',
381
+ args: [userId]
382
+ });
383
+ return result.rows;
384
+ },
385
+
386
+ validateApiKey: async (apiKey) => {
387
+ const result = await db.execute({
388
+ sql: `SELECT u.id, u.username, ak.id as api_key_id
389
+ FROM api_keys ak JOIN users u ON ak.user_id = u.id
390
+ WHERE ak.api_key = ? AND ak.is_active = 1 AND u.is_active = 1`,
391
+ args: [apiKey]
392
+ });
393
+ const row = getRow(result);
394
+ if (row) {
395
+ await db.execute({ sql: 'UPDATE api_keys SET last_used = CURRENT_TIMESTAMP WHERE id = ?', args: [row.api_key_id] });
396
+ }
397
+ return row;
398
+ },
399
+
400
+ deleteApiKey: async (userId, apiKeyId) => {
401
+ await ensureForeignKeys();
402
+ const result = await db.execute({ sql: 'DELETE FROM api_keys WHERE id = ? AND user_id = ?', args: [apiKeyId, userId] });
403
+ return result.rowsAffected > 0;
404
+ },
405
+
406
+ toggleApiKey: async (userId, apiKeyId, isActive) => {
407
+ const result = await db.execute({
408
+ sql: 'UPDATE api_keys SET is_active = ? WHERE id = ? AND user_id = ?',
409
+ args: [isActive ? 1 : 0, apiKeyId, userId]
410
+ });
411
+ return result.rowsAffected > 0;
412
+ }
413
+ };
414
+
415
+ // ─── Credentials DB ─────────────────────────────────────────────────────────────
416
+
417
+ const credentialsDb = {
418
+ createCredential: async (userId, credentialName, credentialType, credentialValue, description = null) => {
419
+ const result = await db.execute({
420
+ sql: 'INSERT INTO user_credentials (user_id, credential_name, credential_type, credential_value, description) VALUES (?, ?, ?, ?, ?)',
421
+ args: [userId, credentialName, credentialType, credentialValue, description]
422
+ });
423
+ return { id: Number(result.lastInsertRowid), credentialName, credentialType };
424
+ },
425
+
426
+ getCredentials: async (userId, credentialType = null) => {
427
+ let sql = 'SELECT id, credential_name, credential_type, description, created_at, is_active FROM user_credentials WHERE user_id = ?';
428
+ const args = [userId];
429
+ if (credentialType) { sql += ' AND credential_type = ?'; args.push(credentialType); }
430
+ sql += ' ORDER BY created_at DESC';
431
+ return (await db.execute({ sql, args })).rows;
432
+ },
433
+
434
+ getActiveCredential: async (userId, credentialType) => {
435
+ const result = await db.execute({
436
+ sql: 'SELECT credential_value FROM user_credentials WHERE user_id = ? AND credential_type = ? AND is_active = 1 ORDER BY created_at DESC LIMIT 1',
437
+ args: [userId, credentialType]
438
+ });
439
+ return getRow(result)?.credential_value || null;
440
+ },
441
+
442
+ deleteCredential: async (userId, credentialId) => {
443
+ await ensureForeignKeys();
444
+ const result = await db.execute({ sql: 'DELETE FROM user_credentials WHERE id = ? AND user_id = ?', args: [credentialId, userId] });
445
+ return result.rowsAffected > 0;
446
+ },
447
+
448
+ toggleCredential: async (userId, credentialId, isActive) => {
449
+ const result = await db.execute({
450
+ sql: 'UPDATE user_credentials SET is_active = ? WHERE id = ? AND user_id = ?',
451
+ args: [isActive ? 1 : 0, credentialId, userId]
452
+ });
453
+ return result.rowsAffected > 0;
454
+ }
455
+ };
456
+
457
+ // Backward compat
458
+ const githubTokensDb = {
459
+ createGithubToken: (userId, tokenName, githubToken, description = null) => credentialsDb.createCredential(userId, tokenName, 'github_token', githubToken, description),
460
+ getGithubTokens: (userId) => credentialsDb.getCredentials(userId, 'github_token'),
461
+ getActiveGithubToken: (userId) => credentialsDb.getActiveCredential(userId, 'github_token'),
462
+ deleteGithubToken: (userId, tokenId) => credentialsDb.deleteCredential(userId, tokenId),
463
+ toggleGithubToken: (userId, tokenId, isActive) => credentialsDb.toggleCredential(userId, tokenId, isActive)
464
+ };
465
+
466
+ // ─── Plan Durations ─────────────────────────────────────────────────────────────
467
+
468
+ const PLAN_DURATIONS = {
469
+ monthly: 30,
470
+ 'half-yearly': 180,
471
+ yearly: 365,
472
+ };
473
+
474
+ // ─── Subscription DB ────────────────────────────────────────────────────────────
475
+
476
+ const subscriptionDb = {
477
+ getActiveSub: async (userId) => {
478
+ const result = await db.execute({
479
+ sql: `SELECT * FROM subscriptions WHERE user_id = ? AND status = 'active' AND expires_at > CURRENT_TIMESTAMP ORDER BY expires_at DESC LIMIT 1`,
480
+ args: [userId]
481
+ });
482
+ return getRow(result);
483
+ },
484
+
485
+ getAllSubs: async (userId) => {
486
+ const result = await db.execute({
487
+ sql: 'SELECT * FROM subscriptions WHERE user_id = ? ORDER BY created_at DESC',
488
+ args: [userId]
489
+ });
490
+ return result.rows;
491
+ },
492
+
493
+ createSub: async (userId, planId, amount, currency, razorpayOrderId, razorpayPaymentId, razorpaySignature) => {
494
+ const days = PLAN_DURATIONS[planId] || 30;
495
+
496
+ // Check if user has an active sub — extend from its expiry, otherwise start now
497
+ const existing = await subscriptionDb.getActiveSub(userId);
498
+ const startsAt = existing ? existing.expires_at : new Date().toISOString();
499
+ const startsDate = new Date(startsAt);
500
+ const expiresAt = new Date(startsDate.getTime() + days * 24 * 60 * 60 * 1000).toISOString();
501
+
502
+ const result = await db.execute({
503
+ sql: `INSERT INTO subscriptions (user_id, plan_id, status, amount, currency, starts_at, expires_at, razorpay_order_id, razorpay_payment_id, razorpay_signature) VALUES (?, ?, 'active', ?, ?, ?, ?, ?, ?, ?)`,
504
+ args: [userId, planId, amount, currency, startsAt, expiresAt, razorpayOrderId, razorpayPaymentId, razorpaySignature]
505
+ });
506
+ return { id: Number(result.lastInsertRowid), planId, status: 'active', startsAt, expiresAt };
507
+ },
508
+
509
+ cancelSub: async (userId, subId) => {
510
+ const result = await db.execute({
511
+ sql: `UPDATE subscriptions SET status = 'cancelled', updated_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?`,
512
+ args: [subId, userId]
513
+ });
514
+ return result.rowsAffected > 0;
515
+ },
516
+
517
+ expireOverdue: async () => {
518
+ const result = await db.execute(
519
+ `UPDATE subscriptions SET status = 'expired', updated_at = CURRENT_TIMESTAMP WHERE status = 'active' AND expires_at <= CURRENT_TIMESTAMP`
520
+ );
521
+ return result.rowsAffected;
522
+ },
523
+ };
524
+
525
+ // ─── Payment DB ─────────────────────────────────────────────────────────────────
526
+
527
+ const paymentDb = {
528
+ createPayment: async (userId, planId, amount, currency, razorpayOrderId) => {
529
+ const result = await db.execute({
530
+ sql: `INSERT INTO payments (user_id, plan_id, amount, currency, razorpay_order_id, status) VALUES (?, ?, ?, ?, ?, 'pending')`,
531
+ args: [userId, planId, amount, currency, razorpayOrderId]
532
+ });
533
+ return { id: Number(result.lastInsertRowid), razorpayOrderId };
534
+ },
535
+
536
+ getByOrderId: async (razorpayOrderId) => {
537
+ const result = await db.execute({
538
+ sql: 'SELECT * FROM payments WHERE razorpay_order_id = ?',
539
+ args: [razorpayOrderId]
540
+ });
541
+ return getRow(result);
542
+ },
543
+
544
+ markPaid: async (razorpayOrderId, razorpayPaymentId, razorpaySignature, subscriptionId) => {
545
+ await db.execute({
546
+ sql: `UPDATE payments SET status = 'paid', razorpay_payment_id = ?, razorpay_signature = ?, subscription_id = ? WHERE razorpay_order_id = ?`,
547
+ args: [razorpayPaymentId, razorpaySignature, subscriptionId, razorpayOrderId]
548
+ });
549
+ },
550
+
551
+ markFailed: async (razorpayOrderId) => {
552
+ await db.execute({
553
+ sql: `UPDATE payments SET status = 'failed' WHERE razorpay_order_id = ?`,
554
+ args: [razorpayOrderId]
555
+ });
556
+ },
557
+
558
+ getUserPayments: async (userId) => {
559
+ const result = await db.execute({
560
+ sql: 'SELECT * FROM payments WHERE user_id = ? ORDER BY created_at DESC',
561
+ args: [userId]
562
+ });
563
+ return result.rows;
564
+ },
565
+ };
566
+
567
+ // ─── Relay Tokens DB ────────────────────────────────────────────────────────────
568
+
569
+ const relayTokensDb = {
570
+ generateToken: () => 'upfyn_' + crypto.randomBytes(32).toString('hex'),
571
+
572
+ createToken: async (userId, name = 'default') => {
573
+ const token = relayTokensDb.generateToken();
574
+ await db.execute({ sql: 'INSERT INTO relay_tokens (user_id, token, name) VALUES (?, ?, ?)', args: [userId, token, name] });
575
+ return { token, name };
576
+ },
577
+
578
+ validateToken: async (token) => {
579
+ try {
580
+ const result = await db.execute({
581
+ sql: `SELECT rt.id, rt.user_id, rt.name, u.id as uid, u.username
582
+ FROM relay_tokens rt JOIN users u ON rt.user_id = u.id
583
+ WHERE rt.token = ? AND rt.is_active = 1 AND u.is_active = 1`,
584
+ args: [token]
585
+ });
586
+ const row = getRow(result);
587
+ if (row) await db.execute({ sql: 'UPDATE relay_tokens SET last_connected = CURRENT_TIMESTAMP WHERE id = ?', args: [row.id] });
588
+ return row;
589
+ } catch { return null; }
590
+ },
591
+
592
+ getTokens: async (userId) => {
593
+ return (await db.execute({ sql: 'SELECT id, name, token, created_at, last_connected, is_active FROM relay_tokens WHERE user_id = ? ORDER BY created_at DESC', args: [userId] })).rows;
594
+ },
595
+
596
+ deleteToken: async (userId, tokenId) => {
597
+ await ensureForeignKeys();
598
+ return (await db.execute({ sql: 'DELETE FROM relay_tokens WHERE id = ? AND user_id = ?', args: [tokenId, userId] })).rowsAffected > 0;
599
+ },
600
+
601
+ toggleToken: async (userId, tokenId, isActive) => {
602
+ return (await db.execute({ sql: 'UPDATE relay_tokens SET is_active = ? WHERE id = ? AND user_id = ?', args: [isActive ? 1 : 0, tokenId, userId] })).rowsAffected > 0;
603
+ }
604
+ };
605
+
606
+ export { db, initializeDatabase, userDb, apiKeysDb, credentialsDb, relayTokensDb, githubTokensDb, subscriptionDb, paymentDb, PLAN_DURATIONS };
@@ -0,0 +1,70 @@
1
+ -- Initialize authentication database
2
+ PRAGMA foreign_keys = ON;
3
+
4
+ -- Users table (single user system)
5
+ CREATE TABLE IF NOT EXISTS users (
6
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
7
+ username TEXT UNIQUE NOT NULL,
8
+ password_hash TEXT NOT NULL,
9
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
10
+ last_login DATETIME,
11
+ is_active BOOLEAN DEFAULT 1,
12
+ email TEXT,
13
+ phone TEXT,
14
+ git_name TEXT,
15
+ git_email TEXT,
16
+ has_completed_onboarding BOOLEAN DEFAULT 0
17
+ );
18
+
19
+ -- Indexes for performance
20
+ CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
21
+ CREATE INDEX IF NOT EXISTS idx_users_active ON users(is_active);
22
+
23
+ -- API Keys table for external API access
24
+ CREATE TABLE IF NOT EXISTS api_keys (
25
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
26
+ user_id INTEGER NOT NULL,
27
+ key_name TEXT NOT NULL,
28
+ api_key TEXT UNIQUE NOT NULL,
29
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
30
+ last_used DATETIME,
31
+ is_active BOOLEAN DEFAULT 1,
32
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
33
+ );
34
+
35
+ CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(api_key);
36
+ CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
37
+ CREATE INDEX IF NOT EXISTS idx_api_keys_active ON api_keys(is_active);
38
+
39
+ -- User credentials table for storing various tokens/credentials (GitHub, GitLab, etc.)
40
+ CREATE TABLE IF NOT EXISTS user_credentials (
41
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
42
+ user_id INTEGER NOT NULL,
43
+ credential_name TEXT NOT NULL,
44
+ credential_type TEXT NOT NULL, -- 'github_token', 'gitlab_token', 'bitbucket_token', etc.
45
+ credential_value TEXT NOT NULL,
46
+ description TEXT,
47
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
48
+ is_active BOOLEAN DEFAULT 1,
49
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
50
+ );
51
+
52
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_user_id ON user_credentials(user_id);
53
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_type ON user_credentials(credential_type);
54
+ CREATE INDEX IF NOT EXISTS idx_user_credentials_active ON user_credentials(is_active);
55
+
56
+ -- Relay tokens for local machine ↔ server connections
57
+ CREATE TABLE IF NOT EXISTS relay_tokens (
58
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
59
+ user_id INTEGER NOT NULL,
60
+ token TEXT UNIQUE NOT NULL,
61
+ name TEXT NOT NULL DEFAULT 'default',
62
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
63
+ last_connected DATETIME,
64
+ is_active BOOLEAN DEFAULT 1,
65
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
66
+ );
67
+
68
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_token ON relay_tokens(token);
69
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_user_id ON relay_tokens(user_id);
70
+ CREATE INDEX IF NOT EXISTS idx_relay_tokens_active ON relay_tokens(is_active);