@fivepixels-js/lite-api 0.2.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 (372) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +537 -0
  3. package/dist/app.d.ts +10 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +70 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/auth/identity.repository.d.ts +62 -0
  8. package/dist/auth/identity.repository.d.ts.map +1 -0
  9. package/dist/auth/identity.repository.js +202 -0
  10. package/dist/auth/identity.repository.js.map +1 -0
  11. package/dist/auth/identity.routes.d.ts +5 -0
  12. package/dist/auth/identity.routes.d.ts.map +1 -0
  13. package/dist/auth/identity.routes.js +56 -0
  14. package/dist/auth/identity.routes.js.map +1 -0
  15. package/dist/auth/identity.schemas.d.ts +2711 -0
  16. package/dist/auth/identity.schemas.d.ts.map +1 -0
  17. package/dist/auth/identity.schemas.js +117 -0
  18. package/dist/auth/identity.schemas.js.map +1 -0
  19. package/dist/auth/identity.service.d.ts +37 -0
  20. package/dist/auth/identity.service.d.ts.map +1 -0
  21. package/dist/auth/identity.service.js +131 -0
  22. package/dist/auth/identity.service.js.map +1 -0
  23. package/dist/auth/password.service.d.ts +15 -0
  24. package/dist/auth/password.service.d.ts.map +1 -0
  25. package/dist/auth/password.service.js +116 -0
  26. package/dist/auth/password.service.js.map +1 -0
  27. package/dist/auth/token.service.d.ts +38 -0
  28. package/dist/auth/token.service.d.ts.map +1 -0
  29. package/dist/auth/token.service.js +54 -0
  30. package/dist/auth/token.service.js.map +1 -0
  31. package/dist/cli/cli.d.ts +3 -0
  32. package/dist/cli/cli.d.ts.map +1 -0
  33. package/dist/cli/cli.js +132 -0
  34. package/dist/cli/cli.js.map +1 -0
  35. package/dist/cli/commands/backup.d.ts +4 -0
  36. package/dist/cli/commands/backup.d.ts.map +1 -0
  37. package/dist/cli/commands/backup.js +24 -0
  38. package/dist/cli/commands/backup.js.map +1 -0
  39. package/dist/cli/commands/init.d.ts +4 -0
  40. package/dist/cli/commands/init.d.ts.map +1 -0
  41. package/dist/cli/commands/init.js +23 -0
  42. package/dist/cli/commands/init.js.map +1 -0
  43. package/dist/cli/commands/migrate.d.ts +4 -0
  44. package/dist/cli/commands/migrate.d.ts.map +1 -0
  45. package/dist/cli/commands/migrate.js +20 -0
  46. package/dist/cli/commands/migrate.js.map +1 -0
  47. package/dist/cli/commands/start.d.ts +4 -0
  48. package/dist/cli/commands/start.d.ts.map +1 -0
  49. package/dist/cli/commands/start.js +13 -0
  50. package/dist/cli/commands/start.js.map +1 -0
  51. package/dist/cli/commands/status.d.ts +4 -0
  52. package/dist/cli/commands/status.d.ts.map +1 -0
  53. package/dist/cli/commands/status.js +48 -0
  54. package/dist/cli/commands/status.js.map +1 -0
  55. package/dist/cli/index.d.ts +3 -0
  56. package/dist/cli/index.d.ts.map +1 -0
  57. package/dist/cli/index.js +4 -0
  58. package/dist/cli/index.js.map +1 -0
  59. package/dist/cli/io.d.ts +6 -0
  60. package/dist/cli/io.d.ts.map +1 -0
  61. package/dist/cli/io.js +9 -0
  62. package/dist/cli/io.js.map +1 -0
  63. package/dist/community/contracts.d.ts +29 -0
  64. package/dist/community/contracts.d.ts.map +1 -0
  65. package/dist/community/contracts.js +41 -0
  66. package/dist/community/contracts.js.map +1 -0
  67. package/dist/community/error-handler.d.ts +3 -0
  68. package/dist/community/error-handler.d.ts.map +1 -0
  69. package/dist/community/error-handler.js +66 -0
  70. package/dist/community/error-handler.js.map +1 -0
  71. package/dist/community/errors.d.ts +10 -0
  72. package/dist/community/errors.d.ts.map +1 -0
  73. package/dist/community/errors.js +39 -0
  74. package/dist/community/errors.js.map +1 -0
  75. package/dist/community/etag.d.ts +5 -0
  76. package/dist/community/etag.d.ts.map +1 -0
  77. package/dist/community/etag.js +31 -0
  78. package/dist/community/etag.js.map +1 -0
  79. package/dist/community/input.d.ts +10 -0
  80. package/dist/community/input.d.ts.map +1 -0
  81. package/dist/community/input.js +48 -0
  82. package/dist/community/input.js.map +1 -0
  83. package/dist/community/mutation-route.d.ts +7 -0
  84. package/dist/community/mutation-route.d.ts.map +1 -0
  85. package/dist/community/mutation-route.js +47 -0
  86. package/dist/community/mutation-route.js.map +1 -0
  87. package/dist/community/schemas.d.ts +807 -0
  88. package/dist/community/schemas.d.ts.map +1 -0
  89. package/dist/community/schemas.js +100 -0
  90. package/dist/community/schemas.js.map +1 -0
  91. package/dist/community/system.schemas.d.ts +40 -0
  92. package/dist/community/system.schemas.d.ts.map +1 -0
  93. package/dist/community/system.schemas.js +30 -0
  94. package/dist/community/system.schemas.js.map +1 -0
  95. package/dist/config/config.d.ts +43 -0
  96. package/dist/config/config.d.ts.map +1 -0
  97. package/dist/config/config.js +208 -0
  98. package/dist/config/config.js.map +1 -0
  99. package/dist/config/data-path.d.ts +2 -0
  100. package/dist/config/data-path.d.ts.map +1 -0
  101. package/dist/config/data-path.js +16 -0
  102. package/dist/config/data-path.js.map +1 -0
  103. package/dist/config/jwt-secret.d.ts +3 -0
  104. package/dist/config/jwt-secret.d.ts.map +1 -0
  105. package/dist/config/jwt-secret.js +67 -0
  106. package/dist/config/jwt-secret.js.map +1 -0
  107. package/dist/db/backup.d.ts +10 -0
  108. package/dist/db/backup.d.ts.map +1 -0
  109. package/dist/db/backup.js +51 -0
  110. package/dist/db/backup.js.map +1 -0
  111. package/dist/db/connection.d.ts +15 -0
  112. package/dist/db/connection.d.ts.map +1 -0
  113. package/dist/db/connection.js +82 -0
  114. package/dist/db/connection.js.map +1 -0
  115. package/dist/db/guid-order.d.ts +2 -0
  116. package/dist/db/guid-order.d.ts.map +1 -0
  117. package/dist/db/guid-order.js +9 -0
  118. package/dist/db/guid-order.js.map +1 -0
  119. package/dist/db/migrate.d.ts +37 -0
  120. package/dist/db/migrate.d.ts.map +1 -0
  121. package/dist/db/migrate.js +145 -0
  122. package/dist/db/migrate.js.map +1 -0
  123. package/dist/db/migrations/001_schema_migrations.sql +6 -0
  124. package/dist/db/migrations/002_identity.sql +95 -0
  125. package/dist/db/migrations/003_projects.sql +62 -0
  126. package/dist/db/migrations/004_feedback_core.sql +236 -0
  127. package/dist/db/migrations/005_project_member_management.sql +55 -0
  128. package/dist/db/migrations/006_align_credentials.sql +33 -0
  129. package/dist/db/migrations/007_align_storage_values.sql +78 -0
  130. package/dist/db/storage-migration.d.ts +9 -0
  131. package/dist/db/storage-migration.d.ts.map +1 -0
  132. package/dist/db/storage-migration.js +79 -0
  133. package/dist/db/storage-migration.js.map +1 -0
  134. package/dist/db/transaction.d.ts +9 -0
  135. package/dist/db/transaction.d.ts.map +1 -0
  136. package/dist/db/transaction.js +14 -0
  137. package/dist/db/transaction.js.map +1 -0
  138. package/dist/errors/error-handler.d.ts +3 -0
  139. package/dist/errors/error-handler.d.ts.map +1 -0
  140. package/dist/errors/error-handler.js +50 -0
  141. package/dist/errors/error-handler.js.map +1 -0
  142. package/dist/feedbacks/feedback-workflow.service.d.ts +59 -0
  143. package/dist/feedbacks/feedback-workflow.service.d.ts.map +1 -0
  144. package/dist/feedbacks/feedback-workflow.service.js +89 -0
  145. package/dist/feedbacks/feedback-workflow.service.js.map +1 -0
  146. package/dist/feedbacks/feedback.input.d.ts +4 -0
  147. package/dist/feedbacks/feedback.input.d.ts.map +1 -0
  148. package/dist/feedbacks/feedback.input.js +25 -0
  149. package/dist/feedbacks/feedback.input.js.map +1 -0
  150. package/dist/feedbacks/feedback.repository.d.ts +48 -0
  151. package/dist/feedbacks/feedback.repository.d.ts.map +1 -0
  152. package/dist/feedbacks/feedback.repository.js +238 -0
  153. package/dist/feedbacks/feedback.repository.js.map +1 -0
  154. package/dist/feedbacks/feedback.routes.d.ts +4 -0
  155. package/dist/feedbacks/feedback.routes.d.ts.map +1 -0
  156. package/dist/feedbacks/feedback.routes.js +78 -0
  157. package/dist/feedbacks/feedback.routes.js.map +1 -0
  158. package/dist/feedbacks/feedback.schemas.d.ts +642 -0
  159. package/dist/feedbacks/feedback.schemas.d.ts.map +1 -0
  160. package/dist/feedbacks/feedback.schemas.js +131 -0
  161. package/dist/feedbacks/feedback.schemas.js.map +1 -0
  162. package/dist/feedbacks/feedback.service.d.ts +23 -0
  163. package/dist/feedbacks/feedback.service.d.ts.map +1 -0
  164. package/dist/feedbacks/feedback.service.js +74 -0
  165. package/dist/feedbacks/feedback.service.js.map +1 -0
  166. package/dist/feedbacks/feedback.types.d.ts +64 -0
  167. package/dist/feedbacks/feedback.types.d.ts.map +1 -0
  168. package/dist/feedbacks/feedback.types.js +2 -0
  169. package/dist/feedbacks/feedback.types.js.map +1 -0
  170. package/dist/page-elements/page-element.input.d.ts +7 -0
  171. package/dist/page-elements/page-element.input.d.ts.map +1 -0
  172. package/dist/page-elements/page-element.input.js +59 -0
  173. package/dist/page-elements/page-element.input.js.map +1 -0
  174. package/dist/page-elements/page-element.repository.d.ts +21 -0
  175. package/dist/page-elements/page-element.repository.d.ts.map +1 -0
  176. package/dist/page-elements/page-element.repository.js +123 -0
  177. package/dist/page-elements/page-element.repository.js.map +1 -0
  178. package/dist/page-elements/page-element.schemas.d.ts +97 -0
  179. package/dist/page-elements/page-element.schemas.d.ts.map +1 -0
  180. package/dist/page-elements/page-element.schemas.js +40 -0
  181. package/dist/page-elements/page-element.schemas.js.map +1 -0
  182. package/dist/page-elements/page-element.types.d.ts +24 -0
  183. package/dist/page-elements/page-element.types.d.ts.map +1 -0
  184. package/dist/page-elements/page-element.types.js +2 -0
  185. package/dist/page-elements/page-element.types.js.map +1 -0
  186. package/dist/plugins/auth.plugin.d.ts +3 -0
  187. package/dist/plugins/auth.plugin.d.ts.map +1 -0
  188. package/dist/plugins/auth.plugin.js +28 -0
  189. package/dist/plugins/auth.plugin.js.map +1 -0
  190. package/dist/plugins/community-api.plugin.d.ts +5 -0
  191. package/dist/plugins/community-api.plugin.d.ts.map +1 -0
  192. package/dist/plugins/community-api.plugin.js +25 -0
  193. package/dist/plugins/community-api.plugin.js.map +1 -0
  194. package/dist/plugins/cors.plugin.d.ts +3 -0
  195. package/dist/plugins/cors.plugin.d.ts.map +1 -0
  196. package/dist/plugins/cors.plugin.js +19 -0
  197. package/dist/plugins/cors.plugin.js.map +1 -0
  198. package/dist/plugins/swagger.plugin.d.ts +3 -0
  199. package/dist/plugins/swagger.plugin.d.ts.map +1 -0
  200. package/dist/plugins/swagger.plugin.js +59 -0
  201. package/dist/plugins/swagger.plugin.js.map +1 -0
  202. package/dist/plugins/user-auth.plugin.d.ts +33 -0
  203. package/dist/plugins/user-auth.plugin.d.ts.map +1 -0
  204. package/dist/plugins/user-auth.plugin.js +62 -0
  205. package/dist/plugins/user-auth.plugin.js.map +1 -0
  206. package/dist/projects/members/project-member.repository.d.ts +49 -0
  207. package/dist/projects/members/project-member.repository.d.ts.map +1 -0
  208. package/dist/projects/members/project-member.repository.js +215 -0
  209. package/dist/projects/members/project-member.repository.js.map +1 -0
  210. package/dist/projects/members/project-member.routes.d.ts +4 -0
  211. package/dist/projects/members/project-member.routes.d.ts.map +1 -0
  212. package/dist/projects/members/project-member.routes.js +82 -0
  213. package/dist/projects/members/project-member.routes.js.map +1 -0
  214. package/dist/projects/members/project-member.schemas.d.ts +2735 -0
  215. package/dist/projects/members/project-member.schemas.d.ts.map +1 -0
  216. package/dist/projects/members/project-member.schemas.js +138 -0
  217. package/dist/projects/members/project-member.schemas.js.map +1 -0
  218. package/dist/projects/members/project-member.service.d.ts +29 -0
  219. package/dist/projects/members/project-member.service.d.ts.map +1 -0
  220. package/dist/projects/members/project-member.service.js +92 -0
  221. package/dist/projects/members/project-member.service.js.map +1 -0
  222. package/dist/projects/project-access.policy.d.ts +11 -0
  223. package/dist/projects/project-access.policy.d.ts.map +1 -0
  224. package/dist/projects/project-access.policy.js +30 -0
  225. package/dist/projects/project-access.policy.js.map +1 -0
  226. package/dist/projects/project-access.repository.d.ts +12 -0
  227. package/dist/projects/project-access.repository.d.ts.map +1 -0
  228. package/dist/projects/project-access.repository.js +45 -0
  229. package/dist/projects/project-access.repository.js.map +1 -0
  230. package/dist/projects/project-access.types.d.ts +9 -0
  231. package/dist/projects/project-access.types.d.ts.map +1 -0
  232. package/dist/projects/project-access.types.js +2 -0
  233. package/dist/projects/project-access.types.js.map +1 -0
  234. package/dist/projects/project-mutation.service.d.ts +15 -0
  235. package/dist/projects/project-mutation.service.d.ts.map +1 -0
  236. package/dist/projects/project-mutation.service.js +39 -0
  237. package/dist/projects/project-mutation.service.js.map +1 -0
  238. package/dist/projects/project.repository.d.ts +49 -0
  239. package/dist/projects/project.repository.d.ts.map +1 -0
  240. package/dist/projects/project.repository.js +155 -0
  241. package/dist/projects/project.repository.js.map +1 -0
  242. package/dist/projects/project.routes.d.ts +4 -0
  243. package/dist/projects/project.routes.d.ts.map +1 -0
  244. package/dist/projects/project.routes.js +45 -0
  245. package/dist/projects/project.routes.js.map +1 -0
  246. package/dist/projects/project.schemas.d.ts +2044 -0
  247. package/dist/projects/project.schemas.d.ts.map +1 -0
  248. package/dist/projects/project.schemas.js +90 -0
  249. package/dist/projects/project.schemas.js.map +1 -0
  250. package/dist/projects/project.service.d.ts +40 -0
  251. package/dist/projects/project.service.d.ts.map +1 -0
  252. package/dist/projects/project.service.js +128 -0
  253. package/dist/projects/project.service.js.map +1 -0
  254. package/dist/replies/reply-mutation.service.d.ts +19 -0
  255. package/dist/replies/reply-mutation.service.d.ts.map +1 -0
  256. package/dist/replies/reply-mutation.service.js +51 -0
  257. package/dist/replies/reply-mutation.service.js.map +1 -0
  258. package/dist/replies/reply.input.d.ts +4 -0
  259. package/dist/replies/reply.input.d.ts.map +1 -0
  260. package/dist/replies/reply.input.js +33 -0
  261. package/dist/replies/reply.input.js.map +1 -0
  262. package/dist/replies/reply.repository.d.ts +40 -0
  263. package/dist/replies/reply.repository.d.ts.map +1 -0
  264. package/dist/replies/reply.repository.js +173 -0
  265. package/dist/replies/reply.repository.js.map +1 -0
  266. package/dist/replies/reply.routes.d.ts +4 -0
  267. package/dist/replies/reply.routes.d.ts.map +1 -0
  268. package/dist/replies/reply.routes.js +64 -0
  269. package/dist/replies/reply.routes.js.map +1 -0
  270. package/dist/replies/reply.schemas.d.ts +251 -0
  271. package/dist/replies/reply.schemas.d.ts.map +1 -0
  272. package/dist/replies/reply.schemas.js +51 -0
  273. package/dist/replies/reply.schemas.js.map +1 -0
  274. package/dist/replies/reply.service.d.ts +19 -0
  275. package/dist/replies/reply.service.d.ts.map +1 -0
  276. package/dist/replies/reply.service.js +50 -0
  277. package/dist/replies/reply.service.js.map +1 -0
  278. package/dist/replies/reply.types.d.ts +31 -0
  279. package/dist/replies/reply.types.d.ts.map +1 -0
  280. package/dist/replies/reply.types.js +2 -0
  281. package/dist/replies/reply.types.js.map +1 -0
  282. package/dist/report-cases/report-case-workflow.service.d.ts +39 -0
  283. package/dist/report-cases/report-case-workflow.service.d.ts.map +1 -0
  284. package/dist/report-cases/report-case-workflow.service.js +103 -0
  285. package/dist/report-cases/report-case-workflow.service.js.map +1 -0
  286. package/dist/report-cases/report-case.input.d.ts +4 -0
  287. package/dist/report-cases/report-case.input.d.ts.map +1 -0
  288. package/dist/report-cases/report-case.input.js +29 -0
  289. package/dist/report-cases/report-case.input.js.map +1 -0
  290. package/dist/report-cases/report-case.repository.d.ts +45 -0
  291. package/dist/report-cases/report-case.repository.d.ts.map +1 -0
  292. package/dist/report-cases/report-case.repository.js +185 -0
  293. package/dist/report-cases/report-case.repository.js.map +1 -0
  294. package/dist/report-cases/report-case.routes.d.ts +4 -0
  295. package/dist/report-cases/report-case.routes.d.ts.map +1 -0
  296. package/dist/report-cases/report-case.routes.js +94 -0
  297. package/dist/report-cases/report-case.routes.js.map +1 -0
  298. package/dist/report-cases/report-case.schemas.d.ts +294 -0
  299. package/dist/report-cases/report-case.schemas.d.ts.map +1 -0
  300. package/dist/report-cases/report-case.schemas.js +77 -0
  301. package/dist/report-cases/report-case.schemas.js.map +1 -0
  302. package/dist/report-cases/report-case.service.d.ts +21 -0
  303. package/dist/report-cases/report-case.service.d.ts.map +1 -0
  304. package/dist/report-cases/report-case.service.js +60 -0
  305. package/dist/report-cases/report-case.service.js.map +1 -0
  306. package/dist/report-cases/report-case.types.d.ts +39 -0
  307. package/dist/report-cases/report-case.types.d.ts.map +1 -0
  308. package/dist/report-cases/report-case.types.js +2 -0
  309. package/dist/report-cases/report-case.types.js.map +1 -0
  310. package/dist/routes/health.route.d.ts +4 -0
  311. package/dist/routes/health.route.d.ts.map +1 -0
  312. package/dist/routes/health.route.js +39 -0
  313. package/dist/routes/health.route.js.map +1 -0
  314. package/dist/routes/version.route.d.ts +3 -0
  315. package/dist/routes/version.route.d.ts.map +1 -0
  316. package/dist/routes/version.route.js +22 -0
  317. package/dist/routes/version.route.js.map +1 -0
  318. package/dist/runtime/index.d.ts +8 -0
  319. package/dist/runtime/index.d.ts.map +1 -0
  320. package/dist/runtime/index.js +11 -0
  321. package/dist/runtime/index.js.map +1 -0
  322. package/dist/server.d.ts +11 -0
  323. package/dist/server.d.ts.map +1 -0
  324. package/dist/server.js +66 -0
  325. package/dist/server.js.map +1 -0
  326. package/dist/storage/values.d.ts +3 -0
  327. package/dist/storage/values.d.ts.map +1 -0
  328. package/dist/storage/values.js +30 -0
  329. package/dist/storage/values.js.map +1 -0
  330. package/dist/users/current-user.routes.d.ts +3 -0
  331. package/dist/users/current-user.routes.d.ts.map +1 -0
  332. package/dist/users/current-user.routes.js +9 -0
  333. package/dist/users/current-user.routes.js.map +1 -0
  334. package/dist/users/current-user.schemas.d.ts +641 -0
  335. package/dist/users/current-user.schemas.d.ts.map +1 -0
  336. package/dist/users/current-user.schemas.js +21 -0
  337. package/dist/users/current-user.schemas.js.map +1 -0
  338. package/dist/users/user-search.repository.d.ts +19 -0
  339. package/dist/users/user-search.repository.d.ts.map +1 -0
  340. package/dist/users/user-search.repository.js +55 -0
  341. package/dist/users/user-search.repository.js.map +1 -0
  342. package/dist/users/user-search.routes.d.ts +4 -0
  343. package/dist/users/user-search.routes.d.ts.map +1 -0
  344. package/dist/users/user-search.routes.js +19 -0
  345. package/dist/users/user-search.routes.js.map +1 -0
  346. package/dist/users/user-search.schemas.d.ts +693 -0
  347. package/dist/users/user-search.schemas.d.ts.map +1 -0
  348. package/dist/users/user-search.schemas.js +41 -0
  349. package/dist/users/user-search.schemas.js.map +1 -0
  350. package/dist/users/user-search.service.d.ts +20 -0
  351. package/dist/users/user-search.service.d.ts.map +1 -0
  352. package/dist/users/user-search.service.js +41 -0
  353. package/dist/users/user-search.service.js.map +1 -0
  354. package/dist/users/user.schemas.d.ts +47 -0
  355. package/dist/users/user.schemas.d.ts.map +1 -0
  356. package/dist/users/user.schemas.js +13 -0
  357. package/dist/users/user.schemas.js.map +1 -0
  358. package/dist/users/user.types.d.ts +6 -0
  359. package/dist/users/user.types.d.ts.map +1 -0
  360. package/dist/users/user.types.js +2 -0
  361. package/dist/users/user.types.js.map +1 -0
  362. package/dist/version.d.ts +3 -0
  363. package/dist/version.d.ts.map +1 -0
  364. package/dist/version.js +5 -0
  365. package/dist/version.js.map +1 -0
  366. package/docs/guides/community-api-quickstart.md +171 -0
  367. package/docs/guides/feature-structure.md +138 -0
  368. package/docs/guides/independent-cli.md +73 -0
  369. package/docs/guides/non-attachment-api-contract.md +138 -0
  370. package/docs/plans/selfdev-schema-alignment.md +61 -0
  371. package/package.json +76 -0
  372. package/sql/fivepixels-lite-init.sql +518 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/db/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import BetterSqlite3 from 'better-sqlite3';
