@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":"project.schemas.d.ts","sourceRoot":"","sources":["../../src/projects/project.schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import { communityErrorResponses, communityResponseSchema, object, paramsSchema, uuidSchema, } from '../community/schemas.js';
2
+ const timestampSchema = { type: 'string', format: 'date-time' };
3
+ export const projectResponseResultSchema = {
4
+ type: 'object',
5
+ additionalProperties: false,
6
+ required: ['id', 'creatorId', 'projectName', 'status', 'version', 'createdAt', 'updatedAt'],
7
+ properties: {
8
+ id: uuidSchema,
9
+ creatorId: uuidSchema,
10
+ projectName: { type: 'string', minLength: 1, maxLength: 100 },
11
+ status: { type: 'string', enum: ['ACTIVE', 'ARCHIVED'] },
12
+ version: { type: 'integer', minimum: 0 },
13
+ createdAt: timestampSchema,
14
+ updatedAt: timestampSchema,
15
+ },
16
+ };
17
+ export const projectListItemResultSchema = {
18
+ type: 'object',
19
+ additionalProperties: false,
20
+ required: ['id', 'projectName', 'status', 'projectRole', 'version', 'createdAt', 'updatedAt'],
21
+ properties: {
22
+ id: uuidSchema,
23
+ projectName: { type: 'string', minLength: 1, maxLength: 100 },
24
+ status: { type: 'string', enum: ['ACTIVE', 'ARCHIVED'] },
25
+ projectRole: { type: 'string', enum: ['OWNER', 'MEMBER'] },
26
+ version: { type: 'integer', minimum: 0 },
27
+ createdAt: timestampSchema,
28
+ updatedAt: timestampSchema,
29
+ },
30
+ };
31
+ export const createProjectSchema = {
32
+ tags: ['projects'],
33
+ summary: '프로젝트 생성',
34
+ security: [{ userJwt: [] }],
35
+ body: {
36
+ type: 'object',
37
+ additionalProperties: false,
38
+ required: ['projectName'],
39
+ properties: {
40
+ projectName: { type: 'string', minLength: 1, maxLength: 100 },
41
+ },
42
+ },
43
+ response: {
44
+ 201: communityResponseSchema(projectResponseResultSchema),
45
+ ...communityErrorResponses,
46
+ },
47
+ };
48
+ export const listProjectsSchema = {
49
+ tags: ['projects'],
50
+ summary: '참여 프로젝트 목록 조회',
51
+ security: [{ userJwt: [] }],
52
+ querystring: {
53
+ type: 'object',
54
+ additionalProperties: false,
55
+ properties: {
56
+ query: { type: 'string' },
57
+ status: { type: 'string' },
58
+ page: { type: 'integer', default: 1 },
59
+ pageSize: { type: 'integer', default: 20 },
60
+ },
61
+ },
62
+ response: {
63
+ 200: communityResponseSchema({
64
+ type: 'array',
65
+ items: projectListItemResultSchema,
66
+ }),
67
+ ...communityErrorResponses,
68
+ },
69
+ };
70
+ export const getProjectSchema = {
71
+ tags: ['projects'],
72
+ summary: '프로젝트 상세 조회',
73
+ security: [{ userJwt: [] }],
74
+ params: {
75
+ type: 'object',
76
+ additionalProperties: false,
77
+ required: ['projectId'],
78
+ properties: { projectId: uuidSchema },
79
+ },
80
+ response: {
81
+ 200: communityResponseSchema(projectResponseResultSchema),
82
+ ...communityErrorResponses,
83
+ },
84
+ };
85
+ export const projectParamsSchema = paramsSchema(['projectId']);
86
+ export const renameProjectBodySchema = object({
87
+ projectName: { type: 'string', minLength: 1, maxLength: 100 },
88
+ });
89
+ export const projectMutationResponseSchema = communityResponseSchema(projectResponseResultSchema);
90
+ //# sourceMappingURL=project.schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.schemas.js","sourceRoot":"","sources":["../../src/projects/project.schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type PaginationMetadata } from '../community/contracts.js';
2
+ import type { ProjectRepository } from './project.repository.js';
3
+ export type ProjectStatus = 'ACTIVE' | 'ARCHIVED';
4
+ export type ProjectRole = 'OWNER' | 'MEMBER';
5
+ export interface ProjectResponse {
6
+ createdAt: string;
7
+ creatorId: string;
8
+ id: string;
9
+ projectName: string;
10
+ status: ProjectStatus;
11
+ updatedAt: string;
12
+ version: number;
13
+ }
14
+ export interface ProjectListItemResponse {
15
+ createdAt: string;
16
+ id: string;
17
+ projectName: string;
18
+ projectRole: ProjectRole;
19
+ status: ProjectStatus;
20
+ updatedAt: string;
21
+ version: number;
22
+ }
23
+ export interface ProjectListRequest {
24
+ page?: number;
25
+ pageSize?: number;
26
+ query?: string;
27
+ status?: string;
28
+ }
29
+ export interface ProjectListResponse {
30
+ items: ProjectListItemResponse[];
31
+ pagination: PaginationMetadata;
32
+ }
33
+ export declare class ProjectService {
34
+ private readonly repository;
35
+ constructor(repository: ProjectRepository);
36
+ create(currentUserId: string, projectName: string): ProjectResponse;
37
+ list(currentUserId: string, request: ProjectListRequest): ProjectListResponse;
38
+ get(currentUserId: string, projectId: string): ProjectResponse;
39
+ }
40
+ //# sourceMappingURL=project.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.service.d.ts","sourceRoot":"","sources":["../../src/projects/project.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGlF,OAAO,KAAK,EAAE,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAQhE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;AAClD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,UAAU,EAAE,kBAAkB,CAAC;CAChC;AA0FD,qBAAa,cAAc;IACN,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,iBAAiB;IAE1D,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,eAAe;IAgBnE,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,mBAAmB;IAkB7E,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe;CAOtE"}
@@ -0,0 +1,128 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { pageMetadata } from '../community/contracts.js';
3
+ import { CommunityApiError } from '../community/errors.js';
4
+ import { storageTimestamp } from '../storage/values.js';
5
+ const ACTIVE_STATUS = 1;
6
+ const ARCHIVED_STATUS = 2;
7
+ const OWNER_ROLE = 1;
8
+ const MEMBER_ROLE = 2;
9
+ function projectStatus(statusCode) {
10
+ if (statusCode === ACTIVE_STATUS)
11
+ return 'ACTIVE';
12
+ if (statusCode === ARCHIVED_STATUS)
13
+ return 'ARCHIVED';
14
+ throw new Error('Unknown project status code.');
15
+ }
16
+ function projectRole(roleCode) {
17
+ if (roleCode === OWNER_ROLE)
18
+ return 'OWNER';
19
+ if (roleCode === MEMBER_ROLE)
20
+ return 'MEMBER';
21
+ throw new Error('Unknown project role code.');
22
+ }
23
+ function mapProject(project) {
24
+ return {
25
+ id: project.id,
26
+ creatorId: project.creatorId,
27
+ projectName: project.name,
28
+ status: projectStatus(project.statusCode),
29
+ version: project.lockVersion,
30
+ createdAt: project.createdAt,
31
+ updatedAt: project.updatedAt,
32
+ };
33
+ }
34
+ function mapProjectListItem(project) {
35
+ return {
36
+ id: project.id,
37
+ projectName: project.name,
38
+ status: projectStatus(project.statusCode),
39
+ projectRole: projectRole(project.roleCode),
40
+ version: project.lockVersion,
41
+ createdAt: project.createdAt,
42
+ updatedAt: project.updatedAt,
43
+ };
44
+ }
45
+ function normalizeProjectName(value) {
46
+ const name = value.trim();
47
+ if (name.length < 1 || name.length > 100) {
48
+ throw new CommunityApiError(400, 'invalid-project-name', '프로젝트 이름은 1자 이상 100자 이하여야 합니다.');
49
+ }
50
+ return name;
51
+ }
52
+ function parseStatus(value) {
53
+ if (value === undefined || value.trim() === '')
54
+ return undefined;
55
+ const status = value.trim().toUpperCase();
56
+ if (status === 'ACTIVE')
57
+ return ACTIVE_STATUS;
58
+ if (status === 'ARCHIVED')
59
+ return ARCHIVED_STATUS;
60
+ throw new CommunityApiError(400, 'invalid-project-status', '프로젝트 상태는 ACTIVE 또는 ARCHIVED여야 합니다.');
61
+ }
62
+ function pageValue(value) {
63
+ const page = value ?? 1;
64
+ if (!Number.isSafeInteger(page) || page < 1) {
65
+ throw new CommunityApiError(400, 'invalid-page', 'page는 1 이상이어야 합니다.');
66
+ }
67
+ return page;
68
+ }
69
+ function pageSizeValue(value) {
70
+ const pageSize = value ?? 20;
71
+ if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 100) {
72
+ throw new CommunityApiError(400, 'invalid-page-size', 'pageSize는 1 이상 100 이하여야 합니다.');
73
+ }
74
+ return pageSize;
75
+ }
76
+ function escapeLike(value) {
77
+ return value
78
+ .replaceAll('~', '~~')
79
+ .replaceAll('%', '~%')
80
+ .replaceAll('_', '~_')
81
+ .replaceAll('[', '~[');
82
+ }
83
+ export class ProjectService {
84
+ repository;
85
+ constructor(repository) {
86
+ this.repository = repository;
87
+ }
88
+ create(currentUserId, projectName) {
89
+ const now = storageTimestamp(new Date());
90
+ const project = this.repository.createWithOwner({
91
+ id: randomUUID(),
92
+ creatorId: currentUserId,
93
+ statusCode: ACTIVE_STATUS,
94
+ name: normalizeProjectName(projectName),
95
+ roleCode: OWNER_ROLE,
96
+ addedBy: currentUserId,
97
+ createdAt: now,
98
+ joinedAt: now,
99
+ updatedAt: now,
100
+ });
101
+ return mapProject(project);
102
+ }
103
+ list(currentUserId, request) {
104
+ const page = pageValue(request.page);
105
+ const pageSize = pageSizeValue(request.pageSize);
106
+ const query = request.query?.trim();
107
+ const statusCode = parseStatus(request.status);
108
+ const records = this.repository.listForUser({
109
+ userId: currentUserId,
110
+ limit: pageSize,
111
+ offset: (page - 1) * pageSize,
112
+ ...(query === undefined || query === '' ? {} : { namePattern: `%${escapeLike(query)}%` }),
113
+ ...(statusCode === undefined ? {} : { statusCode }),
114
+ });
115
+ return {
116
+ items: records.items.map(mapProjectListItem),
117
+ pagination: pageMetadata(page, pageSize, records.totalCount),
118
+ };
119
+ }
120
+ get(currentUserId, projectId) {
121
+ const project = this.repository.findForMember(projectId, currentUserId);
122
+ if (project === undefined) {
123
+ throw new CommunityApiError(404, 'project-not-found', '프로젝트를 찾을 수 없습니다.');
124
+ }
125
+ return mapProject(project);
126
+ }
127
+ }
128
+ //# sourceMappingURL=project.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.service.js","sourceRoot":"","sources":["../../src/projects/project.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { TransactionRunner } from '../db/transaction.js';
2
+ import type { PageElementRepository } from '../page-elements/page-element.repository.js';
3
+ import type { ContentUpdate } from '../page-elements/page-element.types.js';
4
+ import type { ProjectAccessPolicy } from '../projects/project-access.policy.js';
5
+ import type { ReportCaseRepository } from '../report-cases/report-case.repository.js';
6
+ import type { ReplyRepository } from './reply.repository.js';
7
+ import type { ReplyResponse, ReplyTarget } from './reply.types.js';
8
+ export declare class ReplyMutationService {
9
+ private readonly transactions;
10
+ private readonly policy;
11
+ private readonly repository;
12
+ private readonly cases;
13
+ private readonly elements;
14
+ constructor(transactions: TransactionRunner, policy: ProjectAccessPolicy, repository: ReplyRepository, cases: ReportCaseRepository, elements: PageElementRepository);
15
+ editReply(target: ReplyTarget, version: number, body: ContentUpdate): ReplyResponse;
16
+ deleteReply(target: ReplyTarget, version: number): void;
17
+ private editableReply;
18
+ }
19
+ //# sourceMappingURL=reply-mutation.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply-mutation.service.d.ts","sourceRoot":"","sources":["../../src/replies/reply-mutation.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEnE,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAJR,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,mBAAmB,EAC3B,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,qBAAqB;IAG3C,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa;IAYnE,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAO9D,OAAO,CAAC,aAAa;CAYtB"}
@@ -0,0 +1,51 @@
1
+ import { CommunityApiError } from '../community/errors.js';
2
+ import { verifyVersion } from '../community/etag.js';
3
+ import { normalizePageElements } from '../page-elements/page-element.input.js';
4
+ import { editable } from '../projects/project-access.policy.js';
5
+ import { storageTimestamp } from '../storage/values.js';
6
+ import { normalizeReplyContent } from './reply.input.js';
7
+ export class ReplyMutationService {
8
+ transactions;
9
+ policy;
10
+ repository;
11
+ cases;
12
+ elements;
13
+ constructor(transactions, policy, repository, cases, elements) {
14
+ this.transactions = transactions;
15
+ this.policy = policy;
16
+ this.repository = repository;
17
+ this.cases = cases;
18
+ this.elements = elements;
19
+ }
20
+ editReply(target, version, body) {
21
+ return this.transactions.write(() => {
22
+ this.editableReply(target, version);
23
+ const timestamp = storageTimestamp(new Date());
24
+ this.repository.editReply(target.replyId, normalizeReplyContent(body.content), timestamp);
25
+ if (body.pageElements != null) {
26
+ this.elements.replaceReply(target.replyId, target.actorId, normalizePageElements(body.pageElements), timestamp);
27
+ }
28
+ return this.repository.get(target.projectId, target.feedbackId, target.caseId, target.replyId);
29
+ });
30
+ }
31
+ deleteReply(target, version) {
32
+ this.transactions.write(() => {
33
+ this.editableReply(target, version);
34
+ this.repository.deleteReply(target.replyId, storageTimestamp(new Date()));
35
+ });
36
+ }
37
+ editableReply(target, version) {
38
+ const owner = this.policy.authorize(target);
39
+ this.cases.get(target.projectId, target.feedbackId, target.caseId);
40
+ const reply = this.repository.get(target.projectId, target.feedbackId, target.caseId, target.replyId);
41
+ if (reply.status === 'DELETED')
42
+ throw new CommunityApiError(409, 'reply-deleted', '삭제된 답글입니다.');
43
+ if (!['SUGGESTED', 'ADDITIONAL_QUESTION', 'FOUND_ERROR', 'RECHECK_REQUESTED'].includes(reply.type)) {
44
+ throw new CommunityApiError(409, 'system-reply-immutable', '시스템 답글은 수정하거나 삭제할 수 없습니다.');
45
+ }
46
+ editable(owner || reply.author.id === target.actorId, 'reply-edit-forbidden');
47
+ verifyVersion(reply.version, version);
48
+ return reply;
49
+ }
50
+ }
51
+ //# sourceMappingURL=reply-mutation.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply-mutation.service.js","sourceRoot":"","sources":["../../src/replies/reply-mutation.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function normalizeReplyContent(value: string): string;
2
+ export declare function replyTypeCode(type: string): number;
3
+ export declare function replyTypeKey(typeCode: number): string;
4
+ //# sourceMappingURL=reply.input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply.input.d.ts","sourceRoot":"","sources":["../../src/replies/reply.input.ts"],"names":[],"mappings":"AAEA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASlD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAarD"}
@@ -0,0 +1,33 @@
1
+ import { CommunityApiError } from '../community/errors.js';
2
+ export function normalizeReplyContent(value) {
3
+ const normalized = value.trim();
4
+ if (normalized.length < 1 || normalized.length > 10_000 || normalized.includes('\0')) {
5
+ throw new CommunityApiError(400, 'invalid-reply-content', '답글 내용은 1자 이상 10,000자 이하여야 합니다.');
6
+ }
7
+ return normalized;
8
+ }
9
+ export function replyTypeCode(type) {
10
+ switch (type.trim().toUpperCase()) {
11
+ case 'SUGGESTED': return 1;
12
+ case 'ADDITIONAL_QUESTION': return 2;
13
+ case 'FOUND_ERROR': return 3;
14
+ case 'RECHECK_REQUESTED': return 4;
15
+ default:
16
+ throw new CommunityApiError(400, 'invalid-reply-type', '사용자가 생성할 수 없는 답글 유형입니다.');
17
+ }
18
+ }
19
+ export function replyTypeKey(typeCode) {
20
+ switch (typeCode) {
21
+ case 1: return 'SUGGESTED';
22
+ case 2: return 'ADDITIONAL_QUESTION';
23
+ case 3: return 'FOUND_ERROR';
24
+ case 4: return 'RECHECK_REQUESTED';
25
+ case 5: return 'RESOLVED';
26
+ case 6: return 'ASSIGNEE_ASSIGNED';
27
+ case 7: return 'ASSIGNEE_TRANSFERRED';
28
+ case 8: return 'REOPENED';
29
+ case 9: return 'ASSIGNEE_UNASSIGNED';
30
+ default: return 'UNKNOWN';
31
+ }
32
+ }
33
+ //# sourceMappingURL=reply.input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply.input.js","sourceRoot":"","sources":["../../src/replies/reply.input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,MAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,iBAAiB,CACzB,GAAG,EACH,uBAAuB,EACvB,gCAAgC,CACjC,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAClC,KAAK,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3B,KAAK,qBAAqB,CAAC,CAAC,OAAO,CAAC,CAAC;QACrC,KAAK,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC;QAC7B,KAAK,mBAAmB,CAAC,CAAC,OAAO,CAAC,CAAC;QACnC;YACE,MAAM,IAAI,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,EAAE,yBAAyB,CAAC,CAAC;IACtF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,CAAC,CAAC,CAAC,OAAO,WAAW,CAAC;QAC3B,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC;QACrC,KAAK,CAAC,CAAC,CAAC,OAAO,aAAa,CAAC;QAC7B,KAAK,CAAC,CAAC,CAAC,OAAO,mBAAmB,CAAC;QACnC,KAAK,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC;QAC1B,KAAK,CAAC,CAAC,CAAC,OAAO,mBAAmB,CAAC;QACnC,KAAK,CAAC,CAAC,CAAC,OAAO,sBAAsB,CAAC;QACtC,KAAK,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC;QAC1B,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC;QACrC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { SqliteDatabase } from '../db/connection.js';
2
+ import type { PageElementRepository } from '../page-elements/page-element.repository.js';
3
+ import type { NormalizedPageElement } from '../page-elements/page-element.types.js';
4
+ import type { ProjectAccessRepository } from '../projects/project-access.repository.js';
5
+ import type { ReplyResponse } from './reply.types.js';
6
+ export interface NewReplyRecord {
7
+ actorId: string;
8
+ content: string;
9
+ feedbackId: string;
10
+ id: string;
11
+ now: string;
12
+ pageElements: NormalizedPageElement[];
13
+ parentReplyId: string | null;
14
+ projectId: string;
15
+ reportCaseId: string;
16
+ typeCode: number;
17
+ }
18
+ export declare class ReplyRepository {
19
+ private readonly accessRepository;
20
+ private readonly pageElementRepository;
21
+ private readonly countReplies;
22
+ private readonly database;
23
+ private readonly findHierarchy;
24
+ private readonly findParent;
25
+ private readonly findReply;
26
+ private readonly insertReply;
27
+ private readonly listRepliesStatement;
28
+ constructor(database: SqliteDatabase, accessRepository: ProjectAccessRepository, pageElementRepository: PageElementRepository);
29
+ create(record: NewReplyRecord): ReplyResponse;
30
+ get(projectId: string, feedbackId: string, reportCaseId: string, replyId: string): ReplyResponse;
31
+ list(projectId: string, feedbackId: string, reportCaseId: string, page: number, pageSize: number): {
32
+ items: ReplyResponse[];
33
+ totalCount: number;
34
+ };
35
+ private mapRows;
36
+ systemReply(caseId: string, type: number, content: string, actorId: string, assigneeId: string | null, previousAssigneeId: string | null, now: string): void;
37
+ editReply(id: string, content: string, now: string): void;
38
+ deleteReply(id: string, now: string): void;
39
+ }
40
+ //# sourceMappingURL=reply.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply.repository.d.ts","sourceRoot":"","sources":["../../src/replies/reply.repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AACpF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAExF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkBD,qBAAa,eAAe;IAWxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAXxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA0B;gBAG7D,QAAQ,EAAE,cAAc,EACP,gBAAgB,EAAE,uBAAuB,EACzC,qBAAqB,EAAE,qBAAqB;IAqExD,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa;IAkD7C,GAAG,CACR,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,aAAa;IAQT,IAAI,CACT,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAajD,OAAO,CAAC,OAAO;IAgCR,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,kBAAkB,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAS5J,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAOzD,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;CAMlD"}
@@ -0,0 +1,173 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { CommunityApiError } from '../community/errors.js';
3
+ import { sqlGuidOrder } from '../db/guid-order.js';
4
+ import { replyTypeKey } from './reply.input.js';
5
+ export class ReplyRepository {
6
+ accessRepository;
7
+ pageElementRepository;
8
+ countReplies;
9
+ database;
10
+ findHierarchy;
11
+ findParent;
12
+ findReply;
13
+ insertReply;
14
+ listRepliesStatement;
15
+ constructor(database, accessRepository, pageElementRepository) {
16
+ this.accessRepository = accessRepository;
17
+ this.pageElementRepository = pageElementRepository;
18
+ this.database = database;
19
+ this.findHierarchy = database.prepare(`
20
+ SELECT report_case.status_code AS statusCode
21
+ FROM report_cases AS report_case
22
+ INNER JOIN feedbacks AS feedback ON feedback.feedback_id = report_case.feedback_id
23
+ WHERE feedback.project_id = ?
24
+ AND feedback.feedback_id = ?
25
+ AND report_case.report_case_id = ?
26
+ `);
27
+ this.findParent = database.prepare(`
28
+ SELECT status_code AS statusCode
29
+ FROM replies
30
+ WHERE report_case_id = ? AND reply_id = ?
31
+ `);
32
+ this.insertReply = database.prepare(`
33
+ INSERT INTO replies (
34
+ reply_id, type_code, status_code, report_case_id, parent_reply_id, content,
35
+ author_id, assignee_id, previous_assignee_id, lock_version, deleted_at,
36
+ created_at, updated_at
37
+ ) VALUES (?, ?, 1, ?, ?, ?, ?, NULL, NULL, 0, NULL, ?, ?)
38
+ `);
39
+ this.findReply = database.prepare(`
40
+ SELECT reply.reply_id AS id,
41
+ reply.type_code AS typeCode,
42
+ reply.status_code AS statusCode,
43
+ reply.report_case_id AS reportCaseId,
44
+ reply.parent_reply_id AS parentReplyId,
45
+ reply.content,
46
+ reply.author_id AS authorId,
47
+ reply.assignee_id AS assigneeId,
48
+ reply.previous_assignee_id AS previousAssigneeId,
49
+ reply.lock_version AS version,
50
+ reply.deleted_at AS deletedAt,
51
+ reply.created_at AS createdAt,
52
+ reply.updated_at AS updatedAt
53
+ FROM replies AS reply
54
+ INNER JOIN report_cases AS report_case ON report_case.report_case_id = reply.report_case_id
55
+ INNER JOIN feedbacks AS feedback ON feedback.feedback_id = report_case.feedback_id
56
+ WHERE feedback.project_id = ?
57
+ AND feedback.feedback_id = ?
58
+ AND reply.report_case_id = ?
59
+ AND reply.reply_id = ?
60
+ `);
61
+ this.countReplies = database.prepare(`
62
+ SELECT COUNT(*) AS totalCount FROM replies WHERE report_case_id = ?
63
+ `);
64
+ this.listRepliesStatement = database.prepare(`
65
+ SELECT reply_id AS id,
66
+ type_code AS typeCode,
67
+ status_code AS statusCode,
68
+ report_case_id AS reportCaseId,
69
+ parent_reply_id AS parentReplyId,
70
+ content,
71
+ author_id AS authorId,
72
+ assignee_id AS assigneeId,
73
+ previous_assignee_id AS previousAssigneeId,
74
+ lock_version AS version,
75
+ deleted_at AS deletedAt,
76
+ created_at AS createdAt,
77
+ updated_at AS updatedAt
78
+ FROM replies
79
+ WHERE report_case_id = ?
80
+ ORDER BY created_at, ${sqlGuidOrder('reply_id')}
81
+ LIMIT ? OFFSET ?
82
+ `);
83
+ }
84
+ create(record) {
85
+ this.database.transaction(() => {
86
+ const reportCase = this.findHierarchy.get(record.projectId, record.feedbackId, record.reportCaseId);
87
+ if (reportCase === undefined) {
88
+ throw new CommunityApiError(404, 'report-case-not-found', 'Report Case를 찾을 수 없습니다.');
89
+ }
90
+ if (reportCase.statusCode !== 1) {
91
+ throw new CommunityApiError(409, 'report-case-resolved', '해결된 Report Case에는 답변을 작성할 수 없습니다. Report Case를 다시 열어 주세요.');
92
+ }
93
+ if (record.parentReplyId !== null) {
94
+ const parent = this.findParent.get(record.reportCaseId, record.parentReplyId);
95
+ if (parent === undefined) {
96
+ throw new CommunityApiError(404, 'reply-not-found', '답글을 찾을 수 없습니다.');
97
+ }
98
+ if (parent.statusCode !== 1) {
99
+ throw new CommunityApiError(409, 'reply-parent-deleted', '삭제된 답글에는 답글을 추가할 수 없습니다.');
100
+ }
101
+ }
102
+ this.insertReply.run(record.id, record.typeCode, record.reportCaseId, record.parentReplyId, record.content, record.actorId, record.now, record.now);
103
+ this.pageElementRepository.linkReply(record.id, record.actorId, record.pageElements, record.now);
104
+ }).immediate();
105
+ return this.get(record.projectId, record.feedbackId, record.reportCaseId, record.id);
106
+ }
107
+ get(projectId, feedbackId, reportCaseId, replyId) {
108
+ const row = this.findReply.get(projectId, feedbackId, reportCaseId, replyId);
109
+ if (row === undefined) {
110
+ throw new CommunityApiError(404, 'reply-not-found', '답글을 찾을 수 없습니다.');
111
+ }
112
+ return this.mapRows([row])[0];
113
+ }
114
+ list(projectId, feedbackId, reportCaseId, page, pageSize) {
115
+ if (this.findHierarchy.get(projectId, feedbackId, reportCaseId) === undefined) {
116
+ throw new CommunityApiError(404, 'report-case-not-found', 'Report Case를 찾을 수 없습니다.');
117
+ }
118
+ const count = this.countReplies.get(reportCaseId);
119
+ const rows = this.listRepliesStatement.all(reportCaseId, pageSize, (page - 1) * pageSize);
120
+ return { items: this.mapRows(rows), totalCount: count.totalCount };
121
+ }
122
+ mapRows(rows) {
123
+ const activeIds = rows.filter((item) => item.statusCode === 1).map((item) => item.id);
124
+ const pageElements = this.pageElementRepository.loadForReplies(activeIds);
125
+ const users = this.accessRepository.loadUsers(rows.flatMap((item) => [item.authorId, item.assigneeId, item.previousAssigneeId]));
126
+ return rows.map((row) => {
127
+ const author = users.get(row.authorId);
128
+ if (author === undefined)
129
+ throw new Error('reply-author-missing');
130
+ const active = row.statusCode === 1;
131
+ return {
132
+ id: row.id,
133
+ reportCaseId: row.reportCaseId,
134
+ parentReplyId: row.parentReplyId,
135
+ type: replyTypeKey(row.typeCode),
136
+ status: active ? 'ACTIVE' : 'DELETED',
137
+ content: active ? row.content : '',
138
+ author,
139
+ assignee: row.assigneeId === null ? null : (users.get(row.assigneeId) ?? null),
140
+ previousAssignee: row.previousAssigneeId === null
141
+ ? null
142
+ : (users.get(row.previousAssigneeId) ?? null),
143
+ version: row.version,
144
+ deletedAt: row.deletedAt,
145
+ createdAt: row.createdAt,
146
+ updatedAt: row.updatedAt,
147
+ pageElements: active ? (pageElements.get(row.id) ?? []) : [],
148
+ attachments: [],
149
+ };
150
+ });
151
+ }
152
+ systemReply(caseId, type, content, actorId, assigneeId, previousAssigneeId, now) {
153
+ this.database.prepare(`
154
+ INSERT INTO replies (reply_id, type_code, status_code, report_case_id, parent_reply_id,
155
+ content, author_id, assignee_id, previous_assignee_id, lock_version, deleted_at,
156
+ created_at, updated_at)
157
+ VALUES (?, ?, 1, ?, NULL, ?, ?, ?, ?, 0, NULL, ?, ?)
158
+ `).run(randomUUID(), type, caseId, content, actorId, assigneeId, previousAssigneeId, now, now);
159
+ }
160
+ editReply(id, content, now) {
161
+ this.database.prepare(`
162
+ UPDATE replies SET content = ?, lock_version = lock_version + 1, updated_at = ?
163
+ WHERE reply_id = ?
164
+ `).run(content, now, id);
165
+ }
166
+ deleteReply(id, now) {
167
+ this.database.prepare(`
168
+ UPDATE replies SET status_code = 2, deleted_at = ?, updated_at = ?,
169
+ lock_version = lock_version + 1 WHERE reply_id = ?
170
+ `).run(now, now, id);
171
+ }
172
+ }
173
+ //# sourceMappingURL=reply.repository.js.map