@mdguggenbichler/slugbase-core 0.0.1

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 (381) hide show
  1. package/backend/dist/app-factory.d.ts +17 -0
  2. package/backend/dist/app-factory.d.ts.map +1 -0
  3. package/backend/dist/app-factory.js +106 -0
  4. package/backend/dist/app-factory.js.map +1 -0
  5. package/backend/dist/auth/authorization.d.ts +25 -0
  6. package/backend/dist/auth/authorization.d.ts.map +1 -0
  7. package/backend/dist/auth/authorization.js +100 -0
  8. package/backend/dist/auth/authorization.js.map +1 -0
  9. package/backend/dist/auth/jwt.d.ts +5 -0
  10. package/backend/dist/auth/jwt.d.ts.map +1 -0
  11. package/backend/dist/auth/jwt.js +34 -0
  12. package/backend/dist/auth/jwt.js.map +1 -0
  13. package/backend/dist/auth/oidc.d.ts +4 -0
  14. package/backend/dist/auth/oidc.d.ts.map +1 -0
  15. package/backend/dist/auth/oidc.js +201 -0
  16. package/backend/dist/auth/oidc.js.map +1 -0
  17. package/backend/dist/config/cloud-providers.d.ts +18 -0
  18. package/backend/dist/config/cloud-providers.d.ts.map +1 -0
  19. package/backend/dist/config/cloud-providers.js +60 -0
  20. package/backend/dist/config/cloud-providers.js.map +1 -0
  21. package/backend/dist/config/cookies.d.ts +17 -0
  22. package/backend/dist/config/cookies.d.ts.map +1 -0
  23. package/backend/dist/config/cookies.js +26 -0
  24. package/backend/dist/config/cookies.js.map +1 -0
  25. package/backend/dist/config/mode.d.ts +7 -0
  26. package/backend/dist/config/mode.d.ts.map +1 -0
  27. package/backend/dist/config/mode.js +7 -0
  28. package/backend/dist/config/mode.js.map +1 -0
  29. package/backend/dist/config/swagger.d.ts +2 -0
  30. package/backend/dist/config/swagger.d.ts.map +1 -0
  31. package/backend/dist/config/swagger.js +76 -0
  32. package/backend/dist/config/swagger.js.map +1 -0
  33. package/backend/dist/config.d.ts +29 -0
  34. package/backend/dist/config.d.ts.map +1 -0
  35. package/backend/dist/config.js +41 -0
  36. package/backend/dist/config.js.map +1 -0
  37. package/backend/dist/db/index.d.ts +14 -0
  38. package/backend/dist/db/index.d.ts.map +1 -0
  39. package/backend/dist/db/index.js +114 -0
  40. package/backend/dist/db/index.js.map +1 -0
  41. package/backend/dist/db/migrate-slug-nullable.d.ts +10 -0
  42. package/backend/dist/db/migrate-slug-nullable.d.ts.map +1 -0
  43. package/backend/dist/db/migrate-slug-nullable.js +87 -0
  44. package/backend/dist/db/migrate-slug-nullable.js.map +1 -0
  45. package/backend/dist/db/migrations/001_migrate_slug_nullable.d.ts +10 -0
  46. package/backend/dist/db/migrations/001_migrate_slug_nullable.d.ts.map +1 -0
  47. package/backend/dist/db/migrations/001_migrate_slug_nullable.js +103 -0
  48. package/backend/dist/db/migrations/001_migrate_slug_nullable.js.map +1 -0
  49. package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.d.ts +11 -0
  50. package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.d.ts.map +1 -0
  51. package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.js +92 -0
  52. package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.js.map +1 -0
  53. package/backend/dist/db/migrations/003_add_bookmark_features.d.ts +5 -0
  54. package/backend/dist/db/migrations/003_add_bookmark_features.d.ts.map +1 -0
  55. package/backend/dist/db/migrations/003_add_bookmark_features.js +98 -0
  56. package/backend/dist/db/migrations/003_add_bookmark_features.js.map +1 -0
  57. package/backend/dist/db/migrations/004_make_slug_globally_unique.d.ts +12 -0
  58. package/backend/dist/db/migrations/004_make_slug_globally_unique.d.ts.map +1 -0
  59. package/backend/dist/db/migrations/004_make_slug_globally_unique.js +152 -0
  60. package/backend/dist/db/migrations/004_make_slug_globally_unique.js.map +1 -0
  61. package/backend/dist/db/migrations/005_add_email_verification.d.ts +5 -0
  62. package/backend/dist/db/migrations/005_add_email_verification.d.ts.map +1 -0
  63. package/backend/dist/db/migrations/005_add_email_verification.js +102 -0
  64. package/backend/dist/db/migrations/005_add_email_verification.js.map +1 -0
  65. package/backend/dist/db/migrations/006_refresh_tokens.d.ts +9 -0
  66. package/backend/dist/db/migrations/006_refresh_tokens.d.ts.map +1 -0
  67. package/backend/dist/db/migrations/006_refresh_tokens.js +61 -0
  68. package/backend/dist/db/migrations/006_refresh_tokens.js.map +1 -0
  69. package/backend/dist/db/migrations/007_password_reset_token_hash.d.ts +10 -0
  70. package/backend/dist/db/migrations/007_password_reset_token_hash.d.ts.map +1 -0
  71. package/backend/dist/db/migrations/007_password_reset_token_hash.js +40 -0
  72. package/backend/dist/db/migrations/007_password_reset_token_hash.js.map +1 -0
  73. package/backend/dist/db/migrations/008_slug_preferences.d.ts +8 -0
  74. package/backend/dist/db/migrations/008_slug_preferences.d.ts.map +1 -0
  75. package/backend/dist/db/migrations/008_slug_preferences.js +24 -0
  76. package/backend/dist/db/migrations/008_slug_preferences.js.map +1 -0
  77. package/backend/dist/db/migrations/009_signup_email_verified.d.ts +5 -0
  78. package/backend/dist/db/migrations/009_signup_email_verified.d.ts.map +1 -0
  79. package/backend/dist/db/migrations/009_signup_email_verified.js +79 -0
  80. package/backend/dist/db/migrations/009_signup_email_verified.js.map +1 -0
  81. package/backend/dist/db/migrations/010_organizations.d.ts +5 -0
  82. package/backend/dist/db/migrations/010_organizations.d.ts.map +1 -0
  83. package/backend/dist/db/migrations/010_organizations.js +113 -0
  84. package/backend/dist/db/migrations/010_organizations.js.map +1 -0
  85. package/backend/dist/db/migrations/011_org_scoped_teams.d.ts +11 -0
  86. package/backend/dist/db/migrations/011_org_scoped_teams.d.ts.map +1 -0
  87. package/backend/dist/db/migrations/011_org_scoped_teams.js +59 -0
  88. package/backend/dist/db/migrations/011_org_scoped_teams.js.map +1 -0
  89. package/backend/dist/db/migrations/012_org_invitations_token_hash.d.ts +10 -0
  90. package/backend/dist/db/migrations/012_org_invitations_token_hash.d.ts.map +1 -0
  91. package/backend/dist/db/migrations/012_org_invitations_token_hash.js +40 -0
  92. package/backend/dist/db/migrations/012_org_invitations_token_hash.js.map +1 -0
  93. package/backend/dist/db/migrations/013_signup_verification_token_hash.d.ts +10 -0
  94. package/backend/dist/db/migrations/013_signup_verification_token_hash.d.ts.map +1 -0
  95. package/backend/dist/db/migrations/013_signup_verification_token_hash.js +39 -0
  96. package/backend/dist/db/migrations/013_signup_verification_token_hash.js.map +1 -0
  97. package/backend/dist/db/migrations/014_stats_indexes.d.ts +8 -0
  98. package/backend/dist/db/migrations/014_stats_indexes.d.ts.map +1 -0
  99. package/backend/dist/db/migrations/014_stats_indexes.js +19 -0
  100. package/backend/dist/db/migrations/014_stats_indexes.js.map +1 -0
  101. package/backend/dist/db/migrations/015_api_tokens.d.ts +9 -0
  102. package/backend/dist/db/migrations/015_api_tokens.d.ts.map +1 -0
  103. package/backend/dist/db/migrations/015_api_tokens.js +48 -0
  104. package/backend/dist/db/migrations/015_api_tokens.js.map +1 -0
  105. package/backend/dist/db/migrations/016_free_plan_grace_ends_at.d.ts +9 -0
  106. package/backend/dist/db/migrations/016_free_plan_grace_ends_at.d.ts.map +1 -0
  107. package/backend/dist/db/migrations/016_free_plan_grace_ends_at.js +50 -0
  108. package/backend/dist/db/migrations/016_free_plan_grace_ends_at.js.map +1 -0
  109. package/backend/dist/db/migrations/017_ai_suggestions.d.ts +11 -0
  110. package/backend/dist/db/migrations/017_ai_suggestions.d.ts.map +1 -0
  111. package/backend/dist/db/migrations/017_ai_suggestions.js +78 -0
  112. package/backend/dist/db/migrations/017_ai_suggestions.js.map +1 -0
  113. package/backend/dist/db/migrations/018_ai_cache_output_language.d.ts +10 -0
  114. package/backend/dist/db/migrations/018_ai_cache_output_language.d.ts.map +1 -0
  115. package/backend/dist/db/migrations/018_ai_cache_output_language.js +89 -0
  116. package/backend/dist/db/migrations/018_ai_cache_output_language.js.map +1 -0
  117. package/backend/dist/db/migrations/019_ai_suggestion_usage.d.ts +10 -0
  118. package/backend/dist/db/migrations/019_ai_suggestion_usage.d.ts.map +1 -0
  119. package/backend/dist/db/migrations/019_ai_suggestion_usage.js +47 -0
  120. package/backend/dist/db/migrations/019_ai_suggestion_usage.js.map +1 -0
  121. package/backend/dist/db/migrations/020_tenant_scope.d.ts +5 -0
  122. package/backend/dist/db/migrations/020_tenant_scope.d.ts.map +1 -0
  123. package/backend/dist/db/migrations/020_tenant_scope.js +105 -0
  124. package/backend/dist/db/migrations/020_tenant_scope.js.map +1 -0
  125. package/backend/dist/db/migrations/_legacy_cloud_010_organizations.d.ts +5 -0
  126. package/backend/dist/db/migrations/_legacy_cloud_010_organizations.d.ts.map +1 -0
  127. package/backend/dist/db/migrations/_legacy_cloud_010_organizations.js +113 -0
  128. package/backend/dist/db/migrations/_legacy_cloud_010_organizations.js.map +1 -0
  129. package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.d.ts +11 -0
  130. package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.d.ts.map +1 -0
  131. package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.js +59 -0
  132. package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.js.map +1 -0
  133. package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.d.ts +10 -0
  134. package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.d.ts.map +1 -0
  135. package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.js +40 -0
  136. package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.js.map +1 -0
  137. package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.d.ts +9 -0
  138. package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.d.ts.map +1 -0
  139. package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.js +50 -0
  140. package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.js.map +1 -0
  141. package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.d.ts +11 -0
  142. package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.d.ts.map +1 -0
  143. package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.js +78 -0
  144. package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.js.map +1 -0
  145. package/backend/dist/db/migrations/index.d.ts +22 -0
  146. package/backend/dist/db/migrations/index.d.ts.map +1 -0
  147. package/backend/dist/db/migrations/index.js +194 -0
  148. package/backend/dist/db/migrations/index.js.map +1 -0
  149. package/backend/dist/db/pool.d.ts +13 -0
  150. package/backend/dist/db/pool.d.ts.map +1 -0
  151. package/backend/dist/db/pool.js +41 -0
  152. package/backend/dist/db/pool.js.map +1 -0
  153. package/backend/dist/db/seed-data.d.ts +66 -0
  154. package/backend/dist/db/seed-data.d.ts.map +1 -0
  155. package/backend/dist/db/seed-data.js +394 -0
  156. package/backend/dist/db/seed-data.js.map +1 -0
  157. package/backend/dist/db/seed.d.ts +19 -0
  158. package/backend/dist/db/seed.d.ts.map +1 -0
  159. package/backend/dist/db/seed.js +406 -0
  160. package/backend/dist/db/seed.js.map +1 -0
  161. package/backend/dist/index.d.ts +3 -0
  162. package/backend/dist/index.d.ts.map +1 -0
  163. package/backend/dist/index.js +64 -0
  164. package/backend/dist/index.js.map +1 -0
  165. package/backend/dist/instrument.d.ts +2 -0
  166. package/backend/dist/instrument.d.ts.map +1 -0
  167. package/backend/dist/instrument.js +16 -0
  168. package/backend/dist/instrument.js.map +1 -0
  169. package/backend/dist/load-env.d.ts +2 -0
  170. package/backend/dist/load-env.d.ts.map +1 -0
  171. package/backend/dist/load-env.js +33 -0
  172. package/backend/dist/load-env.js.map +1 -0
  173. package/backend/dist/middleware/auth.d.ts +23 -0
  174. package/backend/dist/middleware/auth.d.ts.map +1 -0
  175. package/backend/dist/middleware/auth.js +69 -0
  176. package/backend/dist/middleware/auth.js.map +1 -0
  177. package/backend/dist/middleware/error-handler.d.ts +11 -0
  178. package/backend/dist/middleware/error-handler.d.ts.map +1 -0
  179. package/backend/dist/middleware/error-handler.js +40 -0
  180. package/backend/dist/middleware/error-handler.js.map +1 -0
  181. package/backend/dist/middleware/security.d.ts +26 -0
  182. package/backend/dist/middleware/security.d.ts.map +1 -0
  183. package/backend/dist/middleware/security.js +162 -0
  184. package/backend/dist/middleware/security.js.map +1 -0
  185. package/backend/dist/middleware/stats-auth.d.ts +7 -0
  186. package/backend/dist/middleware/stats-auth.d.ts.map +1 -0
  187. package/backend/dist/middleware/stats-auth.js +20 -0
  188. package/backend/dist/middleware/stats-auth.js.map +1 -0
  189. package/backend/dist/middleware/tenant.d.ts +3 -0
  190. package/backend/dist/middleware/tenant.d.ts.map +1 -0
  191. package/backend/dist/middleware/tenant.js +13 -0
  192. package/backend/dist/middleware/tenant.js.map +1 -0
  193. package/backend/dist/register-routes.d.ts +12 -0
  194. package/backend/dist/register-routes.d.ts.map +1 -0
  195. package/backend/dist/register-routes.js +59 -0
  196. package/backend/dist/register-routes.js.map +1 -0
  197. package/backend/dist/routes/admin/demo-reset.d.ts +8 -0
  198. package/backend/dist/routes/admin/demo-reset.d.ts.map +1 -0
  199. package/backend/dist/routes/admin/demo-reset.js +66 -0
  200. package/backend/dist/routes/admin/demo-reset.js.map +1 -0
  201. package/backend/dist/routes/admin/settings.d.ts +3 -0
  202. package/backend/dist/routes/admin/settings.d.ts.map +1 -0
  203. package/backend/dist/routes/admin/settings.js +452 -0
  204. package/backend/dist/routes/admin/settings.js.map +1 -0
  205. package/backend/dist/routes/admin/stats.d.ts +7 -0
  206. package/backend/dist/routes/admin/stats.d.ts.map +1 -0
  207. package/backend/dist/routes/admin/stats.js +66 -0
  208. package/backend/dist/routes/admin/stats.js.map +1 -0
  209. package/backend/dist/routes/admin/teams.d.ts +3 -0
  210. package/backend/dist/routes/admin/teams.d.ts.map +1 -0
  211. package/backend/dist/routes/admin/teams.js +509 -0
  212. package/backend/dist/routes/admin/teams.js.map +1 -0
  213. package/backend/dist/routes/admin/users.d.ts +3 -0
  214. package/backend/dist/routes/admin/users.d.ts.map +1 -0
  215. package/backend/dist/routes/admin/users.js +525 -0
  216. package/backend/dist/routes/admin/users.js.map +1 -0
  217. package/backend/dist/routes/auth.d.ts +3 -0
  218. package/backend/dist/routes/auth.d.ts.map +1 -0
  219. package/backend/dist/routes/auth.js +992 -0
  220. package/backend/dist/routes/auth.js.map +1 -0
  221. package/backend/dist/routes/billing.d.ts +8 -0
  222. package/backend/dist/routes/billing.d.ts.map +1 -0
  223. package/backend/dist/routes/billing.js +481 -0
  224. package/backend/dist/routes/billing.js.map +1 -0
  225. package/backend/dist/routes/bookmarks.d.ts +3 -0
  226. package/backend/dist/routes/bookmarks.d.ts.map +1 -0
  227. package/backend/dist/routes/bookmarks.js +1593 -0
  228. package/backend/dist/routes/bookmarks.js.map +1 -0
  229. package/backend/dist/routes/config.d.ts +7 -0
  230. package/backend/dist/routes/config.d.ts.map +1 -0
  231. package/backend/dist/routes/config.js +52 -0
  232. package/backend/dist/routes/config.js.map +1 -0
  233. package/backend/dist/routes/contact.d.ts +9 -0
  234. package/backend/dist/routes/contact.d.ts.map +1 -0
  235. package/backend/dist/routes/contact.js +99 -0
  236. package/backend/dist/routes/contact.js.map +1 -0
  237. package/backend/dist/routes/csrf.d.ts +3 -0
  238. package/backend/dist/routes/csrf.d.ts.map +1 -0
  239. package/backend/dist/routes/csrf.js +39 -0
  240. package/backend/dist/routes/csrf.js.map +1 -0
  241. package/backend/dist/routes/dashboard.d.ts +3 -0
  242. package/backend/dist/routes/dashboard.d.ts.map +1 -0
  243. package/backend/dist/routes/dashboard.js +212 -0
  244. package/backend/dist/routes/dashboard.js.map +1 -0
  245. package/backend/dist/routes/email-verification.d.ts +3 -0
  246. package/backend/dist/routes/email-verification.d.ts.map +1 -0
  247. package/backend/dist/routes/email-verification.js +124 -0
  248. package/backend/dist/routes/email-verification.js.map +1 -0
  249. package/backend/dist/routes/folders.d.ts +3 -0
  250. package/backend/dist/routes/folders.d.ts.map +1 -0
  251. package/backend/dist/routes/folders.js +524 -0
  252. package/backend/dist/routes/folders.js.map +1 -0
  253. package/backend/dist/routes/go-helpers.d.ts +18 -0
  254. package/backend/dist/routes/go-helpers.d.ts.map +1 -0
  255. package/backend/dist/routes/go-helpers.js +64 -0
  256. package/backend/dist/routes/go-helpers.js.map +1 -0
  257. package/backend/dist/routes/go.d.ts +23 -0
  258. package/backend/dist/routes/go.d.ts.map +1 -0
  259. package/backend/dist/routes/go.js +361 -0
  260. package/backend/dist/routes/go.js.map +1 -0
  261. package/backend/dist/routes/health.d.ts +6 -0
  262. package/backend/dist/routes/health.d.ts.map +1 -0
  263. package/backend/dist/routes/health.js +79 -0
  264. package/backend/dist/routes/health.js.map +1 -0
  265. package/backend/dist/routes/invitations.d.ts +3 -0
  266. package/backend/dist/routes/invitations.d.ts.map +1 -0
  267. package/backend/dist/routes/invitations.js +172 -0
  268. package/backend/dist/routes/invitations.js.map +1 -0
  269. package/backend/dist/routes/oidc-providers.d.ts +3 -0
  270. package/backend/dist/routes/oidc-providers.d.ts.map +1 -0
  271. package/backend/dist/routes/oidc-providers.js +495 -0
  272. package/backend/dist/routes/oidc-providers.js.map +1 -0
  273. package/backend/dist/routes/organizations.d.ts +3 -0
  274. package/backend/dist/routes/organizations.d.ts.map +1 -0
  275. package/backend/dist/routes/organizations.js +538 -0
  276. package/backend/dist/routes/organizations.js.map +1 -0
  277. package/backend/dist/routes/password-reset.d.ts +3 -0
  278. package/backend/dist/routes/password-reset.d.ts.map +1 -0
  279. package/backend/dist/routes/password-reset.js +212 -0
  280. package/backend/dist/routes/password-reset.js.map +1 -0
  281. package/backend/dist/routes/redirect.d.ts +3 -0
  282. package/backend/dist/routes/redirect.d.ts.map +1 -0
  283. package/backend/dist/routes/redirect.js +124 -0
  284. package/backend/dist/routes/redirect.js.map +1 -0
  285. package/backend/dist/routes/tags.d.ts +3 -0
  286. package/backend/dist/routes/tags.d.ts.map +1 -0
  287. package/backend/dist/routes/tags.js +302 -0
  288. package/backend/dist/routes/tags.js.map +1 -0
  289. package/backend/dist/routes/teams.d.ts +3 -0
  290. package/backend/dist/routes/teams.d.ts.map +1 -0
  291. package/backend/dist/routes/teams.js +60 -0
  292. package/backend/dist/routes/teams.js.map +1 -0
  293. package/backend/dist/routes/tokens.d.ts +3 -0
  294. package/backend/dist/routes/tokens.d.ts.map +1 -0
  295. package/backend/dist/routes/tokens.js +157 -0
  296. package/backend/dist/routes/tokens.js.map +1 -0
  297. package/backend/dist/routes/users.d.ts +3 -0
  298. package/backend/dist/routes/users.d.ts.map +1 -0
  299. package/backend/dist/routes/users.js +199 -0
  300. package/backend/dist/routes/users.js.map +1 -0
  301. package/backend/dist/services/ai-suggestions.d.ts +29 -0
  302. package/backend/dist/services/ai-suggestions.d.ts.map +1 -0
  303. package/backend/dist/services/ai-suggestions.js +163 -0
  304. package/backend/dist/services/ai-suggestions.js.map +1 -0
  305. package/backend/dist/services/api-tokens.d.ts +66 -0
  306. package/backend/dist/services/api-tokens.d.ts.map +1 -0
  307. package/backend/dist/services/api-tokens.js +129 -0
  308. package/backend/dist/services/api-tokens.js.map +1 -0
  309. package/backend/dist/services/fetch-page-metadata.d.ts +15 -0
  310. package/backend/dist/services/fetch-page-metadata.d.ts.map +1 -0
  311. package/backend/dist/services/fetch-page-metadata.js +205 -0
  312. package/backend/dist/services/fetch-page-metadata.js.map +1 -0
  313. package/backend/dist/services/stats.d.ts +73 -0
  314. package/backend/dist/services/stats.d.ts.map +1 -0
  315. package/backend/dist/services/stats.js +145 -0
  316. package/backend/dist/services/stats.js.map +1 -0
  317. package/backend/dist/types/oidc-provider.d.ts +17 -0
  318. package/backend/dist/types/oidc-provider.d.ts.map +1 -0
  319. package/backend/dist/types/oidc-provider.js +2 -0
  320. package/backend/dist/types/oidc-provider.js.map +1 -0
  321. package/backend/dist/types.d.ts +86 -0
  322. package/backend/dist/types.d.ts.map +1 -0
  323. package/backend/dist/types.js +2 -0
  324. package/backend/dist/types.js.map +1 -0
  325. package/backend/dist/utils/ai-feature.d.ts +23 -0
  326. package/backend/dist/utils/ai-feature.d.ts.map +1 -0
  327. package/backend/dist/utils/ai-feature.js +62 -0
  328. package/backend/dist/utils/ai-feature.js.map +1 -0
  329. package/backend/dist/utils/email.d.ts +40 -0
  330. package/backend/dist/utils/email.d.ts.map +1 -0
  331. package/backend/dist/utils/email.js +456 -0
  332. package/backend/dist/utils/email.js.map +1 -0
  333. package/backend/dist/utils/encryption.d.ts +18 -0
  334. package/backend/dist/utils/encryption.d.ts.map +1 -0
  335. package/backend/dist/utils/encryption.js +95 -0
  336. package/backend/dist/utils/encryption.js.map +1 -0
  337. package/backend/dist/utils/env-validation.d.ts +6 -0
  338. package/backend/dist/utils/env-validation.d.ts.map +1 -0
  339. package/backend/dist/utils/env-validation.js +51 -0
  340. package/backend/dist/utils/env-validation.js.map +1 -0
  341. package/backend/dist/utils/jwt.d.ts +20 -0
  342. package/backend/dist/utils/jwt.d.ts.map +1 -0
  343. package/backend/dist/utils/jwt.js +48 -0
  344. package/backend/dist/utils/jwt.js.map +1 -0
  345. package/backend/dist/utils/org-cleanup.d.ts +6 -0
  346. package/backend/dist/utils/org-cleanup.d.ts.map +1 -0
  347. package/backend/dist/utils/org-cleanup.js +37 -0
  348. package/backend/dist/utils/org-cleanup.js.map +1 -0
  349. package/backend/dist/utils/organizations.d.ts +12 -0
  350. package/backend/dist/utils/organizations.d.ts.map +1 -0
  351. package/backend/dist/utils/organizations.js +24 -0
  352. package/backend/dist/utils/organizations.js.map +1 -0
  353. package/backend/dist/utils/plan-errors.d.ts +18 -0
  354. package/backend/dist/utils/plan-errors.d.ts.map +1 -0
  355. package/backend/dist/utils/plan-errors.js +21 -0
  356. package/backend/dist/utils/plan-errors.js.map +1 -0
  357. package/backend/dist/utils/refresh-token.d.ts +31 -0
  358. package/backend/dist/utils/refresh-token.d.ts.map +1 -0
  359. package/backend/dist/utils/refresh-token.js +63 -0
  360. package/backend/dist/utils/refresh-token.js.map +1 -0
  361. package/backend/dist/utils/session-store.d.ts +46 -0
  362. package/backend/dist/utils/session-store.d.ts.map +1 -0
  363. package/backend/dist/utils/session-store.js +222 -0
  364. package/backend/dist/utils/session-store.js.map +1 -0
  365. package/backend/dist/utils/tenant.d.ts +5 -0
  366. package/backend/dist/utils/tenant.d.ts.map +1 -0
  367. package/backend/dist/utils/tenant.js +12 -0
  368. package/backend/dist/utils/tenant.js.map +1 -0
  369. package/backend/dist/utils/user-key.d.ts +24 -0
  370. package/backend/dist/utils/user-key.d.ts.map +1 -0
  371. package/backend/dist/utils/user-key.js +116 -0
  372. package/backend/dist/utils/user-key.js.map +1 -0
  373. package/backend/dist/utils/validation.d.ts +91 -0
  374. package/backend/dist/utils/validation.d.ts.map +1 -0
  375. package/backend/dist/utils/validation.js +337 -0
  376. package/backend/dist/utils/validation.js.map +1 -0
  377. package/backend/index.js +15 -0
  378. package/frontend/index.js +5 -0
  379. package/frontend/index.tsx +7 -0
  380. package/package.json +16 -0
  381. package/types/index.js +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_add_oidc_custom_endpoints.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/002_add_oidc_custom_endpoints.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,eAAO,MAAM,WAAW,kCAAkC,CAAC;AAC3D,eAAO,MAAM,aAAa,oCAAoC,CAAC;AAE/D,wBAAsB,EAAE,kBA8CvB;AAED,wBAAsB,IAAI,kBAuCzB"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Migration: Add custom OIDC endpoint fields
