@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.
- package/LICENSE +93 -0
- package/README.md +537 -0
- package/dist/app.d.ts +10 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +70 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/identity.repository.d.ts +62 -0
- package/dist/auth/identity.repository.d.ts.map +1 -0
- package/dist/auth/identity.repository.js +202 -0
- package/dist/auth/identity.repository.js.map +1 -0
- package/dist/auth/identity.routes.d.ts +5 -0
- package/dist/auth/identity.routes.d.ts.map +1 -0
- package/dist/auth/identity.routes.js +56 -0
- package/dist/auth/identity.routes.js.map +1 -0
- package/dist/auth/identity.schemas.d.ts +2711 -0
- package/dist/auth/identity.schemas.d.ts.map +1 -0
- package/dist/auth/identity.schemas.js +117 -0
- package/dist/auth/identity.schemas.js.map +1 -0
- package/dist/auth/identity.service.d.ts +37 -0
- package/dist/auth/identity.service.d.ts.map +1 -0
- package/dist/auth/identity.service.js +131 -0
- package/dist/auth/identity.service.js.map +1 -0
- package/dist/auth/password.service.d.ts +15 -0
- package/dist/auth/password.service.d.ts.map +1 -0
- package/dist/auth/password.service.js +116 -0
- package/dist/auth/password.service.js.map +1 -0
- package/dist/auth/token.service.d.ts +38 -0
- package/dist/auth/token.service.d.ts.map +1 -0
- package/dist/auth/token.service.js +54 -0
- package/dist/auth/token.service.js.map +1 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +132 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +24 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +20 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/start.d.ts +4 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +13 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +4 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +48 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/io.d.ts +6 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +9 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/community/contracts.d.ts +29 -0
- package/dist/community/contracts.d.ts.map +1 -0
- package/dist/community/contracts.js +41 -0
- package/dist/community/contracts.js.map +1 -0
- package/dist/community/error-handler.d.ts +3 -0
- package/dist/community/error-handler.d.ts.map +1 -0
- package/dist/community/error-handler.js +66 -0
- package/dist/community/error-handler.js.map +1 -0
- package/dist/community/errors.d.ts +10 -0
- package/dist/community/errors.d.ts.map +1 -0
- package/dist/community/errors.js +39 -0
- package/dist/community/errors.js.map +1 -0
- package/dist/community/etag.d.ts +5 -0
- package/dist/community/etag.d.ts.map +1 -0
- package/dist/community/etag.js +31 -0
- package/dist/community/etag.js.map +1 -0
- package/dist/community/input.d.ts +10 -0
- package/dist/community/input.d.ts.map +1 -0
- package/dist/community/input.js +48 -0
- package/dist/community/input.js.map +1 -0
- package/dist/community/mutation-route.d.ts +7 -0
- package/dist/community/mutation-route.d.ts.map +1 -0
- package/dist/community/mutation-route.js +47 -0
- package/dist/community/mutation-route.js.map +1 -0
- package/dist/community/schemas.d.ts +807 -0
- package/dist/community/schemas.d.ts.map +1 -0
- package/dist/community/schemas.js +100 -0
- package/dist/community/schemas.js.map +1 -0
- package/dist/community/system.schemas.d.ts +40 -0
- package/dist/community/system.schemas.d.ts.map +1 -0
- package/dist/community/system.schemas.js +30 -0
- package/dist/community/system.schemas.js.map +1 -0
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +208 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/data-path.d.ts +2 -0
- package/dist/config/data-path.d.ts.map +1 -0
- package/dist/config/data-path.js +16 -0
- package/dist/config/data-path.js.map +1 -0
- package/dist/config/jwt-secret.d.ts +3 -0
- package/dist/config/jwt-secret.d.ts.map +1 -0
- package/dist/config/jwt-secret.js +67 -0
- package/dist/config/jwt-secret.js.map +1 -0
- package/dist/db/backup.d.ts +10 -0
- package/dist/db/backup.d.ts.map +1 -0
- package/dist/db/backup.js +51 -0
- package/dist/db/backup.js.map +1 -0
- package/dist/db/connection.d.ts +15 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +82 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/guid-order.d.ts +2 -0
- package/dist/db/guid-order.d.ts.map +1 -0
- package/dist/db/guid-order.js +9 -0
- package/dist/db/guid-order.js.map +1 -0
- package/dist/db/migrate.d.ts +37 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +145 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migrations/001_schema_migrations.sql +6 -0
- package/dist/db/migrations/002_identity.sql +95 -0
- package/dist/db/migrations/003_projects.sql +62 -0
- package/dist/db/migrations/004_feedback_core.sql +236 -0
- package/dist/db/migrations/005_project_member_management.sql +55 -0
- package/dist/db/migrations/006_align_credentials.sql +33 -0
- package/dist/db/migrations/007_align_storage_values.sql +78 -0
- package/dist/db/storage-migration.d.ts +9 -0
- package/dist/db/storage-migration.d.ts.map +1 -0
- package/dist/db/storage-migration.js +79 -0
- package/dist/db/storage-migration.js.map +1 -0
- package/dist/db/transaction.d.ts +9 -0
- package/dist/db/transaction.d.ts.map +1 -0
- package/dist/db/transaction.js +14 -0
- package/dist/db/transaction.js.map +1 -0
- package/dist/errors/error-handler.d.ts +3 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +50 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts +59 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.js +89 -0
- package/dist/feedbacks/feedback-workflow.service.js.map +1 -0
- package/dist/feedbacks/feedback.input.d.ts +4 -0
- package/dist/feedbacks/feedback.input.d.ts.map +1 -0
- package/dist/feedbacks/feedback.input.js +25 -0
- package/dist/feedbacks/feedback.input.js.map +1 -0
- package/dist/feedbacks/feedback.repository.d.ts +48 -0
- package/dist/feedbacks/feedback.repository.d.ts.map +1 -0
- package/dist/feedbacks/feedback.repository.js +238 -0
- package/dist/feedbacks/feedback.repository.js.map +1 -0
- package/dist/feedbacks/feedback.routes.d.ts +4 -0
- package/dist/feedbacks/feedback.routes.d.ts.map +1 -0
- package/dist/feedbacks/feedback.routes.js +78 -0
- package/dist/feedbacks/feedback.routes.js.map +1 -0
- package/dist/feedbacks/feedback.schemas.d.ts +642 -0
- package/dist/feedbacks/feedback.schemas.d.ts.map +1 -0
- package/dist/feedbacks/feedback.schemas.js +131 -0
- package/dist/feedbacks/feedback.schemas.js.map +1 -0
- package/dist/feedbacks/feedback.service.d.ts +23 -0
- package/dist/feedbacks/feedback.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback.service.js +74 -0
- package/dist/feedbacks/feedback.service.js.map +1 -0
- package/dist/feedbacks/feedback.types.d.ts +64 -0
- package/dist/feedbacks/feedback.types.d.ts.map +1 -0
- package/dist/feedbacks/feedback.types.js +2 -0
- package/dist/feedbacks/feedback.types.js.map +1 -0
- package/dist/page-elements/page-element.input.d.ts +7 -0
- package/dist/page-elements/page-element.input.d.ts.map +1 -0
- package/dist/page-elements/page-element.input.js +59 -0
- package/dist/page-elements/page-element.input.js.map +1 -0
- package/dist/page-elements/page-element.repository.d.ts +21 -0
- package/dist/page-elements/page-element.repository.d.ts.map +1 -0
- package/dist/page-elements/page-element.repository.js +123 -0
- package/dist/page-elements/page-element.repository.js.map +1 -0
- package/dist/page-elements/page-element.schemas.d.ts +97 -0
- package/dist/page-elements/page-element.schemas.d.ts.map +1 -0
- package/dist/page-elements/page-element.schemas.js +40 -0
- package/dist/page-elements/page-element.schemas.js.map +1 -0
- package/dist/page-elements/page-element.types.d.ts +24 -0
- package/dist/page-elements/page-element.types.d.ts.map +1 -0
- package/dist/page-elements/page-element.types.js +2 -0
- package/dist/page-elements/page-element.types.js.map +1 -0
- package/dist/plugins/auth.plugin.d.ts +3 -0
- package/dist/plugins/auth.plugin.d.ts.map +1 -0
- package/dist/plugins/auth.plugin.js +28 -0
- package/dist/plugins/auth.plugin.js.map +1 -0
- package/dist/plugins/community-api.plugin.d.ts +5 -0
- package/dist/plugins/community-api.plugin.d.ts.map +1 -0
- package/dist/plugins/community-api.plugin.js +25 -0
- package/dist/plugins/community-api.plugin.js.map +1 -0
- package/dist/plugins/cors.plugin.d.ts +3 -0
- package/dist/plugins/cors.plugin.d.ts.map +1 -0
- package/dist/plugins/cors.plugin.js +19 -0
- package/dist/plugins/cors.plugin.js.map +1 -0
- package/dist/plugins/swagger.plugin.d.ts +3 -0
- package/dist/plugins/swagger.plugin.d.ts.map +1 -0
- package/dist/plugins/swagger.plugin.js +59 -0
- package/dist/plugins/swagger.plugin.js.map +1 -0
- package/dist/plugins/user-auth.plugin.d.ts +33 -0
- package/dist/plugins/user-auth.plugin.d.ts.map +1 -0
- package/dist/plugins/user-auth.plugin.js +62 -0
- package/dist/plugins/user-auth.plugin.js.map +1 -0
- package/dist/projects/members/project-member.repository.d.ts +49 -0
- package/dist/projects/members/project-member.repository.d.ts.map +1 -0
- package/dist/projects/members/project-member.repository.js +215 -0
- package/dist/projects/members/project-member.repository.js.map +1 -0
- package/dist/projects/members/project-member.routes.d.ts +4 -0
- package/dist/projects/members/project-member.routes.d.ts.map +1 -0
- package/dist/projects/members/project-member.routes.js +82 -0
- package/dist/projects/members/project-member.routes.js.map +1 -0
- package/dist/projects/members/project-member.schemas.d.ts +2735 -0
- package/dist/projects/members/project-member.schemas.d.ts.map +1 -0
- package/dist/projects/members/project-member.schemas.js +138 -0
- package/dist/projects/members/project-member.schemas.js.map +1 -0
- package/dist/projects/members/project-member.service.d.ts +29 -0
- package/dist/projects/members/project-member.service.d.ts.map +1 -0
- package/dist/projects/members/project-member.service.js +92 -0
- package/dist/projects/members/project-member.service.js.map +1 -0
- package/dist/projects/project-access.policy.d.ts +11 -0
- package/dist/projects/project-access.policy.d.ts.map +1 -0
- package/dist/projects/project-access.policy.js +30 -0
- package/dist/projects/project-access.policy.js.map +1 -0
- package/dist/projects/project-access.repository.d.ts +12 -0
- package/dist/projects/project-access.repository.d.ts.map +1 -0
- package/dist/projects/project-access.repository.js +45 -0
- package/dist/projects/project-access.repository.js.map +1 -0
- package/dist/projects/project-access.types.d.ts +9 -0
- package/dist/projects/project-access.types.d.ts.map +1 -0
- package/dist/projects/project-access.types.js +2 -0
- package/dist/projects/project-access.types.js.map +1 -0
- package/dist/projects/project-mutation.service.d.ts +15 -0
- package/dist/projects/project-mutation.service.d.ts.map +1 -0
- package/dist/projects/project-mutation.service.js +39 -0
- package/dist/projects/project-mutation.service.js.map +1 -0
- package/dist/projects/project.repository.d.ts +49 -0
- package/dist/projects/project.repository.d.ts.map +1 -0
- package/dist/projects/project.repository.js +155 -0
- package/dist/projects/project.repository.js.map +1 -0
- package/dist/projects/project.routes.d.ts +4 -0
- package/dist/projects/project.routes.d.ts.map +1 -0
- package/dist/projects/project.routes.js +45 -0
- package/dist/projects/project.routes.js.map +1 -0
- package/dist/projects/project.schemas.d.ts +2044 -0
- package/dist/projects/project.schemas.d.ts.map +1 -0
- package/dist/projects/project.schemas.js +90 -0
- package/dist/projects/project.schemas.js.map +1 -0
- package/dist/projects/project.service.d.ts +40 -0
- package/dist/projects/project.service.d.ts.map +1 -0
- package/dist/projects/project.service.js +128 -0
- package/dist/projects/project.service.js.map +1 -0
- package/dist/replies/reply-mutation.service.d.ts +19 -0
- package/dist/replies/reply-mutation.service.d.ts.map +1 -0
- package/dist/replies/reply-mutation.service.js +51 -0
- package/dist/replies/reply-mutation.service.js.map +1 -0
- package/dist/replies/reply.input.d.ts +4 -0
- package/dist/replies/reply.input.d.ts.map +1 -0
- package/dist/replies/reply.input.js +33 -0
- package/dist/replies/reply.input.js.map +1 -0
- package/dist/replies/reply.repository.d.ts +40 -0
- package/dist/replies/reply.repository.d.ts.map +1 -0
- package/dist/replies/reply.repository.js +173 -0
- package/dist/replies/reply.repository.js.map +1 -0
- package/dist/replies/reply.routes.d.ts +4 -0
- package/dist/replies/reply.routes.d.ts.map +1 -0
- package/dist/replies/reply.routes.js +64 -0
- package/dist/replies/reply.routes.js.map +1 -0
- package/dist/replies/reply.schemas.d.ts +251 -0
- package/dist/replies/reply.schemas.d.ts.map +1 -0
- package/dist/replies/reply.schemas.js +51 -0
- package/dist/replies/reply.schemas.js.map +1 -0
- package/dist/replies/reply.service.d.ts +19 -0
- package/dist/replies/reply.service.d.ts.map +1 -0
- package/dist/replies/reply.service.js +50 -0
- package/dist/replies/reply.service.js.map +1 -0
- package/dist/replies/reply.types.d.ts +31 -0
- package/dist/replies/reply.types.d.ts.map +1 -0
- package/dist/replies/reply.types.js +2 -0
- package/dist/replies/reply.types.js.map +1 -0
- package/dist/report-cases/report-case-workflow.service.d.ts +39 -0
- package/dist/report-cases/report-case-workflow.service.d.ts.map +1 -0
- package/dist/report-cases/report-case-workflow.service.js +103 -0
- package/dist/report-cases/report-case-workflow.service.js.map +1 -0
- package/dist/report-cases/report-case.input.d.ts +4 -0
- package/dist/report-cases/report-case.input.d.ts.map +1 -0
- package/dist/report-cases/report-case.input.js +29 -0
- package/dist/report-cases/report-case.input.js.map +1 -0
- package/dist/report-cases/report-case.repository.d.ts +45 -0
- package/dist/report-cases/report-case.repository.d.ts.map +1 -0
- package/dist/report-cases/report-case.repository.js +185 -0
- package/dist/report-cases/report-case.repository.js.map +1 -0
- package/dist/report-cases/report-case.routes.d.ts +4 -0
- package/dist/report-cases/report-case.routes.d.ts.map +1 -0
- package/dist/report-cases/report-case.routes.js +94 -0
- package/dist/report-cases/report-case.routes.js.map +1 -0
- package/dist/report-cases/report-case.schemas.d.ts +294 -0
- package/dist/report-cases/report-case.schemas.d.ts.map +1 -0
- package/dist/report-cases/report-case.schemas.js +77 -0
- package/dist/report-cases/report-case.schemas.js.map +1 -0
- package/dist/report-cases/report-case.service.d.ts +21 -0
- package/dist/report-cases/report-case.service.d.ts.map +1 -0
- package/dist/report-cases/report-case.service.js +60 -0
- package/dist/report-cases/report-case.service.js.map +1 -0
- package/dist/report-cases/report-case.types.d.ts +39 -0
- package/dist/report-cases/report-case.types.d.ts.map +1 -0
- package/dist/report-cases/report-case.types.js +2 -0
- package/dist/report-cases/report-case.types.js.map +1 -0
- package/dist/routes/health.route.d.ts +4 -0
- package/dist/routes/health.route.d.ts.map +1 -0
- package/dist/routes/health.route.js +39 -0
- package/dist/routes/health.route.js.map +1 -0
- package/dist/routes/version.route.d.ts +3 -0
- package/dist/routes/version.route.d.ts.map +1 -0
- package/dist/routes/version.route.js +22 -0
- package/dist/routes/version.route.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +11 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/values.d.ts +3 -0
- package/dist/storage/values.d.ts.map +1 -0
- package/dist/storage/values.js +30 -0
- package/dist/storage/values.js.map +1 -0
- package/dist/users/current-user.routes.d.ts +3 -0
- package/dist/users/current-user.routes.d.ts.map +1 -0
- package/dist/users/current-user.routes.js +9 -0
- package/dist/users/current-user.routes.js.map +1 -0
- package/dist/users/current-user.schemas.d.ts +641 -0
- package/dist/users/current-user.schemas.d.ts.map +1 -0
- package/dist/users/current-user.schemas.js +21 -0
- package/dist/users/current-user.schemas.js.map +1 -0
- package/dist/users/user-search.repository.d.ts +19 -0
- package/dist/users/user-search.repository.d.ts.map +1 -0
- package/dist/users/user-search.repository.js +55 -0
- package/dist/users/user-search.repository.js.map +1 -0
- package/dist/users/user-search.routes.d.ts +4 -0
- package/dist/users/user-search.routes.d.ts.map +1 -0
- package/dist/users/user-search.routes.js +19 -0
- package/dist/users/user-search.routes.js.map +1 -0
- package/dist/users/user-search.schemas.d.ts +693 -0
- package/dist/users/user-search.schemas.d.ts.map +1 -0
- package/dist/users/user-search.schemas.js +41 -0
- package/dist/users/user-search.schemas.js.map +1 -0
- package/dist/users/user-search.service.d.ts +20 -0
- package/dist/users/user-search.service.d.ts.map +1 -0
- package/dist/users/user-search.service.js +41 -0
- package/dist/users/user-search.service.js.map +1 -0
- package/dist/users/user.schemas.d.ts +47 -0
- package/dist/users/user.schemas.d.ts.map +1 -0
- package/dist/users/user.schemas.js +13 -0
- package/dist/users/user.schemas.js.map +1 -0
- package/dist/users/user.types.d.ts +6 -0
- package/dist/users/user.types.d.ts.map +1 -0
- package/dist/users/user.types.js +2 -0
- package/dist/users/user.types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/docs/guides/community-api-quickstart.md +171 -0
- package/docs/guides/feature-structure.md +138 -0
- package/docs/guides/independent-cli.md +73 -0
- package/docs/guides/non-attachment-api-contract.md +138 -0
- package/docs/plans/selfdev-schema-alignment.md +61 -0
- package/package.json +76 -0
- 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":"AAAA,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,MAAM,EACN,YAAY,EACZ,UAAU,GACX,MAAM,yBAAyB,CAAC;AAEjC,MAAM,eAAe,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAW,CAAC;AAEzE,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC;IAC3F,UAAU,EAAE;QACV,EAAE,EAAE,UAAU;QACd,SAAS,EAAE,UAAU;QACrB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE;QACxD,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACxC,SAAS,EAAE,eAAe;QAC1B,SAAS,EAAE,eAAe;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC;IAC7F,UAAU,EAAE;QACV,EAAE,EAAE,UAAU;QACd,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE;QACxD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE;QAC1D,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACxC,SAAS,EAAE,eAAe;QAC1B,SAAS,EAAE,eAAe;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,QAAQ,EAAE,CAAC,aAAa,CAAC;QACzB,UAAU,EAAE;YACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;SAC9D;KACF;IACD,QAAQ,EAAE;QACR,GAAG,EAAE,uBAAuB,CAAC,2BAA2B,CAAC;QACzD,GAAG,uBAAuB;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,OAAO,EAAE,eAAe;IACxB,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3B,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;YACrC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE;SAC3C;KACF;IACD,QAAQ,EAAE;QACR,GAAG,EAAE,uBAAuB,CAAC;YAC3B,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,2BAA2B;SACnC,CAAC;QACF,GAAG,uBAAuB;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3B,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,QAAQ,EAAE,CAAC,WAAW,CAAC;QACvB,UAAU,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;KACtC;IACD,QAAQ,EAAE;QACR,GAAG,EAAE,uBAAuB,CAAC,2BAA2B,CAAC;QACzD,GAAG,uBAAuB;KAC3B;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAE/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;IAC5C,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;CAC9D,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,uBAAuB,CAAC,2BAA2B,CAAC,CAAC"}
|
|
@@ -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 @@
|
|
|
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
|