2
+ export type SqliteDatabase = BetterSqlite3.Database;
3
+ export declare class DatabaseConfigurationError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export interface OpenDatabaseOptions {
7
+ fileMustExist?: boolean;
8
+ readonly?: boolean;
9
+ }
10
+ export declare function openDatabase(dbPath: string, options?: OpenDatabaseOptions): SqliteDatabase;
11
+ export declare function applyAndVerifyPragmas(database: SqliteDatabase): void;
12
+ export declare function getSqliteVersion(database: SqliteDatabase): string;
13
+ export declare function isWalResetSafeVersion(version: string): boolean;
14
+ export declare function assertSafeSqliteVersion(version: string): void;
15
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAGA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC;AAEpD,qBAAa,0BAA2B,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAInC;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAAwB,GAChC,cAAc,CAsBhB;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAsBpE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAGjE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa9D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM7D"}
@@ -0,0 +1,82 @@
1
+ import { chmodSync, existsSync, mkdirSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import BetterSqlite3 from 'better-sqlite3';
4
+ export class DatabaseConfigurationError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'DatabaseConfigurationError';
8
+ }
9
+ }
10
+ export function openDatabase(dbPath, options = {}) {
11
+ const existed = existsSync(dbPath);
12
+ if (!options.readonly) {
13
+ mkdirSync(dirname(dbPath), { mode: 0o700, recursive: true });
14
+ }
15
+ const database = new BetterSqlite3(dbPath, {
16
+ fileMustExist: options.fileMustExist ?? false,
17
+ readonly: options.readonly ?? false,
18
+ });
19
+ try {
20
+ if (!options.readonly) {
21
+ applyAndVerifyPragmas(database);
22
+ if (!existed)
23
+ chmodSync(dbPath, 0o600);
24
+ }
25
+ assertSafeSqliteVersion(getSqliteVersion(database));
26
+ return database;
27
+ }
28
+ catch (error) {
29
+ database.close();
30
+ throw error;
31
+ }
32
+ }
33
+ export function applyAndVerifyPragmas(database) {
34
+ const journalMode = String(database.pragma('journal_mode = WAL', { simple: true })).toLowerCase();
35
+ database.pragma('foreign_keys = ON');
36
+ database.pragma('busy_timeout = 5000');
37
+ database.pragma('synchronous = NORMAL');
38
+ const foreignKeys = Number(database.pragma('foreign_keys', { simple: true }));
39
+ const busyTimeout = Number(database.pragma('busy_timeout', { simple: true }));
40
+ const synchronous = Number(database.pragma('synchronous', { simple: true }));
41
+ if (journalMode !== 'wal') {
42
+ throw new DatabaseConfigurationError('SQLite WAL mode could not be enabled.');
43
+ }
44
+ if (foreignKeys !== 1) {
45
+ throw new DatabaseConfigurationError('SQLite foreign key enforcement could not be enabled.');
46
+ }
47
+ if (busyTimeout !== 5000) {
48
+ throw new DatabaseConfigurationError('SQLite busy timeout could not be configured.');
49
+ }
50
+ if (synchronous !== 1) {
51
+ throw new DatabaseConfigurationError('SQLite synchronous mode could not be set to NORMAL.');
52
+ }
53
+ }
54
+ export function getSqliteVersion(database) {
55
+ const row = database.prepare('SELECT sqlite_version() AS version').get();
56
+ return row.version;
57
+ }
58
+ export function isWalResetSafeVersion(version) {
59
+ const parts = version.split('.').map((value) => Number(value));
60
+ const major = parts[0] ?? 0;
61
+ const minor = parts[1] ?? 0;
62
+ const patch = parts[2] ?? 0;
63
+ if (major > 3)
64
+ return true;
65
+ if (major !== 3)
66
+ return false;
67
+ if (minor > 51)
68
+ return true;
69
+ if (minor === 51)
70
+ return patch >= 3;
71
+ if (minor === 50)
72
+ return patch >= 7;
73
+ if (minor === 44)
74
+ return patch >= 6;
75
+ return false;
76
+ }
77
+ export function assertSafeSqliteVersion(version) {
78
+ if (!isWalResetSafeVersion(version)) {
79
+ throw new DatabaseConfigurationError(`SQLite ${version} does not contain the required WAL-reset safety fix.`);
80
+ }
81
+ }
82
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAI3C,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAmB,OAAe;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAOD,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,UAA+B,EAAE;IAEjC,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE;QACzC,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,KAAK;QAC7C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtB,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,CAAC,OAAO;gBAAE,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QACD,uBAAuB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAwB;IAC5D,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAClG,QAAQ,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAExC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE7E,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,0BAA0B,CAAC,uCAAuC,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,0BAA0B,CAAC,sDAAsD,CAAC,CAAC;IAC/F,CAAC;IACD,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,0BAA0B,CAAC,8CAA8C,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,0BAA0B,CAAC,qDAAqD,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAwB;IACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAAyB,CAAC;IAChG,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5B,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,0BAA0B,CAClC,UAAU,OAAO,sDAAsD,CACxE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function sqlGuidOrder(column: string): string;
2
+ //# sourceMappingURL=guid-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guid-order.d.ts","sourceRoot":"","sources":["../../src/db/guid-order.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAInD"}
@@ -0,0 +1,9 @@
1
+ // SqlGuid compares Guid.ToByteArray() in order 10..15, 8,9, 6,7, 4,5, 0..3.
2
+ // SQL expressions use only repository-owned identifiers, never request values.
3
+ export function sqlGuidOrder(column) {
4
+ if (!/^(?:[a-z_]+\.)?[a-z_]+$/.test(column))
5
+ throw new Error('invalid-guid-column');
6
+ return '(' + [[25, 12], [20, 4], [17, 2], [15, 2], [12, 2], [10, 2], [7, 2], [5, 2], [3, 2], [1, 2]]
7
+ .map(([start, length]) => `substr(${column}, ${start}, ${length})`).join(' || ') + ')';
8
+ }
9
+ //# sourceMappingURL=guid-order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guid-order.js","sourceRoot":"","sources":["../../src/db/guid-order.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACpF,OAAO,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACjG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,UAAU,MAAM,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { SqliteDatabase } from './connection.js';
2
+ export interface MigrationFile {
3
+ checksum: string;
4
+ name: string;
5
+ path: string;
6
+ sql: string;
7
+ version: number;
8
+ }
9
+ export interface AppliedMigration {
10
+ appliedAt: string;
11
+ checksum: string;
12
+ name: string;
13
+ version: number;
14
+ }
15
+ export interface MigrationStatus {
16
+ applied: AppliedMigration[];
17
+ currentVersion: number;
18
+ pending: MigrationFile[];
19
+ }
20
+ export interface MigrationResult {
21
+ appliedVersions: number[];
22
+ backupPath?: string;
23
+ currentVersion: number;
24
+ removedBackups: string[];
25
+ }
26
+ export interface MigrationOptions {
27
+ automaticBackupRetention?: number;
28
+ dbPath: string;
29
+ migrationsDirectory?: string;
30
+ }
31
+ export declare class MigrationError extends Error {
32
+ constructor(message: string, options?: ErrorOptions);
33
+ }
34
+ export declare function loadMigrations(directory?: string): MigrationFile[];
35
+ export declare function getMigrationStatus(database: SqliteDatabase, migrationsDirectory?: string): MigrationStatus;
36
+ export declare function migrateDatabase(database: SqliteDatabase, options: MigrationOptions): Promise<MigrationResult>;
37
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAMtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,cAAe,SAAQ,KAAK;gBACpB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAI3D;AAMD,wBAAgB,cAAc,CAAC,SAAS,SAA+B,GAAG,aAAa,EAAE,CAgCxF;AA4BD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,mBAAmB,SAA+B,GACjD,eAAe,CAyBjB;AAOD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAyD1B"}
@@ -0,0 +1,145 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { basename, dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createBackup, pruneAutomaticBackups } from './backup.js';
6
+ import { prepareStorageMigration } from './storage-migration.js';
7
+ const DEFAULT_MIGRATIONS_DIRECTORY = fileURLToPath(new URL('./migrations/', import.meta.url));
8
+ const MIGRATION_FILE_PATTERN = /^(\d+)_([a-z0-9_]+)\.sql$/;
9
+ export class MigrationError extends Error {
10
+ constructor(message, options) {
11
+ super(message, options);
12
+ this.name = 'MigrationError';
13
+ }
14
+ }
15
+ function checksum(sql) {
16
+ return createHash('sha256').update(sql).digest('hex');
17
+ }
18
+ export function loadMigrations(directory = DEFAULT_MIGRATIONS_DIRECTORY) {
19
+ const migrations = readdirSync(directory)
20
+ .filter((fileName) => fileName.endsWith('.sql'))
21
+ .map((fileName) => {
22
+ const match = MIGRATION_FILE_PATTERN.exec(fileName);
23
+ if (match === null) {
24
+ throw new MigrationError(`Invalid migration file name: ${fileName}`);
25
+ }
26
+ const version = Number(match[1]);
27
+ const name = match[2];
28
+ if (!Number.isSafeInteger(version) || version < 1 || name === undefined) {
29
+ throw new MigrationError(`Invalid migration file name: ${fileName}`);
30
+ }
31
+ const path = join(directory, fileName);
32
+ const sql = readFileSync(path, 'utf8');
33
+ return { checksum: checksum(sql), name, path, sql, version };
34
+ })
35
+ .sort((left, right) => left.version - right.version);
36
+ migrations.forEach((migration, index) => {
37
+ if (index > 0 && migrations[index - 1]?.version === migration.version) {
38
+ throw new MigrationError(`Duplicate migration version: ${migration.version}`);
39
+ }
40
+ const expectedVersion = index + 1;
41
+ if (migration.version !== expectedVersion) {
42
+ throw new MigrationError(`Migration sequence must be contiguous. Expected ${expectedVersion}, found ${migration.version}.`);
43
+ }
44
+ });
45
+ return migrations;
46
+ }
47
+ function migrationTableExists(database) {
48
+ const row = database.prepare("SELECT 1 AS found FROM sqlite_master WHERE type = 'table' AND name = ?").get('schema_migrations');
49
+ return row?.found === 1;
50
+ }
51
+ function databaseHasUserSchema(database) {
52
+ const row = database.prepare(`
53
+ SELECT 1 AS found
54
+ FROM sqlite_master
55
+ WHERE type = 'table'
56
+ AND name NOT LIKE 'sqlite_%'
57
+ LIMIT 1
58
+ `).get();
59
+ return row?.found === 1;
60
+ }
61
+ function readAppliedMigrations(database) {
62
+ if (!migrationTableExists(database))
63
+ return [];
64
+ const rows = database.prepare('SELECT version, name, checksum, applied_at AS appliedAt FROM schema_migrations ORDER BY version').all();
65
+ return rows;
66
+ }
67
+ export function getMigrationStatus(database, migrationsDirectory = DEFAULT_MIGRATIONS_DIRECTORY) {
68
+ const available = loadMigrations(migrationsDirectory);
69
+ const applied = readAppliedMigrations(database);
70
+ const availableByVersion = new Map(available.map((migration) => [migration.version, migration]));
71
+ for (const [index, appliedMigration] of applied.entries()) {
72
+ if (appliedMigration.version !== index + 1) {
73
+ throw new MigrationError('Applied migration history is not contiguous.');
74
+ }
75
+ const migration = availableByVersion.get(appliedMigration.version);
76
+ if (migration === undefined) {
77
+ throw new MigrationError(`Applied migration ${appliedMigration.version} is missing from the package.`);
78
+ }
79
+ if (migration.name !== appliedMigration.name || migration.checksum !== appliedMigration.checksum) {
80
+ throw new MigrationError(`Applied migration ${appliedMigration.version} has been modified.`);
81
+ }
82
+ }
83
+ const appliedVersions = new Set(applied.map((migration) => migration.version));
84
+ const pending = available.filter((migration) => !appliedVersions.has(migration.version));
85
+ return {
86
+ applied,
87
+ currentVersion: applied.at(-1)?.version ?? 0,
88
+ pending,
89
+ };
90
+ }
91
+ function automaticBackupPath(dbPath, fromVersion, toVersion) {
92
+ const now = new Date().toISOString().replace(/[:.]/g, '-');
93
+ return join(dirname(dbPath), 'backups', `auto-v${fromVersion}-to-v${toVersion}-${now}.db`);
94
+ }
95
+ export async function migrateDatabase(database, options) {
96
+ const status = getMigrationStatus(database, options.migrationsDirectory);
97
+ if (status.pending.length === 0) {
98
+ return {
99
+ appliedVersions: [],
100
+ currentVersion: status.currentVersion,
101
+ removedBackups: [],
102
+ };
103
+ }
104
+ let backupPath;
105
+ if (existsSync(options.dbPath) && databaseHasUserSchema(database)) {
106
+ const targetVersion = status.pending.at(-1)?.version ?? status.currentVersion;
107
+ const backup = await createBackup(database, automaticBackupPath(options.dbPath, status.currentVersion, targetVersion));
108
+ backupPath = backup.path;
109
+ }
110
+ const appliedVersions = [];
111
+ const available = loadMigrations(options.migrationsDirectory);
112
+ for (const migration of status.pending) {
113
+ try {
114
+ database.transaction(() => {
115
+ const isStorageAlignment = (migration.version === 6 && migration.name === 'align_credentials')
116
+ || (migration.version === 7 && migration.name === 'align_storage_values');
117
+ const verify = isStorageAlignment
118
+ ? prepareStorageMigration(database, available, migration.version) : undefined;
119
+ database.exec(migration.sql);
120
+ verify?.();
121
+ database.prepare('INSERT INTO schema_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)').run(migration.version, migration.name, migration.checksum, new Date().toISOString());
122
+ }).immediate();
123
+ appliedVersions.push(migration.version);
124
+ }
125
+ catch (error) {
126
+ const safeReasons = new Set([
127
+ 'unsupported-custom-schema', 'inconsistent-credential-keys', 'invalid-storage-timestamp',
128
+ 'invalid-storage-pathname', 'foreign-keys-required', 'foreign-key-check-failed',
129
+ 'integrity-check-failed', 'migration-row-count-mismatch',
130
+ ]);
131
+ const reason = error instanceof Error && safeReasons.has(error.message) ? ` (${error.message})` : '';
132
+ throw new MigrationError(`Migration ${basename(migration.path)} failed${reason}.`, { cause: error });
133
+ }
134
+ }
135
+ const removedBackups = backupPath === undefined
136
+ ? []
137
+ : pruneAutomaticBackups(options.dbPath, options.automaticBackupRetention ?? 3);
138
+ return {
139
+ ...(backupPath === undefined ? {} : { backupPath }),
140
+ appliedVersions,
141
+ currentVersion: appliedVersions.at(-1) ?? status.currentVersion,
142
+ removedBackups,
143
+ };
144
+ }
145
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ CREATE TABLE schema_migrations (
2
+ version INTEGER PRIMARY KEY CHECK (version > 0),
3
+ name TEXT NOT NULL UNIQUE,
4
+ checksum TEXT NOT NULL CHECK (length(checksum) = 64),
5
+ applied_at TEXT NOT NULL
6
+ ) STRICT;
@@ -0,0 +1,95 @@
1
+ CREATE TABLE users (
2
+ user_id TEXT PRIMARY KEY
3
+ , status_code INTEGER NOT NULL DEFAULT 1
4
+ , user_name TEXT NOT NULL
5
+ , profile_image_url TEXT
6
+ , created_at TEXT NOT NULL
7
+ , updated_at TEXT NOT NULL
8
+ , CHECK (
9
+ length(user_id) = 36
10
+ AND user_id = lower(user_id)
11
+ AND substr(user_id, 9, 1) = '-'
12
+ AND substr(user_id, 14, 1) = '-'
13
+ AND substr(user_id, 19, 1) = '-'
14
+ AND substr(user_id, 24, 1) = '-'
15
+ AND length(replace(user_id, '-', '')) = 32
16
+ AND replace(user_id, '-', '') NOT GLOB '*[^0-9a-f]*'
17
+ )
18
+ , CHECK (status_code IN (1, 2, 3))
19
+ , CHECK (user_name = trim(user_name) AND length(user_name) BETWEEN 1 AND 100)
20
+ , CHECK (
21
+ profile_image_url IS NULL
22
+ OR (profile_image_url = trim(profile_image_url) AND length(profile_image_url) BETWEEN 1 AND 2048)
23
+ )
24
+ ) STRICT;
25
+
26
+ CREATE TABLE local_credentials (
27
+ user_id TEXT PRIMARY KEY
28
+ , login_id TEXT NOT NULL
29
+ , normalized_login_id TEXT NOT NULL
30
+ , email TEXT NOT NULL
31
+ , normalized_email TEXT NOT NULL
32
+ , password_hash TEXT NOT NULL
33
+ , failed_login_count INTEGER NOT NULL DEFAULT 0
34
+ , locked_until TEXT
35
+ , email_verified_at TEXT
36
+ , password_changed_at TEXT NOT NULL
37
+ , last_login_at TEXT
38
+ , lock_version INTEGER NOT NULL DEFAULT 0
39
+ , created_at TEXT NOT NULL
40
+ , updated_at TEXT NOT NULL
41
+ , CONSTRAINT fk_local_credentials_user FOREIGN KEY (user_id)
42
+ REFERENCES users (user_id) ON DELETE RESTRICT
43
+ , CHECK (login_id = trim(login_id) AND length(login_id) BETWEEN 4 AND 50)
44
+ , CHECK (substr(login_id, 1, 1) GLOB '[A-Za-z0-9]')
45
+ , CHECK (login_id NOT GLOB '*[^A-Za-z0-9._-]*')
46
+ , CHECK (normalized_login_id = lower(login_id))
47
+ , CHECK (email = trim(email) AND length(email) BETWEEN 3 AND 320)
48
+ , CHECK (normalized_email = trim(normalized_email) AND length(normalized_email) BETWEEN 3 AND 320)
49
+ , CHECK (password_hash = trim(password_hash) AND length(password_hash) BETWEEN 20 AND 512)
50
+ , CHECK (failed_login_count >= 0)
51
+ , CHECK (lock_version >= 0)
52
+ ) STRICT;
53
+
54
+ CREATE UNIQUE INDEX uq_local_credentials_normalized_login_id
55
+ ON local_credentials (normalized_login_id);
56
+
57
+ CREATE UNIQUE INDEX uq_local_credentials_normalized_email
58
+ ON local_credentials (normalized_email);
59
+
60
+ CREATE TABLE auth_refresh_tokens (
61
+ refresh_token_id TEXT PRIMARY KEY
62
+ , user_id TEXT NOT NULL
63
+ , token_hash BLOB NOT NULL UNIQUE
64
+ , expires_at TEXT NOT NULL
65
+ , last_used_at TEXT
66
+ , revoked_at TEXT
67
+ , replaced_by_token_id TEXT
68
+ , lock_version INTEGER NOT NULL DEFAULT 0
69
+ , created_at TEXT NOT NULL
70
+ , CONSTRAINT fk_auth_refresh_tokens_user FOREIGN KEY (user_id)
71
+ REFERENCES users (user_id) ON DELETE RESTRICT
72
+ , CONSTRAINT fk_auth_refresh_tokens_replacement FOREIGN KEY (replaced_by_token_id)
73
+ REFERENCES auth_refresh_tokens (refresh_token_id) ON DELETE RESTRICT
74
+ , CHECK (
75
+ length(refresh_token_id) = 36
76
+ AND refresh_token_id = lower(refresh_token_id)
77
+ AND substr(refresh_token_id, 9, 1) = '-'
78
+ AND substr(refresh_token_id, 14, 1) = '-'
79
+ AND substr(refresh_token_id, 19, 1) = '-'
80
+ AND substr(refresh_token_id, 24, 1) = '-'
81
+ AND length(replace(refresh_token_id, '-', '')) = 32
82
+ AND replace(refresh_token_id, '-', '') NOT GLOB '*[^0-9a-f]*'
83
+ )
84
+ , CHECK (length(token_hash) = 32)
85
+ , CHECK (expires_at > created_at)
86
+ , CHECK (
87
+ replaced_by_token_id IS NULL
88
+ OR (replaced_by_token_id <> refresh_token_id AND revoked_at IS NOT NULL)
89
+ )
90
+ , CHECK (lock_version >= 0)
91
+ ) STRICT;
92
+
93
+ CREATE INDEX ix_auth_refresh_tokens_user_active
94
+ ON auth_refresh_tokens (user_id, expires_at, refresh_token_id)
95
+ WHERE revoked_at IS NULL;
@@ -0,0 +1,62 @@
1
+ CREATE TABLE projects (
2
+ project_id TEXT PRIMARY KEY
3
+ CHECK (
4
+ length(project_id) = 36
5
+ AND substr(project_id, 9, 1) = '-'
6
+ AND substr(project_id, 14, 1) = '-'
7
+ AND substr(project_id, 19, 1) = '-'
8
+ AND substr(project_id, 24, 1) = '-'
9
+ AND project_id = lower(project_id)
10
+ AND length(replace(project_id, '-', '')) = 32
11
+ AND replace(project_id, '-', '') NOT GLOB '*[^0-9a-f]*'
12
+ ),
13
+ creator_id TEXT NOT NULL,
14
+ status_code INTEGER NOT NULL DEFAULT 1
15
+ CHECK (status_code IN (1, 2)),
16
+ project_name TEXT NOT NULL
17
+ CHECK (
18
+ length(project_name) BETWEEN 1 AND 100
19
+ AND project_name = trim(project_name)
20
+ ),
21
+ lock_version INTEGER NOT NULL DEFAULT 0
22
+ CHECK (lock_version >= 0),
23
+ created_at TEXT NOT NULL,
24
+ updated_at TEXT NOT NULL,
25
+ CONSTRAINT fk_projects_creator
26
+ FOREIGN KEY (creator_id) REFERENCES users(user_id)
27
+ ON UPDATE RESTRICT ON DELETE RESTRICT
28
+ ) STRICT;
29
+
30
+ CREATE INDEX ix_projects_status_created_at
31
+ ON projects (status_code, created_at DESC, project_id DESC);
32
+
33
+ CREATE INDEX ix_projects_creator_created_at
34
+ ON projects (creator_id, created_at DESC, project_id DESC);
35
+
36
+ CREATE TABLE project_members (
37
+ project_id TEXT NOT NULL,
38
+ user_id TEXT NOT NULL,
39
+ role_code INTEGER NOT NULL
40
+ CHECK (role_code IN (1, 2)),
41
+ added_by TEXT NOT NULL,
42
+ lock_version INTEGER NOT NULL DEFAULT 0
43
+ CHECK (lock_version >= 0),
44
+ joined_at TEXT NOT NULL,
45
+ updated_at TEXT NOT NULL,
46
+ CONSTRAINT pk_project_members PRIMARY KEY (project_id, user_id),
47
+ CONSTRAINT fk_project_members_project
48
+ FOREIGN KEY (project_id) REFERENCES projects(project_id)
49
+ ON UPDATE RESTRICT ON DELETE RESTRICT,
50
+ CONSTRAINT fk_project_members_user
51
+ FOREIGN KEY (user_id) REFERENCES users(user_id)
52
+ ON UPDATE RESTRICT ON DELETE RESTRICT,
53
+ CONSTRAINT fk_project_members_added_by
54
+ FOREIGN KEY (added_by) REFERENCES users(user_id)
55
+ ON UPDATE RESTRICT ON DELETE RESTRICT
56
+ ) STRICT;
57
+
58
+ CREATE INDEX ix_project_members_user_joined_at
59
+ ON project_members (user_id, joined_at DESC, project_id DESC);
60
+
61
+ CREATE INDEX ix_project_members_project_role
62
+ ON project_members (project_id, role_code, user_id);