3
+ * Date: 2026-01-12
4
+ * Description: Adds optional custom endpoint fields (authorization_url, token_url, userinfo_url) to oidc_providers table
5
+ * to allow providers with non-standard endpoint paths
6
+ */
7
+ import { execute } from '../index.js';
8
+ export const migrationId = '002_add_oidc_custom_endpoints';
9
+ export const migrationName = 'Add custom OIDC endpoint fields';
10
+ export async function up() {
11
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
12
+ if (DB_TYPE === 'postgresql') {
13
+ // PostgreSQL: Add columns
14
+ await execute('ALTER TABLE oidc_providers ADD COLUMN IF NOT EXISTS authorization_url TEXT', []);
15
+ await execute('ALTER TABLE oidc_providers ADD COLUMN IF NOT EXISTS token_url TEXT', []);
16
+ await execute('ALTER TABLE oidc_providers ADD COLUMN IF NOT EXISTS userinfo_url TEXT', []);
17
+ }
18
+ else {
19
+ // SQLite: Need to recreate table
20
+ // Create new table with new columns
21
+ await execute(`
22
+ CREATE TABLE IF NOT EXISTS oidc_providers_new (
23
+ id VARCHAR(255) PRIMARY KEY,
24
+ provider_key VARCHAR(255) UNIQUE NOT NULL,
25
+ client_id TEXT NOT NULL,
26
+ client_secret TEXT NOT NULL,
27
+ issuer_url TEXT NOT NULL,
28
+ authorization_url TEXT,
29
+ token_url TEXT,
30
+ userinfo_url TEXT,
31
+ scopes TEXT NOT NULL,
32
+ auto_create_users BOOLEAN DEFAULT TRUE,
33
+ default_role VARCHAR(50) DEFAULT 'user',
34
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
35
+ )
36
+ `, []);
37
+ // Copy data from old table
38
+ await execute(`
39
+ INSERT INTO oidc_providers_new (
40
+ id, provider_key, client_id, client_secret, issuer_url,
41
+ scopes, auto_create_users, default_role, created_at
42
+ )
43
+ SELECT
44
+ id, provider_key, client_id, client_secret, issuer_url,
45
+ scopes, auto_create_users, default_role, created_at
46
+ FROM oidc_providers
47
+ `, []);
48
+ // Drop old table
49
+ await execute('DROP TABLE oidc_providers', []);
50
+ // Rename new table
51
+ await execute('ALTER TABLE oidc_providers_new RENAME TO oidc_providers', []);
52
+ }
53
+ }
54
+ export async function down() {
55
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
56
+ if (DB_TYPE === 'postgresql') {
57
+ // PostgreSQL: Drop columns
58
+ await execute('ALTER TABLE oidc_providers DROP COLUMN IF EXISTS authorization_url', []);
59
+ await execute('ALTER TABLE oidc_providers DROP COLUMN IF EXISTS token_url', []);
60
+ await execute('ALTER TABLE oidc_providers DROP COLUMN IF EXISTS userinfo_url', []);
61
+ }
62
+ else {
63
+ // SQLite: Need to recreate table without new columns
64
+ await execute(`
65
+ CREATE TABLE IF NOT EXISTS oidc_providers_new (
66
+ id VARCHAR(255) PRIMARY KEY,
67
+ provider_key VARCHAR(255) UNIQUE NOT NULL,
68
+ client_id TEXT NOT NULL,
69
+ client_secret TEXT NOT NULL,
70
+ issuer_url TEXT NOT NULL,
71
+ scopes TEXT NOT NULL,
72
+ auto_create_users BOOLEAN DEFAULT TRUE,
73
+ default_role VARCHAR(50) DEFAULT 'user',
74
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
75
+ )
76
+ `, []);
77
+ // Copy data (excluding new columns)
78
+ await execute(`
79
+ INSERT INTO oidc_providers_new (
80
+ id, provider_key, client_id, client_secret, issuer_url,
81
+ scopes, auto_create_users, default_role, created_at
82
+ )
83
+ SELECT
84
+ id, provider_key, client_id, client_secret, issuer_url,
85
+ scopes, auto_create_users, default_role, created_at
86
+ FROM oidc_providers
87
+ `, []);
88
+ await execute('DROP TABLE oidc_providers', []);
89
+ await execute('ALTER TABLE oidc_providers_new RENAME TO oidc_providers', []);
90
+ }
91
+ }
92
+ //# sourceMappingURL=002_add_oidc_custom_endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_add_oidc_custom_endpoints.js","sourceRoot":"","sources":["../../../src/db/migrations/002_add_oidc_custom_endpoints.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GAAG,+BAA+B,CAAC;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,iCAAiC,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,EAAE;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,0BAA0B;QAC1B,MAAM,OAAO,CAAC,4EAA4E,EAAE,EAAE,CAAC,CAAC;QAChG,MAAM,OAAO,CAAC,oEAAoE,EAAE,EAAE,CAAC,CAAC;QACxF,MAAM,OAAO,CAAC,uEAAuE,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;SAAM,CAAC;QACN,iCAAiC;QACjC,oCAAoC;QACpC,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;KAeb,EAAE,EAAE,CAAC,CAAC;QAEP,2BAA2B;QAC3B,MAAM,OAAO,CAAC;;;;;;;;;KASb,EAAE,EAAE,CAAC,CAAC;QAEP,iBAAiB;QACjB,MAAM,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;QAE/C,mBAAmB;QACnB,MAAM,OAAO,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,2BAA2B;QAC3B,MAAM,OAAO,CAAC,oEAAoE,EAAE,EAAE,CAAC,CAAC;QACxF,MAAM,OAAO,CAAC,4DAA4D,EAAE,EAAE,CAAC,CAAC;QAChF,MAAM,OAAO,CAAC,+DAA+D,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;SAAM,CAAC;QACN,qDAAqD;QACrD,MAAM,OAAO,CAAC;;;;;;;;;;;;KAYb,EAAE,EAAE,CAAC,CAAC;QAEP,oCAAoC;QACpC,MAAM,OAAO,CAAC;;;;;;;;;KASb,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;QAC/C,MAAM,OAAO,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const migrationId = "003_add_bookmark_features";
2
+ export declare const migrationName = "Add pinned, access_count, and last_accessed_at fields to bookmarks";
3
+ export declare function up(): Promise<void>;
4
+ export declare function down(): Promise<void>;
5
+ //# sourceMappingURL=003_add_bookmark_features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"003_add_bookmark_features.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/003_add_bookmark_features.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,8BAA8B,CAAC;AACvD,eAAO,MAAM,aAAa,uEAAuE,CAAC;AAElG,wBAAsB,EAAE,kBAuDvB;AAED,wBAAsB,IAAI,kBA6CzB"}
@@ -0,0 +1,98 @@
1
+ import { execute } from '../index.js';
2
+ export const migrationId = '003_add_bookmark_features';
3
+ export const migrationName = 'Add pinned, access_count, and last_accessed_at fields to bookmarks';
4
+ export async function up() {
5
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
6
+ if (DB_TYPE === 'postgresql') {
7
+ // PostgreSQL: Add columns directly
8
+ await execute('ALTER TABLE bookmarks ADD COLUMN IF NOT EXISTS pinned BOOLEAN DEFAULT FALSE', []);
9
+ await execute('ALTER TABLE bookmarks ADD COLUMN IF NOT EXISTS access_count INTEGER DEFAULT 0', []);
10
+ await execute('ALTER TABLE bookmarks ADD COLUMN IF NOT EXISTS last_accessed_at TIMESTAMP', []);
11
+ }
12
+ else {
13
+ // SQLite: Need to recreate table
14
+ // Create new table with new columns
15
+ await execute(`
16
+ CREATE TABLE IF NOT EXISTS bookmarks_new (
17
+ id VARCHAR(255) PRIMARY KEY,
18
+ user_id VARCHAR(255) NOT NULL,
19
+ title TEXT NOT NULL,
20
+ url TEXT NOT NULL,
21
+ slug VARCHAR(255),
22
+ forwarding_enabled BOOLEAN DEFAULT FALSE,
23
+ pinned BOOLEAN DEFAULT FALSE,
24
+ access_count INTEGER DEFAULT 0,
25
+ last_accessed_at TIMESTAMP,
26
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
27
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
28
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
29
+ )
30
+ `, []);
31
+ // Copy data from old table
32
+ await execute(`
33
+ INSERT INTO bookmarks_new (
34
+ id, user_id, title, url, slug, forwarding_enabled,
35
+ pinned, access_count, last_accessed_at, created_at, updated_at
36
+ )
37
+ SELECT
38
+ id, user_id, title, url, slug, forwarding_enabled,
39
+ FALSE as pinned, 0 as access_count, NULL as last_accessed_at,
40
+ created_at, updated_at
41
+ FROM bookmarks
42
+ `, []);
43
+ // Drop old table
44
+ await execute('DROP TABLE bookmarks', []);
45
+ // Rename new table
46
+ await execute('ALTER TABLE bookmarks_new RENAME TO bookmarks', []);
47
+ // Recreate indexes
48
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_id ON bookmarks(user_id)', []);
49
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_slug ON bookmarks(slug)', []);
50
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_slug ON bookmarks(user_id, slug)', []);
51
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_pinned ON bookmarks(pinned)', []);
52
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_access_count ON bookmarks(access_count)', []);
53
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_last_accessed ON bookmarks(last_accessed_at)', []);
54
+ }
55
+ }
56
+ export async function down() {
57
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
58
+ if (DB_TYPE === 'postgresql') {
59
+ // PostgreSQL: Remove columns
60
+ await execute('ALTER TABLE bookmarks DROP COLUMN IF EXISTS pinned', []);
61
+ await execute('ALTER TABLE bookmarks DROP COLUMN IF EXISTS access_count', []);
62
+ await execute('ALTER TABLE bookmarks DROP COLUMN IF EXISTS last_accessed_at', []);
63
+ }
64
+ else {
65
+ // SQLite: Recreate table without new columns
66
+ await execute(`
67
+ CREATE TABLE IF NOT EXISTS bookmarks_old (
68
+ id VARCHAR(255) PRIMARY KEY,
69
+ user_id VARCHAR(255) NOT NULL,
70
+ title TEXT NOT NULL,
71
+ url TEXT NOT NULL,
72
+ slug VARCHAR(255),
73
+ forwarding_enabled BOOLEAN DEFAULT FALSE,
74
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
75
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
76
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
77
+ )
78
+ `, []);
79
+ // Copy data (excluding new columns)
80
+ await execute(`
81
+ INSERT INTO bookmarks_old (
82
+ id, user_id, title, url, slug, forwarding_enabled, created_at, updated_at
83
+ )
84
+ SELECT
85
+ id, user_id, title, url, slug, forwarding_enabled, created_at, updated_at
86
+ FROM bookmarks
87
+ `, []);
88
+ // Drop new table
89
+ await execute('DROP TABLE bookmarks', []);
90
+ // Rename old table
91
+ await execute('ALTER TABLE bookmarks_old RENAME TO bookmarks', []);
92
+ // Recreate indexes
93
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_id ON bookmarks(user_id)', []);
94
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_slug ON bookmarks(slug)', []);
95
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_slug ON bookmarks(user_id, slug)', []);
96
+ }
97
+ }
98
+ //# sourceMappingURL=003_add_bookmark_features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"003_add_bookmark_features.js","sourceRoot":"","sources":["../../../src/db/migrations/003_add_bookmark_features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,oEAAoE,CAAC;AAElG,MAAM,CAAC,KAAK,UAAU,EAAE;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,mCAAmC;QACnC,MAAM,OAAO,CAAC,6EAA6E,EAAE,EAAE,CAAC,CAAC;QACjG,MAAM,OAAO,CAAC,+EAA+E,EAAE,EAAE,CAAC,CAAC;QACnG,MAAM,OAAO,CAAC,2EAA2E,EAAE,EAAE,CAAC,CAAC;IACjG,CAAC;SAAM,CAAC;QACN,iCAAiC;QACjC,oCAAoC;QACpC,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;KAeb,EAAE,EAAE,CAAC,CAAC;QAEP,2BAA2B;QAC3B,MAAM,OAAO,CAAC;;;;;;;;;;KAUb,EAAE,EAAE,CAAC,CAAC;QAEP,iBAAiB;QACjB,MAAM,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAE1C,mBAAmB;QACnB,MAAM,OAAO,CAAC,+CAA+C,EAAE,EAAE,CAAC,CAAC;QAEnE,mBAAmB;QACnB,MAAM,OAAO,CAAC,wEAAwE,EAAE,EAAE,CAAC,CAAC;QAC5F,MAAM,OAAO,CAAC,kEAAkE,EAAE,EAAE,CAAC,CAAC;QACtF,MAAM,OAAO,CAAC,gFAAgF,EAAE,EAAE,CAAC,CAAC;QACpG,MAAM,OAAO,CAAC,sEAAsE,EAAE,EAAE,CAAC,CAAC;QAC1F,MAAM,OAAO,CAAC,kFAAkF,EAAE,EAAE,CAAC,CAAC;QACtG,MAAM,OAAO,CAAC,uFAAuF,EAAE,EAAE,CAAC,CAAC;IAC7G,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,6BAA6B;QAC7B,MAAM,OAAO,CAAC,oDAAoD,EAAE,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,CAAC,0DAA0D,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,OAAO,CAAC,8DAA8D,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;SAAM,CAAC;QACN,6CAA6C;QAC7C,MAAM,OAAO,CAAC;;;;;;;;;;;;KAYb,EAAE,EAAE,CAAC,CAAC;QAEP,oCAAoC;QACpC,MAAM,OAAO,CAAC;;;;;;;KAOb,EAAE,EAAE,CAAC,CAAC;QAEP,iBAAiB;QACjB,MAAM,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAE1C,mBAAmB;QACnB,MAAM,OAAO,CAAC,+CAA+C,EAAE,EAAE,CAAC,CAAC;QAEnE,mBAAmB;QACnB,MAAM,OAAO,CAAC,wEAAwE,EAAE,EAAE,CAAC,CAAC;QAC5F,MAAM,OAAO,CAAC,kEAAkE,EAAE,EAAE,CAAC,CAAC;QACtF,MAAM,OAAO,CAAC,gFAAgF,EAAE,EAAE,CAAC,CAAC;IACtG,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Migration 004: Make slug globally unique
3
+ *
4
+ * Changes the UNIQUE constraint on bookmarks.slug from (user_id, slug) to just (slug)
5
+ * This ensures that when bookmarks are shared, slugs are unique across the entire system,
6
+ * allowing any user's user_key to work with shared bookmarks via forwarding.
7
+ */
8
+ export declare const migrationId = "004";
9
+ export declare const migrationName = "Make slug globally unique";
10
+ export declare function up(): Promise<void>;
11
+ export declare function down(): Promise<void>;
12
+ //# sourceMappingURL=004_make_slug_globally_unique.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"004_make_slug_globally_unique.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/004_make_slug_globally_unique.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,eAAO,MAAM,WAAW,QAAQ,CAAC;AACjC,eAAO,MAAM,aAAa,8BAA8B,CAAC;AAEzD,wBAAsB,EAAE,kBAgIvB;AAED,wBAAsB,IAAI,kBAmDzB"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Migration 004: Make slug globally unique
3
+ *
4
+ * Changes the UNIQUE constraint on bookmarks.slug from (user_id, slug) to just (slug)
5
+ * This ensures that when bookmarks are shared, slugs are unique across the entire system,
6
+ * allowing any user's user_key to work with shared bookmarks via forwarding.
7
+ */
8
+ import { execute, query } from '../index.js';
9
+ export const migrationId = '004';
10
+ export const migrationName = 'Make slug globally unique';
11
+ export async function up() {
12
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
13
+ if (DB_TYPE === 'postgresql') {
14
+ // PostgreSQL: Drop the old unique constraint and add a new one
15
+ try {
16
+ // Drop the old unique constraint
17
+ await execute('ALTER TABLE bookmarks DROP CONSTRAINT IF EXISTS bookmarks_user_id_slug_key', []);
18
+ }
19
+ catch (error) {
20
+ // Constraint might not exist or have a different name, try alternative
21
+ try {
22
+ await execute('ALTER TABLE bookmarks DROP CONSTRAINT IF EXISTS bookmarks_user_id_slug_unique', []);
23
+ }
24
+ catch (e) {
25
+ // Try to find and drop the constraint
26
+ const constraints = await query(`SELECT constraint_name
27
+ FROM information_schema.table_constraints
28
+ WHERE table_name = 'bookmarks'
29
+ AND constraint_type = 'UNIQUE'
30
+ AND constraint_name LIKE '%slug%'`, []);
31
+ for (const constraint of constraints) {
32
+ try {
33
+ await execute(`ALTER TABLE bookmarks DROP CONSTRAINT IF EXISTS ${constraint.constraint_name}`, []);
34
+ }
35
+ catch (e) {
36
+ // Ignore errors
37
+ }
38
+ }
39
+ }
40
+ }
41
+ // Add global unique constraint on slug (NULL values are allowed and don't violate uniqueness)
42
+ await execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_bookmarks_slug_unique ON bookmarks (slug) WHERE slug IS NOT NULL', []);
43
+ }
44
+ else {
45
+ // SQLite: Need to recreate the table
46
+ // First, check if there are any duplicate slugs (excluding NULL)
47
+ const duplicates = await query(`SELECT slug, COUNT(*) as count
48
+ FROM bookmarks
49
+ WHERE slug IS NOT NULL AND slug != ''
50
+ GROUP BY slug
51
+ HAVING COUNT(*) > 1`, []);
52
+ if (Array.isArray(duplicates) && duplicates.length > 0) {
53
+ // For duplicates, keep the oldest bookmark (by created_at) and nullify slugs for others
54
+ console.log(`Found ${duplicates.length} duplicate slug(s). Resolving by keeping oldest bookmark for each slug...`);
55
+ for (const dup of duplicates) {
56
+ const slug = dup.slug;
57
+ // Get all bookmarks with this slug, ordered by created_at
58
+ const bookmarksWithSlug = await query(`SELECT id, created_at FROM bookmarks
59
+ WHERE slug = ?
60
+ ORDER BY created_at ASC`, [slug]);
61
+ if (Array.isArray(bookmarksWithSlug) && bookmarksWithSlug.length > 1) {
62
+ // Keep the first one (oldest), nullify slugs for the rest
63
+ const toKeep = bookmarksWithSlug[0];
64
+ const toNullify = bookmarksWithSlug.slice(1);
65
+ for (const bm of toNullify) {
66
+ await execute(`UPDATE bookmarks SET slug = NULL, forwarding_enabled = FALSE WHERE id = ?`, [bm.id]);
67
+ console.log(` - Nullified slug for bookmark ${bm.id} (duplicate of ${toKeep.id})`);
68
+ }
69
+ }
70
+ }
71
+ console.log('Duplicate slugs resolved. Continuing migration...');
72
+ }
73
+ // Create new table with global unique constraint
74
+ await execute(`
75
+ CREATE TABLE bookmarks_new (
76
+ id VARCHAR(255) PRIMARY KEY,
77
+ user_id VARCHAR(255) NOT NULL,
78
+ title TEXT NOT NULL,
79
+ url TEXT NOT NULL,
80
+ slug VARCHAR(255),
81
+ forwarding_enabled BOOLEAN DEFAULT FALSE,
82
+ pinned BOOLEAN DEFAULT FALSE,
83
+ access_count INTEGER DEFAULT 0,
84
+ last_accessed_at TIMESTAMP,
85
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
86
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
87
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
88
+ UNIQUE(slug)
89
+ )
90
+ `, []);
91
+ // Copy data
92
+ await execute(`
93
+ INSERT INTO bookmarks_new
94
+ SELECT * FROM bookmarks
95
+ `, []);
96
+ // Drop old table
97
+ await execute('DROP TABLE bookmarks', []);
98
+ // Rename new table
99
+ await execute('ALTER TABLE bookmarks_new RENAME TO bookmarks', []);
100
+ // Recreate indexes
101
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_id ON bookmarks(user_id)', []);
102
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_slug ON bookmarks(slug)', []);
103
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_pinned ON bookmarks(pinned)', []);
104
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_access_count ON bookmarks(access_count)', []);
105
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_last_accessed ON bookmarks(last_accessed_at)', []);
106
+ }
107
+ }
108
+ export async function down() {
109
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
110
+ if (DB_TYPE === 'postgresql') {
111
+ // Drop the global unique index
112
+ await execute('DROP INDEX IF EXISTS idx_bookmarks_slug_unique', []);
113
+ // Restore the per-user unique constraint
114
+ await execute('ALTER TABLE bookmarks ADD CONSTRAINT bookmarks_user_id_slug_key UNIQUE (user_id, slug)', []);
115
+ }
116
+ else {
117
+ // SQLite: Recreate table with per-user unique constraint
118
+ await execute(`
119
+ CREATE TABLE bookmarks_old (
120
+ id VARCHAR(255) PRIMARY KEY,
121
+ user_id VARCHAR(255) NOT NULL,
122
+ title TEXT NOT NULL,
123
+ url TEXT NOT NULL,
124
+ slug VARCHAR(255),
125
+ forwarding_enabled BOOLEAN DEFAULT FALSE,
126
+ pinned BOOLEAN DEFAULT FALSE,
127
+ access_count INTEGER DEFAULT 0,
128
+ last_accessed_at TIMESTAMP,
129
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
130
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
131
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
132
+ UNIQUE(user_id, slug)
133
+ )
134
+ `, []);
135
+ // Copy data
136
+ await execute(`
137
+ INSERT INTO bookmarks_old
138
+ SELECT * FROM bookmarks
139
+ `, []);
140
+ // Drop current table
141
+ await execute('DROP TABLE bookmarks', []);
142
+ // Rename old table
143
+ await execute('ALTER TABLE bookmarks_old RENAME TO bookmarks', []);
144
+ // Recreate indexes
145
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_id ON bookmarks(user_id)', []);
146
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_slug ON bookmarks(slug)', []);
147
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_pinned ON bookmarks(pinned)', []);
148
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_access_count ON bookmarks(access_count)', []);
149
+ await execute('CREATE INDEX IF NOT EXISTS idx_bookmarks_last_accessed ON bookmarks(last_accessed_at)', []);
150
+ }
151
+ }
152
+ //# sourceMappingURL=004_make_slug_globally_unique.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"004_make_slug_globally_unique.js","sourceRoot":"","sources":["../../../src/db/migrations/004_make_slug_globally_unique.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const migrationId = "005";
2
+ export declare const migrationName = "Add email verification system";
3
+ export declare function up(): Promise<void>;
4
+ export declare function down(): Promise<void>;
5
+ //# sourceMappingURL=005_add_email_verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"005_add_email_verification.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/005_add_email_verification.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,QAAQ,CAAC;AACjC,eAAO,MAAM,aAAa,kCAAkC,CAAC;AAE7D,wBAAsB,EAAE,kBAuFvB;AAED,wBAAsB,IAAI,kBAiBzB"}
@@ -0,0 +1,102 @@
1
+ import { execute, query } from '../index.js';
2
+ export const migrationId = '005';
3
+ export const migrationName = 'Add email verification system';
4
+ export async function up() {
5
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
6
+ if (DB_TYPE === 'postgresql') {
7
+ // Add email_pending column to users table
8
+ await execute(`
9
+ ALTER TABLE users
10
+ ADD COLUMN IF NOT EXISTS email_pending VARCHAR(255)
11
+ `, []);
12
+ // Create email verification tokens table
13
+ await execute(`
14
+ CREATE TABLE IF NOT EXISTS email_verification_tokens (
15
+ id VARCHAR(255) PRIMARY KEY,
16
+ user_id VARCHAR(255) NOT NULL,
17
+ token VARCHAR(255) UNIQUE NOT NULL,
18
+ new_email VARCHAR(255) NOT NULL,
19
+ expires_at TIMESTAMP NOT NULL,
20
+ used BOOLEAN DEFAULT FALSE,
21
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
22
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
23
+ )
24
+ `, []);
25
+ // Create indexes
26
+ await execute(`
27
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_token
28
+ ON email_verification_tokens(token)
29
+ `, []);
30
+ await execute(`
31
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_user
32
+ ON email_verification_tokens(user_id)
33
+ `, []);
34
+ await execute(`
35
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_expires
36
+ ON email_verification_tokens(expires_at)
37
+ `, []);
38
+ }
39
+ else {
40
+ // SQLite: Check if column exists before adding
41
+ const tableInfo = await query("PRAGMA table_info(users)", []);
42
+ const hasEmailPending = tableInfo.some((col) => col.name === 'email_pending');
43
+ if (!hasEmailPending) {
44
+ // SQLite doesn't support ALTER TABLE ADD COLUMN IF NOT EXISTS, so we need to recreate
45
+ // But we'll use a safer approach: just add the column (it will fail if exists, but that's ok)
46
+ try {
47
+ await execute(`ALTER TABLE users ADD COLUMN email_pending VARCHAR(255)`, []);
48
+ }
49
+ catch (error) {
50
+ // Column might already exist, ignore
51
+ if (!error.message?.includes('duplicate column name')) {
52
+ throw error;
53
+ }
54
+ }
55
+ }
56
+ // Create email verification tokens table
57
+ await execute(`
58
+ CREATE TABLE IF NOT EXISTS email_verification_tokens (
59
+ id TEXT PRIMARY KEY,
60
+ user_id TEXT NOT NULL,
61
+ token TEXT UNIQUE NOT NULL,
62
+ new_email TEXT NOT NULL,
63
+ expires_at TEXT NOT NULL,
64
+ used INTEGER DEFAULT 0,
65
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
66
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
67
+ )
68
+ `, []);
69
+ // Create indexes
70
+ await execute(`
71
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_token
72
+ ON email_verification_tokens(token)
73
+ `, []);
74
+ await execute(`
75
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_user
76
+ ON email_verification_tokens(user_id)
77
+ `, []);
78
+ await execute(`
79
+ CREATE INDEX IF NOT EXISTS idx_email_verification_tokens_expires
80
+ ON email_verification_tokens(expires_at)
81
+ `, []);
82
+ }
83
+ }
84
+ export async function down() {
85
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
86
+ if (DB_TYPE === 'postgresql') {
87
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_expires`, []);
88
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_user`, []);
89
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_token`, []);
90
+ await execute(`DROP TABLE IF EXISTS email_verification_tokens`, []);
91
+ await execute(`ALTER TABLE users DROP COLUMN IF EXISTS email_pending`, []);
92
+ }
93
+ else {
94
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_expires`, []);
95
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_user`, []);
96
+ await execute(`DROP INDEX IF EXISTS idx_email_verification_tokens_token`, []);
97
+ await execute(`DROP TABLE IF EXISTS email_verification_tokens`, []);
98
+ // SQLite doesn't support DROP COLUMN easily, so we'll leave email_pending
99
+ // It won't cause issues if it exists
100
+ }
101
+ }
102
+ //# sourceMappingURL=005_add_email_verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"005_add_email_verification.js","sourceRoot":"","sources":["../../../src/db/migrations/005_add_email_verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AACjC,MAAM,CAAC,MAAM,aAAa,GAAG,+BAA+B,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,EAAE;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,0CAA0C;QAC1C,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;QAEP,yCAAyC;QACzC,MAAM,OAAO,CAAC;;;;;;;;;;;KAWb,EAAE,EAAE,CAAC,CAAC;QAEP,iBAAiB;QACjB,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,eAAe,GAAI,SAAmB,CAAC,IAAI,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;QAE9F,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,sFAAsF;YACtF,8FAA8F;YAC9F,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAC;YAC/E,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,qCAAqC;gBACrC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;oBACtD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,yCAAyC;QACzC,MAAM,OAAO,CAAC;;;;;;;;;;;KAWb,EAAE,EAAE,CAAC,CAAC;QAEP,iBAAiB;QACjB,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,CAAC;;;KAGb,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,4DAA4D,EAAE,EAAE,CAAC,CAAC;QAChF,MAAM,OAAO,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAC;QAC7E,MAAM,OAAO,CAAC,0DAA0D,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,OAAO,CAAC,gDAAgD,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,CAAC,uDAAuD,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,CAAC,4DAA4D,EAAE,EAAE,CAAC,CAAC;QAChF,MAAM,OAAO,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAC;QAC7E,MAAM,OAAO,CAAC,0DAA0D,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,OAAO,CAAC,gDAAgD,EAAE,EAAE,CAAC,CAAC;QACpE,0EAA0E;QAC1E,qCAAqC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Migration: Add refresh_tokens table for CLOUD mode auth (short-lived access JWT + refresh cookie).
3
+ * Used only in CLOUD mode; table is harmless when empty in SELFHOSTED.
4
+ */
5
+ export declare const migrationId = "006_refresh_tokens";
6
+ export declare const migrationName = "Add refresh_tokens table for CLOUD mode";
7
+ export declare function up(): Promise<void>;
8
+ export declare function down(): Promise<void>;
9
+ //# sourceMappingURL=006_refresh_tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"006_refresh_tokens.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/006_refresh_tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,eAAO,MAAM,aAAa,4CAA4C,CAAC;AAEvE,wBAAsB,EAAE,kBA8CvB;AAED,wBAAsB,IAAI,kBAKzB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Migration: Add refresh_tokens table for CLOUD mode auth (short-lived access JWT + refresh cookie).
3
+ * Used only in CLOUD mode; table is harmless when empty in SELFHOSTED.
4
+ */
5
+ import { execute } from '../index.js';
6
+ export const migrationId = '006_refresh_tokens';
7
+ export const migrationName = 'Add refresh_tokens table for CLOUD mode';
8
+ export async function up() {
9
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
10
+ if (DB_TYPE === 'postgresql') {
11
+ await execute(`
12
+ CREATE TABLE IF NOT EXISTS refresh_tokens (
13
+ id VARCHAR(255) PRIMARY KEY,
14
+ user_id VARCHAR(255) NOT NULL,
15
+ token_hash VARCHAR(255) NOT NULL,
16
+ expires_at TIMESTAMP NOT NULL,
17
+ revoked BOOLEAN DEFAULT FALSE,
18
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
19
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
20
+ )
21
+ `, []);
22
+ await execute(`
23
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token_hash ON refresh_tokens(token_hash)
24
+ `, []);
25
+ await execute(`
26
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id)
27
+ `, []);
28
+ await execute(`
29
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires_at ON refresh_tokens(expires_at)
30
+ `, []);
31
+ }
32
+ else {
33
+ await execute(`
34
+ CREATE TABLE IF NOT EXISTS refresh_tokens (
35
+ id TEXT PRIMARY KEY,
36
+ user_id TEXT NOT NULL,
37
+ token_hash TEXT NOT NULL,
38
+ expires_at TEXT NOT NULL,
39
+ revoked INTEGER DEFAULT 0,
40
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
41
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
42
+ )
43
+ `, []);
44
+ await execute(`
45
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token_hash ON refresh_tokens(token_hash)
46
+ `, []);
47
+ await execute(`
48
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id)
49
+ `, []);
50
+ await execute(`
51
+ CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires_at ON refresh_tokens(expires_at)
52
+ `, []);
53
+ }
54
+ }
55
+ export async function down() {
56
+ await execute(`DROP INDEX IF EXISTS idx_refresh_tokens_expires_at`, []);
57
+ await execute(`DROP INDEX IF EXISTS idx_refresh_tokens_user_id`, []);
58
+ await execute(`DROP INDEX IF EXISTS idx_refresh_tokens_token_hash`, []);
59
+ await execute(`DROP TABLE IF EXISTS refresh_tokens`, []);
60
+ }
61
+ //# sourceMappingURL=006_refresh_tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"006_refresh_tokens.js","sourceRoot":"","sources":["../../../src/db/migrations/006_refresh_tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAChD,MAAM,CAAC,MAAM,aAAa,GAAG,yCAAyC,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,EAAE;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC;;;;;;;;;;KAUb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,CAAC;;;;;;;;;;KAUb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,CAAC;;KAEb,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,OAAO,CAAC,oDAAoD,EAAE,EAAE,CAAC,CAAC;IACxE,MAAM,OAAO,CAAC,iDAAiD,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,OAAO,CAAC,oDAAoD,EAAE,EAAE,CAAC,CAAC;IACxE,MAAM,OAAO,CAAC,qCAAqC,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Migration: Add token_hash to password_reset_tokens; store only hash, not plaintext token.
3
+ * New rows use token_hash for lookup; token column holds placeholder 'h:'+id. Legacy rows
4
+ * (token_hash IS NULL) are looked up by token and migrated on use.
5
+ */
6
+ export declare const migrationId = "007_password_reset_token_hash";
7
+ export declare const migrationName = "Add password_reset_tokens.token_hash for secure storage";
8
+ export declare function up(): Promise<void>;
9
+ export declare function down(): Promise<void>;
10
+ //# sourceMappingURL=007_password_reset_token_hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"007_password_reset_token_hash.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/007_password_reset_token_hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,WAAW,kCAAkC,CAAC;AAC3D,eAAO,MAAM,aAAa,4DAA4D,CAAC;AAEvF,wBAAsB,EAAE,kBAsBvB;AAED,wBAAsB,IAAI,kBAOzB"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Migration: Add token_hash to password_reset_tokens; store only hash, not plaintext token.
3
+ * New rows use token_hash for lookup; token column holds placeholder 'h:'+id. Legacy rows
4
+ * (token_hash IS NULL) are looked up by token and migrated on use.
5
+ */
6
+ import { execute } from '../index.js';
7
+ export const migrationId = '007_password_reset_token_hash';
8
+ export const migrationName = 'Add password_reset_tokens.token_hash for secure storage';
9
+ export async function up() {
10
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
11
+ if (DB_TYPE === 'postgresql') {
12
+ await execute(`
13
+ ALTER TABLE password_reset_tokens
14
+ ADD COLUMN IF NOT EXISTS token_hash VARCHAR(255)
15
+ `, []);
16
+ await execute(`
17
+ CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token_hash
18
+ ON password_reset_tokens(token_hash)
19
+ `, []);
20
+ }
21
+ else {
22
+ // SQLite: ADD COLUMN only
23
+ await execute(`
24
+ ALTER TABLE password_reset_tokens ADD COLUMN token_hash TEXT
25
+ `, []);
26
+ await execute(`
27
+ CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token_hash
28
+ ON password_reset_tokens(token_hash)
29
+ `, []);
30
+ }
31
+ }
32
+ export async function down() {
33
+ await execute(`DROP INDEX IF EXISTS idx_password_reset_tokens_token_hash`, []);
34
+ // SQLite does not support DROP COLUMN easily; leave column for safety
35
+ const DB_TYPE = process.env.DB_TYPE || 'sqlite';
36
+ if (DB_TYPE === 'postgresql') {
37
+ await execute(`ALTER TABLE password_reset_tokens DROP COLUMN IF EXISTS token_hash`, []);
38
+ }
39
+ }
40
+ //# sourceMappingURL=007_password_reset_token_hash.js.map