@things-factory/board-ai 10.1.4 → 10.1.6
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/client/components/default-catalog-entries.ts +1 -1
- package/client/components/default-slash-templates.ts +1 -1
- package/client/index.ts +27 -6
- package/dist-client/client/components/default-catalog-entries.d.ts +1 -1
- package/dist-client/client/components/default-catalog-entries.js.map +1 -1
- package/dist-client/client/components/default-slash-templates.d.ts +1 -1
- package/dist-client/client/components/default-slash-templates.js.map +1 -1
- package/dist-client/client/index.d.ts +3 -11
- package/dist-client/client/index.js +25 -6
- package/dist-client/client/index.js.map +1 -1
- package/dist-client/server/service/assistant.d.ts +22 -22
- package/dist-client/server/service/assistant.js +32 -70
- package/dist-client/server/service/assistant.js.map +1 -1
- package/dist-client/server/service/grounding.d.ts +2 -12
- package/dist-client/server/service/grounding.js +15 -23
- package/dist-client/server/service/grounding.js.map +1 -1
- package/dist-client/server/service/types.d.ts +2 -4
- package/dist-client/server/service/types.js.map +1 -1
- package/dist-client/server/service/validation/board-model-schema.d.ts +270 -270
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/assistant.d.ts +22 -22
- package/dist-server/service/assistant.js +25 -76
- package/dist-server/service/assistant.js.map +1 -1
- package/dist-server/service/board-ai-resolver.js +41 -30
- package/dist-server/service/board-ai-resolver.js.map +1 -1
- package/dist-server/service/board-session-resolver.d.ts +12 -0
- package/dist-server/service/board-session-resolver.js +203 -0
- package/dist-server/service/board-session-resolver.js.map +1 -0
- package/dist-server/service/board-tool-rights.d.ts +7 -0
- package/dist-server/service/board-tool-rights.js +62 -0
- package/dist-server/service/board-tool-rights.js.map +1 -0
- package/dist-server/service/grounding.d.ts +2 -12
- package/dist-server/service/grounding.js +16 -24
- package/dist-server/service/grounding.js.map +1 -1
- package/dist-server/service/index.d.ts +4 -10
- package/dist-server/service/index.js +16 -23
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/patch-entry/board-patch-subscription.js +2 -2
- package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -1
- package/dist-server/service/patch-entry/patch-entry.d.ts +1 -1
- package/dist-server/service/patch-entry/patch-entry.js +3 -3
- package/dist-server/service/patch-entry/patch-entry.js.map +1 -1
- package/dist-server/service/types.d.ts +2 -4
- package/dist-server/service/types.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/server/service/apply-patch-drift.test.ts +3 -1
- package/server/service/assistant.ts +47 -73
- package/server/service/board-ai-resolver.ts +22 -12
- package/server/service/board-session-resolver.ts +183 -0
- package/server/service/board-tool-rights.test.ts +96 -0
- package/server/service/board-tool-rights.ts +73 -0
- package/server/service/dock-contract.test.ts +3 -0
- package/server/service/grounding.test.ts +3 -3
- package/server/service/grounding.ts +15 -34
- package/server/service/index.ts +16 -22
- package/server/service/patch-entry/board-patch-subscription.ts +1 -1
- package/server/service/patch-entry/patch-entry.ts +3 -2
- package/server/service/registry-tool-loop.test.ts +1 -0
- package/server/service/tool-exposure.test.ts +2 -0
- package/server/service/types.ts +3 -4
- package/client/components/board-ai-chat.test.ts +0 -149
- package/client/components/board-ai-chat.ts +0 -3184
- package/client/components/chat-echo-dedup.test.ts +0 -230
- package/client/components/chat-echo-dedup.ts +0 -155
- package/client/components/chat-input-builder.ts +0 -69
- package/client/components/markdown.test.ts +0 -518
- package/client/components/markdown.ts +0 -508
- package/client/components/mention-popup-helpers.ts +0 -433
- package/client/components/mention-popup.test.ts +0 -588
- package/client/components/mention-popup.ts +0 -238
- package/client/utils/board-edit-patch.ts +0 -374
- package/dist-client/client/components/board-ai-chat.d.ts +0 -384
- package/dist-client/client/components/board-ai-chat.js +0 -3008
- package/dist-client/client/components/board-ai-chat.js.map +0 -1
- package/dist-client/client/components/board-ai-chat.test.d.ts +0 -1
- package/dist-client/client/components/board-ai-chat.test.js +0 -138
- package/dist-client/client/components/board-ai-chat.test.js.map +0 -1
- package/dist-client/client/components/chat-echo-dedup.d.ts +0 -54
- package/dist-client/client/components/chat-echo-dedup.js +0 -115
- package/dist-client/client/components/chat-echo-dedup.js.map +0 -1
- package/dist-client/client/components/chat-echo-dedup.test.d.ts +0 -1
- package/dist-client/client/components/chat-echo-dedup.test.js +0 -203
- package/dist-client/client/components/chat-echo-dedup.test.js.map +0 -1
- package/dist-client/client/components/chat-input-builder.d.ts +0 -55
- package/dist-client/client/components/chat-input-builder.js +0 -32
- package/dist-client/client/components/chat-input-builder.js.map +0 -1
- package/dist-client/client/components/markdown.d.ts +0 -60
- package/dist-client/client/components/markdown.js +0 -422
- package/dist-client/client/components/markdown.js.map +0 -1
- package/dist-client/client/components/markdown.test.d.ts +0 -1
- package/dist-client/client/components/markdown.test.js +0 -418
- package/dist-client/client/components/markdown.test.js.map +0 -1
- package/dist-client/client/components/mention-popup-helpers.d.ts +0 -165
- package/dist-client/client/components/mention-popup-helpers.js +0 -330
- package/dist-client/client/components/mention-popup-helpers.js.map +0 -1
- package/dist-client/client/components/mention-popup.d.ts +0 -35
- package/dist-client/client/components/mention-popup.js +0 -223
- package/dist-client/client/components/mention-popup.js.map +0 -1
- package/dist-client/client/components/mention-popup.test.d.ts +0 -1
- package/dist-client/client/components/mention-popup.test.js +0 -474
- package/dist-client/client/components/mention-popup.test.js.map +0 -1
- package/dist-client/client/utils/board-edit-patch.d.ts +0 -157
- package/dist-client/client/utils/board-edit-patch.js +0 -284
- package/dist-client/client/utils/board-edit-patch.js.map +0 -1
- package/dist-server/service/chat-message/chat-message-broadcast.d.ts +0 -13
- package/dist-server/service/chat-message/chat-message-broadcast.js +0 -13
- package/dist-server/service/chat-message/chat-message-broadcast.js.map +0 -1
- package/dist-server/service/chat-message/chat-message-publish.d.ts +0 -6
- package/dist-server/service/chat-message/chat-message-publish.js +0 -27
- package/dist-server/service/chat-message/chat-message-publish.js.map +0 -1
- package/dist-server/service/chat-message/chat-message-subscription.d.ts +0 -8
- package/dist-server/service/chat-message/chat-message-subscription.js +0 -53
- package/dist-server/service/chat-message/chat-message-subscription.js.map +0 -1
- package/dist-server/service/chat-message/chat-message.d.ts +0 -68
- package/dist-server/service/chat-message/chat-message.js +0 -172
- package/dist-server/service/chat-message/chat-message.js.map +0 -1
- package/dist-server/service/chat-message/fold-history.d.ts +0 -43
- package/dist-server/service/chat-message/fold-history.js +0 -33
- package/dist-server/service/chat-message/fold-history.js.map +0 -1
- package/dist-server/service/chat-message/history-summary.d.ts +0 -43
- package/dist-server/service/chat-message/history-summary.js +0 -77
- package/dist-server/service/chat-message/history-summary.js.map +0 -1
- package/dist-server/service/chat-message/index.d.ts +0 -5
- package/dist-server/service/chat-message/index.js +0 -12
- package/dist-server/service/chat-message/index.js.map +0 -1
- package/dist-server/service/chat-message/llm-history.d.ts +0 -46
- package/dist-server/service/chat-message/llm-history.js +0 -87
- package/dist-server/service/chat-message/llm-history.js.map +0 -1
- package/dist-server/service/chat-session/chat-session.d.ts +0 -62
- package/dist-server/service/chat-session/chat-session.js +0 -164
- package/dist-server/service/chat-session/chat-session.js.map +0 -1
- package/dist-server/service/chat-session/index.d.ts +0 -3
- package/dist-server/service/chat-session/index.js +0 -7
- package/dist-server/service/chat-session/index.js.map +0 -1
- package/dist-server/service/chat-session/session-activity-broadcast.d.ts +0 -30
- package/dist-server/service/chat-session/session-activity-broadcast.js +0 -34
- package/dist-server/service/chat-session/session-activity-broadcast.js.map +0 -1
- package/dist-server/service/chat-session/session-activity-publish.d.ts +0 -12
- package/dist-server/service/chat-session/session-activity-publish.js +0 -37
- package/dist-server/service/chat-session/session-activity-publish.js.map +0 -1
- package/dist-server/service/chat-session/session-activity-subscription.d.ts +0 -14
- package/dist-server/service/chat-session/session-activity-subscription.js +0 -87
- package/dist-server/service/chat-session/session-activity-subscription.js.map +0 -1
- package/dist-server/service/chat-session/session-anchor.d.ts +0 -12
- package/dist-server/service/chat-session/session-anchor.js +0 -20
- package/dist-server/service/chat-session/session-anchor.js.map +0 -1
- package/dist-server/service/chat-session/session-inbox.d.ts +0 -80
- package/dist-server/service/chat-session/session-inbox.js +0 -133
- package/dist-server/service/chat-session/session-inbox.js.map +0 -1
- package/dist-server/service/chat-session-participant/chat-session-participant.d.ts +0 -49
- package/dist-server/service/chat-session-participant/chat-session-participant.js +0 -141
- package/dist-server/service/chat-session-participant/chat-session-participant.js.map +0 -1
- package/dist-server/service/chat-session-participant/index.d.ts +0 -4
- package/dist-server/service/chat-session-participant/index.js +0 -10
- package/dist-server/service/chat-session-participant/index.js.map +0 -1
- package/dist-server/service/chat-session-participant/invite-notification.d.ts +0 -27
- package/dist-server/service/chat-session-participant/invite-notification.js +0 -30
- package/dist-server/service/chat-session-participant/invite-notification.js.map +0 -1
- package/dist-server/service/chat-session-participant/presence.d.ts +0 -4
- package/dist-server/service/chat-session-participant/presence.js +0 -22
- package/dist-server/service/chat-session-participant/presence.js.map +0 -1
- package/dist-server/service/chat-session-resolver.d.ts +0 -102
- package/dist-server/service/chat-session-resolver.js +0 -856
- package/dist-server/service/chat-session-resolver.js.map +0 -1
- package/dist-server/service/subscribe-auth.d.ts +0 -14
- package/dist-server/service/subscribe-auth.js +0 -33
- package/dist-server/service/subscribe-auth.js.map +0 -1
- package/server/service/chat-message/chat-message-broadcast.integration.test.ts +0 -73
- package/server/service/chat-message/chat-message-broadcast.test.ts +0 -40
- package/server/service/chat-message/chat-message-broadcast.ts +0 -27
- package/server/service/chat-message/chat-message-publish.ts +0 -22
- package/server/service/chat-message/chat-message-subscription.ts +0 -41
- package/server/service/chat-message/chat-message.ts +0 -195
- package/server/service/chat-message/fold-history.test.ts +0 -98
- package/server/service/chat-message/fold-history.ts +0 -77
- package/server/service/chat-message/history-summary.test.ts +0 -127
- package/server/service/chat-message/history-summary.ts +0 -100
- package/server/service/chat-message/index.ts +0 -12
- package/server/service/chat-message/llm-history.test.ts +0 -194
- package/server/service/chat-message/llm-history.ts +0 -163
- package/server/service/chat-session/chat-session.ts +0 -182
- package/server/service/chat-session/index.ts +0 -5
- package/server/service/chat-session/session-activity-broadcast.ts +0 -57
- package/server/service/chat-session/session-activity-publish.ts +0 -44
- package/server/service/chat-session/session-activity-subscription.ts +0 -67
- package/server/service/chat-session/session-anchor.ts +0 -35
- package/server/service/chat-session/session-inbox.test.ts +0 -185
- package/server/service/chat-session/session-inbox.ts +0 -161
- package/server/service/chat-session-participant/chat-session-participant.ts +0 -135
- package/server/service/chat-session-participant/index.ts +0 -6
- package/server/service/chat-session-participant/invite-notification.test.ts +0 -30
- package/server/service/chat-session-participant/invite-notification.ts +0 -48
- package/server/service/chat-session-participant/presence.test.ts +0 -39
- package/server/service/chat-session-participant/presence.ts +0 -21
- package/server/service/chat-session-resolver.ts +0 -779
- package/server/service/session-anchor.test.ts +0 -65
- package/server/service/subscribe-auth.test.ts +0 -57
- package/server/service/subscribe-auth.ts +0 -34
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MySessionActivitySubscription = exports.SessionActivity = exports.publishSessionActivity = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
/*
|
|
6
|
-
* MySessionActivitySubscription — **내가 참여한 모든 세션**의 활동 알림.
|
|
7
|
-
*
|
|
8
|
-
* 기존 chatMessageActivity 는 그 세션을 열어 둔 구독자에게 본문을 보낸다 → 창을 닫아 두면 새 메시지를
|
|
9
|
-
* 알 수 없었다. 이 구독은 배지·목록 갱신용으로 최소 정보만 보낸다(본문 없음).
|
|
10
|
-
*
|
|
11
|
-
* 도메인 격리는 필터가, "내 것만" 은 참여자 검사가 성립시킨다(session-activity-broadcast.ts).
|
|
12
|
-
*/
|
|
13
|
-
const type_graphql_1 = require("type-graphql");
|
|
14
|
-
const graphql_yoga_1 = require("graphql-yoga");
|
|
15
|
-
const shell_1 = require("@things-factory/shell");
|
|
16
|
-
const session_activity_broadcast_js_1 = require("./session-activity-broadcast.js");
|
|
17
|
-
const subscribe_auth_js_1 = require("../subscribe-auth.js");
|
|
18
|
-
var session_activity_publish_js_1 = require("./session-activity-publish.js");
|
|
19
|
-
Object.defineProperty(exports, "publishSessionActivity", { enumerable: true, get: function () { return session_activity_publish_js_1.publishSessionActivity; } });
|
|
20
|
-
let SessionActivity = class SessionActivity {
|
|
21
|
-
};
|
|
22
|
-
exports.SessionActivity = SessionActivity;
|
|
23
|
-
tslib_1.__decorate([
|
|
24
|
-
(0, type_graphql_1.Field)({ description: 'Session that had activity.' }),
|
|
25
|
-
tslib_1.__metadata("design:type", String)
|
|
26
|
-
], SessionActivity.prototype, "sessionId", void 0);
|
|
27
|
-
tslib_1.__decorate([
|
|
28
|
-
(0, type_graphql_1.Field)({
|
|
29
|
-
description: "Kind of activity: 'message' (new message — raise the unread badge) or 'meta' (session itself changed, e.g. renamed — refresh the list but do not badge)."
|
|
30
|
-
}),
|
|
31
|
-
tslib_1.__metadata("design:type", String)
|
|
32
|
-
], SessionActivity.prototype, "kind", void 0);
|
|
33
|
-
tslib_1.__decorate([
|
|
34
|
-
(0, type_graphql_1.Field)({ nullable: true, description: "What the session is anchored to: 'board' | 'space' | 'instance' | 'none'." }),
|
|
35
|
-
tslib_1.__metadata("design:type", String)
|
|
36
|
-
], SessionActivity.prototype, "anchorType", void 0);
|
|
37
|
-
tslib_1.__decorate([
|
|
38
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Id of the anchored target.' }),
|
|
39
|
-
tslib_1.__metadata("design:type", String)
|
|
40
|
-
], SessionActivity.prototype, "anchorId", void 0);
|
|
41
|
-
tslib_1.__decorate([
|
|
42
|
-
(0, type_graphql_1.Field)({ description: 'Activity timestamp (ISO).' }),
|
|
43
|
-
tslib_1.__metadata("design:type", String)
|
|
44
|
-
], SessionActivity.prototype, "at", void 0);
|
|
45
|
-
tslib_1.__decorate([
|
|
46
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'One-line preview (not the full body).' }),
|
|
47
|
-
tslib_1.__metadata("design:type", String)
|
|
48
|
-
], SessionActivity.prototype, "preview", void 0);
|
|
49
|
-
tslib_1.__decorate([
|
|
50
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'User who caused the activity — clients skip badging their own.' }),
|
|
51
|
-
tslib_1.__metadata("design:type", String)
|
|
52
|
-
], SessionActivity.prototype, "actorId", void 0);
|
|
53
|
-
exports.SessionActivity = SessionActivity = tslib_1.__decorate([
|
|
54
|
-
(0, type_graphql_1.ObjectType)({ description: 'Activity notice for a session the current user participates in — badge/list refresh only, no message body.' })
|
|
55
|
-
], SessionActivity);
|
|
56
|
-
let MySessionActivitySubscription = class MySessionActivitySubscription {
|
|
57
|
-
mySessionActivity(payload) {
|
|
58
|
-
return {
|
|
59
|
-
sessionId: payload.sessionId,
|
|
60
|
-
kind: payload.kind ?? 'message',
|
|
61
|
-
anchorType: payload.anchorType,
|
|
62
|
-
anchorId: payload.anchorId,
|
|
63
|
-
at: payload.at,
|
|
64
|
-
preview: payload.preview,
|
|
65
|
-
actorId: payload.actorId
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
exports.MySessionActivitySubscription = MySessionActivitySubscription;
|
|
70
|
-
tslib_1.__decorate([
|
|
71
|
-
(0, type_graphql_1.Subscription)(() => SessionActivity, {
|
|
72
|
-
description: 'Subscribes to activity in every session the current user participates in, so a closed chat surface can still show unread badges and refresh its list.',
|
|
73
|
-
subscribe: async ({ context }) => {
|
|
74
|
-
const { domain, user } = context.state;
|
|
75
|
-
await (0, subscribe_auth_js_1.assertDomainSubscribeAllowed)(domain, user, (d, u) => process.superUserGranted(d, u));
|
|
76
|
-
return (0, graphql_yoga_1.pipe)(shell_1.pubsub.subscribe(session_activity_broadcast_js_1.SESSION_ACTIVITY_TOPIC), (0, graphql_yoga_1.filter)((0, session_activity_broadcast_js_1.sessionActivityFilter)(domain.id, user.id)));
|
|
77
|
-
}
|
|
78
|
-
}),
|
|
79
|
-
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
80
|
-
tslib_1.__metadata("design:type", Function),
|
|
81
|
-
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
82
|
-
tslib_1.__metadata("design:returntype", SessionActivity)
|
|
83
|
-
], MySessionActivitySubscription.prototype, "mySessionActivity", null);
|
|
84
|
-
exports.MySessionActivitySubscription = MySessionActivitySubscription = tslib_1.__decorate([
|
|
85
|
-
(0, type_graphql_1.Resolver)(SessionActivity)
|
|
86
|
-
], MySessionActivitySubscription);
|
|
87
|
-
//# sourceMappingURL=session-activity-subscription.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-activity-subscription.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-activity-subscription.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;GAOG;AACH,+CAA8E;AAC9E,+CAA2C;AAC3C,iDAA8C;AAE9C,mFAA4H;AAC5H,4DAAmE;AAEnE,6EAAsE;AAA7D,qIAAA,sBAAsB,OAAA;AAGxB,IAAM,eAAe,GAArB,MAAM,eAAe;CAwB3B,CAAA;AAxBY,0CAAe;AAE1B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;kDACnC;AAMlB;IAJC,IAAA,oBAAK,EAAC;QACL,WAAW,EACT,0JAA0J;KAC7J,CAAC;;6CACW;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;;mDACjG;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;iDACpD;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;;2CACzC;AAGX;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;;gDAChE;AAGhB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gEAAgE,EAAE,CAAC;;gDACzF;0BAvBL,eAAe;IAD3B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,4GAA4G,EAAE,CAAC;GAC7H,eAAe,CAwB3B;AAGM,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IAUxC,iBAAiB,CAAS,OAA+B;QACvD,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS;YAC/B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAA;IACH,CAAC;CACF,CAAA;AArBY,sEAA6B;AAUxC;IATC,IAAA,2BAAY,EAAC,GAAG,EAAE,CAAC,eAAe,EAAE;QACnC,WAAW,EACT,uJAAuJ;QACzJ,SAAS,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YAC/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;YACtC,MAAM,IAAA,gDAA4B,EAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YAC1F,OAAO,IAAA,mBAAI,EAAC,cAAM,CAAC,SAAS,CAAC,sDAAsB,CAAC,EAAE,IAAA,qBAAM,EAAC,IAAA,qDAAqB,EAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAC1G,CAAC;KACF,CAAC;IACiB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;;4CAAmC,eAAe;sEAU1E;wCApBU,6BAA6B;IADzC,IAAA,uBAAQ,EAAC,eAAe,CAAC;GACb,6BAA6B,CAqBzC","sourcesContent":["/*\n * MySessionActivitySubscription — **내가 참여한 모든 세션**의 활동 알림.\n *\n * 기존 chatMessageActivity 는 그 세션을 열어 둔 구독자에게 본문을 보낸다 → 창을 닫아 두면 새 메시지를\n * 알 수 없었다. 이 구독은 배지·목록 갱신용으로 최소 정보만 보낸다(본문 없음).\n *\n * 도메인 격리는 필터가, \"내 것만\" 은 참여자 검사가 성립시킨다(session-activity-broadcast.ts).\n */\nimport { Resolver, Subscription, Root, ObjectType, Field } from 'type-graphql'\nimport { filter, pipe } from 'graphql-yoga'\nimport { pubsub } from '@things-factory/shell'\n\nimport { SESSION_ACTIVITY_TOPIC, sessionActivityFilter, type SessionActivityPayload } from './session-activity-broadcast.js'\nimport { assertDomainSubscribeAllowed } from '../subscribe-auth.js'\n\nexport { publishSessionActivity } from './session-activity-publish.js'\n\n@ObjectType({ description: 'Activity notice for a session the current user participates in — badge/list refresh only, no message body.' })\nexport class SessionActivity {\n @Field({ description: 'Session that had activity.' })\n sessionId!: string\n\n @Field({\n description:\n \"Kind of activity: 'message' (new message — raise the unread badge) or 'meta' (session itself changed, e.g. renamed — refresh the list but do not badge).\"\n })\n kind!: string\n\n @Field({ nullable: true, description: \"What the session is anchored to: 'board' | 'space' | 'instance' | 'none'.\" })\n anchorType?: string\n\n @Field({ nullable: true, description: 'Id of the anchored target.' })\n anchorId?: string\n\n @Field({ description: 'Activity timestamp (ISO).' })\n at!: string\n\n @Field({ nullable: true, description: 'One-line preview (not the full body).' })\n preview?: string\n\n @Field({ nullable: true, description: 'User who caused the activity — clients skip badging their own.' })\n actorId?: string\n}\n\n@Resolver(SessionActivity)\nexport class MySessionActivitySubscription {\n @Subscription(() => SessionActivity, {\n description:\n 'Subscribes to activity in every session the current user participates in, so a closed chat surface can still show unread badges and refresh its list.',\n subscribe: async ({ context }) => {\n const { domain, user } = context.state\n await assertDomainSubscribeAllowed(domain, user, (d, u) => process.superUserGranted(d, u))\n return pipe(pubsub.subscribe(SESSION_ACTIVITY_TOPIC), filter(sessionActivityFilter(domain.id, user.id)))\n }\n })\n mySessionActivity(@Root() payload: SessionActivityPayload): SessionActivity {\n return {\n sessionId: payload.sessionId,\n kind: payload.kind ?? 'message',\n anchorType: payload.anchorType,\n anchorId: payload.anchorId,\n at: payload.at,\n preview: payload.preview,\n actorId: payload.actorId\n }\n }\n}\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type SessionAnchorType = 'board' | 'space' | 'instance' | 'none';
|
|
2
|
-
/** 앵커 → 저장할 컬럼 값. 보드 앵커는 boardId 에도 같은 값을 넣어 기존 조회가 그대로 동작하게 한다. */
|
|
3
|
-
export declare function anchorColumns(anchorType: string | undefined, anchorId: string | undefined): {
|
|
4
|
-
anchorType: SessionAnchorType;
|
|
5
|
-
anchorId?: string;
|
|
6
|
-
boardId?: string;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* 앵커 조회 조건. 보드 앵커는 **앵커 컬럼이 빈 옛 행도 잡아야** 하므로 boardId 로 찾는다
|
|
10
|
-
* (dual-write 덕분에 신규 행도 같은 조건에 걸린다). 그 밖 앵커는 앵커 컬럼으로 찾는다.
|
|
11
|
-
*/
|
|
12
|
-
export declare function anchorWhere(domainId: string, anchorType: string, anchorId: string): any;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.anchorColumns = anchorColumns;
|
|
4
|
-
exports.anchorWhere = anchorWhere;
|
|
5
|
-
/** 앵커 → 저장할 컬럼 값. 보드 앵커는 boardId 에도 같은 값을 넣어 기존 조회가 그대로 동작하게 한다. */
|
|
6
|
-
function anchorColumns(anchorType, anchorId) {
|
|
7
|
-
const type = (anchorType || 'none');
|
|
8
|
-
const id = anchorId || undefined;
|
|
9
|
-
return { anchorType: type, anchorId: id, boardId: type === 'board' ? id : undefined };
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* 앵커 조회 조건. 보드 앵커는 **앵커 컬럼이 빈 옛 행도 잡아야** 하므로 boardId 로 찾는다
|
|
13
|
-
* (dual-write 덕분에 신규 행도 같은 조건에 걸린다). 그 밖 앵커는 앵커 컬럼으로 찾는다.
|
|
14
|
-
*/
|
|
15
|
-
function anchorWhere(domainId, anchorType, anchorId) {
|
|
16
|
-
if (anchorType === 'board')
|
|
17
|
-
return { boardId: anchorId, domain: { id: domainId } };
|
|
18
|
-
return { anchorType, anchorId, domain: { id: domainId } };
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=session-anchor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-anchor.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-anchor.ts"],"names":[],"mappings":";;AAkBA,sCAOC;AAMD,kCAGC;AAjBD,oEAAoE;AACpE,SAAgB,aAAa,CAC3B,UAA8B,EAC9B,QAA4B;IAE5B,MAAM,IAAI,GAAG,CAAC,UAAU,IAAI,MAAM,CAAsB,CAAA;IACxD,MAAM,EAAE,GAAG,QAAQ,IAAI,SAAS,CAAA;IAChC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;AACvF,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,QAAgB,EAAE,UAAkB,EAAE,QAAgB;IAChF,IAAI,UAAU,KAAK,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;IAClF,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAA;AAC3D,CAAC","sourcesContent":["/*\n * 세션 앵커 순수 로직 — 리졸버와 분리.\n *\n * chat-session-resolver 는 type-graphql 의 **매개변수 데코레이터**(@Arg)를 쓰므로 jest 의 babel\n * 파서가 읽지 못한다. 순수 함수를 여기 두면 단위 테스트가 가능하다(chat-echo-dedup ·\n * chat-input-builder 와 같은 관례).\n *\n * **앵커란**: 대화가 무엇에 매달려 있는지. 저작 대화는 보드에, 운영 대화는 공간(사이트와 그 공간에서\n * 도는 트윈들)에 매달린다. 앵커가 대화의 성격과 **이력 경계**를 정한다 — 보드 편집 이력에 운영\n * 문답이 끼지 않아야 하고, 그 반대도 마찬가지다.\n *\n * **하위호환**: 기존 행은 앵커 컬럼이 비어 있고 boardId 만 있다. 백필하지 않고 **읽을 때** board\n * 앵커로 간주한다(컬럼 추가만으로 끝내기 위함). 보드 앵커 세션은 anchorId 와 boardId 를 함께\n * 쓴다(dual-write) — 기존 조회·인덱스·소비자(operato-board 등)가 그대로 동작한다.\n */\nexport type SessionAnchorType = 'board' | 'space' | 'instance' | 'none'\n\n/** 앵커 → 저장할 컬럼 값. 보드 앵커는 boardId 에도 같은 값을 넣어 기존 조회가 그대로 동작하게 한다. */\nexport function anchorColumns(\n anchorType: string | undefined,\n anchorId: string | undefined\n): { anchorType: SessionAnchorType; anchorId?: string; boardId?: string } {\n const type = (anchorType || 'none') as SessionAnchorType\n const id = anchorId || undefined\n return { anchorType: type, anchorId: id, boardId: type === 'board' ? id : undefined }\n}\n\n/**\n * 앵커 조회 조건. 보드 앵커는 **앵커 컬럼이 빈 옛 행도 잡아야** 하므로 boardId 로 찾는다\n * (dual-write 덕분에 신규 행도 같은 조건에 걸린다). 그 밖 앵커는 앵커 컬럼으로 찾는다.\n */\nexport function anchorWhere(domainId: string, anchorType: string, anchorId: string): any {\n if (anchorType === 'board') return { boardId: anchorId, domain: { id: domainId } }\n return { anchorType, anchorId, domain: { id: domainId } }\n}\n"]}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/** 목록에 필요한 세션 필드(엔티티·typeorm 비의존). */
|
|
2
|
-
export interface InboxSessionRow {
|
|
3
|
-
id?: string;
|
|
4
|
-
name?: string;
|
|
5
|
-
anchorType?: string;
|
|
6
|
-
anchorId?: string;
|
|
7
|
-
boardId?: string;
|
|
8
|
-
lastMessageAt?: Date | string | null;
|
|
9
|
-
lastMessagePreview?: string | null;
|
|
10
|
-
createdAt?: Date | string | null;
|
|
11
|
-
}
|
|
12
|
-
/** 내 참여 기록(읽은 지점). */
|
|
13
|
-
export interface MyParticipation {
|
|
14
|
-
sessionId?: string;
|
|
15
|
-
lastReadAt?: Date | string | null;
|
|
16
|
-
/** 내 목록에서 숨긴 시각 — 이후 새 활동이 생기면 다시 보인다. */
|
|
17
|
-
hiddenAt?: Date | string | null;
|
|
18
|
-
}
|
|
19
|
-
export interface InboxEntry extends InboxSessionRow {
|
|
20
|
-
/** 안 읽은 활동이 있는가 — 목록의 점 표시. */
|
|
21
|
-
unread: boolean;
|
|
22
|
-
/** 내가 참여자인가 — 아니면 열어볼 수는 있어도 읽음 상태를 갖지 않는다. */
|
|
23
|
-
participant: boolean;
|
|
24
|
-
/** 내가 숨긴 대화인가 — 목록에서 빠지지만 필터로 볼 수 있다(되돌리기 가능). */
|
|
25
|
-
hidden?: boolean;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* 세션 + 내 참여 기록 → 목록 항목. **최근 활동순**(활동 없으면 생성순) 내림차순.
|
|
29
|
-
*
|
|
30
|
-
* 안 읽음 판정: 세션의 마지막 활동이 내가 읽은 지점보다 **뒤**면 안 읽음.
|
|
31
|
-
* · 참여자가 아니면 안 읽음으로 표시하지 않는다(내 것이 아닌 대화에 배지를 띄우지 않는다).
|
|
32
|
-
* · 참여자인데 한 번도 읽지 않았고(lastReadAt 없음) 활동이 있으면 안 읽음이다.
|
|
33
|
-
* · 활동이 없는 세션(빈 대화)은 안 읽음이 아니다.
|
|
34
|
-
*
|
|
35
|
-
* 같은 시각 비교는 **엄격 초과**만 안 읽음으로 본다 — 읽은 직후 같은 밀리초에 저장된 활동을 안 읽음으로
|
|
36
|
-
* 잡으면 방금 읽은 화면에 배지가 남는다.
|
|
37
|
-
*/
|
|
38
|
-
export declare function buildInbox(sessions: InboxSessionRow[], mine: MyParticipation[]): InboxEntry[];
|
|
39
|
-
/**
|
|
40
|
-
* 숨김 표시·필터.
|
|
41
|
-
*
|
|
42
|
-
* 숨김은 **나에게만** 적용되고 되돌릴 수 있다. 숨긴 **뒤에 새 활동이 생기면 다시 보인다** —
|
|
43
|
-
* 아직 참여 중인 대화에서 조용히 잘려 나가는 것이 목록 한 줄보다 나쁘다.
|
|
44
|
-
*
|
|
45
|
-
* `showHidden` 이면 숨긴 것도 함께 돌려주되 표시(hidden)를 남긴다 — 필터를 켠 사용자가 무엇이
|
|
46
|
-
* 숨겨진 것인지 알아야 되돌릴 수 있다.
|
|
47
|
-
*/
|
|
48
|
-
export declare function applyHidden(entries: InboxEntry[], hiddenAt: Map<string, Date | string | null | undefined>, showHidden?: boolean): InboxEntry[];
|
|
49
|
-
/**
|
|
50
|
-
* 검색 — 이름과 마지막 미리보기에 대한 대소문자 무시 부분일치.
|
|
51
|
-
*
|
|
52
|
-
* **왜 메모리에서 하는가**: 이 프레임워크는 5개 DB 드라이버를 지원한다. 대소문자 무시 검색은
|
|
53
|
-
* 드라이버마다 표기가 갈리고(ILIKE=pg 전용, LOWER()+LIKE 는 되지만 정렬·NULL 취급이 또 갈린다),
|
|
54
|
-
* 목록 경로에 드라이버별 SQL 을 두는 것은 이 프로젝트의 규율에 반한다. 그래서 조회는 앵커로
|
|
55
|
-
* **상한을 두고** 가져오고(아래 INBOX_SCAN_CAP) 걸러내기·정렬·페이지는 여기서 한다.
|
|
56
|
-
* 상한을 넘으면 잘렸다는 사실을 그대로 알린다(조용히 일부만 보여주지 않는다).
|
|
57
|
-
*/
|
|
58
|
-
export declare function searchInbox(entries: InboxEntry[], search?: string): InboxEntry[];
|
|
59
|
-
/** 한 번에 훑는 세션 상한 — 이보다 많으면 잘렸다고 알린다(정직). */
|
|
60
|
-
export declare const INBOX_SCAN_CAP = 500;
|
|
61
|
-
/** 안 읽은 세션 수 — 도크 버튼 배지(개수가 아니라 **세션 수**). */
|
|
62
|
-
export declare function countUnreadSessions(entries: InboxEntry[]): number;
|
|
63
|
-
/**
|
|
64
|
-
* 메시지 저장 시 세션에 반영할 활동 값. 미리보기는 짧게 자르고 개행을 없앤다
|
|
65
|
-
* (목록 한 줄에 들어가야 하고, 컬럼 길이 제한이 있다).
|
|
66
|
-
*/
|
|
67
|
-
export declare function activityPatch(content: string, at?: Date): {
|
|
68
|
-
lastMessageAt: Date;
|
|
69
|
-
lastMessagePreview: string;
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* 첫 발화로 세션 이름을 만든다.
|
|
73
|
-
*
|
|
74
|
-
* `세션 2` 같은 순번은 목록에서 아무것도 알려주지 않는다 — "A-DC 포화 원인" 이어야 돌아갈 대화를 찾는다.
|
|
75
|
-
* 사용자가 직접 지은 이름은 이 함수로 덮지 않는다(호출부가 이름 없을 때만 부른다).
|
|
76
|
-
*
|
|
77
|
-
* 규칙: 한 줄로 눌러 첫 문장 경계(., ?, !, 개행)까지, 최대 40자. 문장 부호로 끝나면 떼어 낸다
|
|
78
|
-
* (목록 제목에 물음표가 붙으면 길이만 먹는다).
|
|
79
|
-
*/
|
|
80
|
-
export declare function autoSessionName(content: string, max?: number): string;
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* 세션 목록(받은편지함) 순수 로직 — 리졸버와 분리해 단위 테스트 가능.
|
|
4
|
-
*
|
|
5
|
-
* ── 왜 필요한가 ─────────────────────────────────────────────────────────────
|
|
6
|
-
* 대화가 늘면(가벼운 질문을 승격할 때마다 새 세션) "어디로 갈지"를 목록에서 골라야 하고, 다른 참여자가
|
|
7
|
-
* 남긴 새 메시지를 알아야 한다. 세션 목록은 **최근 활동순**이어야 하고 **안 읽음**이 보여야 한다.
|
|
8
|
-
*
|
|
9
|
-
* ── 집계 쿼리를 쓰지 않는다 ─────────────────────────────────────────────────
|
|
10
|
-
* 세션마다 메시지를 집계하면(MAX/COUNT + group by) 목록 한 번에 집계가 붙고, 이 프레임워크는 5개 DB
|
|
11
|
-
* 드라이버를 지원해야 한다. 대신 `ChatSession.lastMessageAt` 을 비정규화해 두고(메시지 저장 시 갱신),
|
|
12
|
-
* 참여자의 `lastReadAt` 과 **값 비교**로 안 읽음을 판정한다 — 조회 두 번(세션·내 참여자)으로 끝난다.
|
|
13
|
-
*
|
|
14
|
-
* ── v1 은 개수가 아니라 "안 읽음 여부" ──────────────────────────────────────
|
|
15
|
-
* 정확한 미읽음 **개수**는 세션별 count 가 필요하다(목록 N개면 N번). 목록에서는 점 하나로 충분하고,
|
|
16
|
-
* 숫자가 필요해지면 화면에 보이는 세션에 한해 따로 세면 된다. 처음부터 N번 세지 않는다.
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.INBOX_SCAN_CAP = void 0;
|
|
20
|
-
exports.buildInbox = buildInbox;
|
|
21
|
-
exports.applyHidden = applyHidden;
|
|
22
|
-
exports.searchInbox = searchInbox;
|
|
23
|
-
exports.countUnreadSessions = countUnreadSessions;
|
|
24
|
-
exports.activityPatch = activityPatch;
|
|
25
|
-
exports.autoSessionName = autoSessionName;
|
|
26
|
-
function time(v) {
|
|
27
|
-
if (!v)
|
|
28
|
-
return 0;
|
|
29
|
-
const t = v instanceof Date ? v.getTime() : Date.parse(v);
|
|
30
|
-
return Number.isFinite(t) ? t : 0;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* 세션 + 내 참여 기록 → 목록 항목. **최근 활동순**(활동 없으면 생성순) 내림차순.
|
|
34
|
-
*
|
|
35
|
-
* 안 읽음 판정: 세션의 마지막 활동이 내가 읽은 지점보다 **뒤**면 안 읽음.
|
|
36
|
-
* · 참여자가 아니면 안 읽음으로 표시하지 않는다(내 것이 아닌 대화에 배지를 띄우지 않는다).
|
|
37
|
-
* · 참여자인데 한 번도 읽지 않았고(lastReadAt 없음) 활동이 있으면 안 읽음이다.
|
|
38
|
-
* · 활동이 없는 세션(빈 대화)은 안 읽음이 아니다.
|
|
39
|
-
*
|
|
40
|
-
* 같은 시각 비교는 **엄격 초과**만 안 읽음으로 본다 — 읽은 직후 같은 밀리초에 저장된 활동을 안 읽음으로
|
|
41
|
-
* 잡으면 방금 읽은 화면에 배지가 남는다.
|
|
42
|
-
*/
|
|
43
|
-
function buildInbox(sessions, mine) {
|
|
44
|
-
const readBy = new Map();
|
|
45
|
-
const isParticipant = new Set();
|
|
46
|
-
for (const p of mine) {
|
|
47
|
-
if (!p.sessionId)
|
|
48
|
-
continue;
|
|
49
|
-
isParticipant.add(p.sessionId);
|
|
50
|
-
readBy.set(p.sessionId, time(p.lastReadAt));
|
|
51
|
-
}
|
|
52
|
-
const entries = sessions.map(session => {
|
|
53
|
-
const id = session.id ?? '';
|
|
54
|
-
const activity = time(session.lastMessageAt);
|
|
55
|
-
const participant = isParticipant.has(id);
|
|
56
|
-
const read = readBy.get(id) ?? 0;
|
|
57
|
-
return {
|
|
58
|
-
...session,
|
|
59
|
-
participant,
|
|
60
|
-
unread: participant && activity > 0 && activity > read
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
return entries.sort((a, b) => (time(b.lastMessageAt) || time(b.createdAt)) - (time(a.lastMessageAt) || time(a.createdAt)));
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* 숨김 표시·필터.
|
|
67
|
-
*
|
|
68
|
-
* 숨김은 **나에게만** 적용되고 되돌릴 수 있다. 숨긴 **뒤에 새 활동이 생기면 다시 보인다** —
|
|
69
|
-
* 아직 참여 중인 대화에서 조용히 잘려 나가는 것이 목록 한 줄보다 나쁘다.
|
|
70
|
-
*
|
|
71
|
-
* `showHidden` 이면 숨긴 것도 함께 돌려주되 표시(hidden)를 남긴다 — 필터를 켠 사용자가 무엇이
|
|
72
|
-
* 숨겨진 것인지 알아야 되돌릴 수 있다.
|
|
73
|
-
*/
|
|
74
|
-
function applyHidden(entries, hiddenAt, showHidden = false) {
|
|
75
|
-
const out = [];
|
|
76
|
-
for (const entry of entries) {
|
|
77
|
-
const at = hiddenAt.get(entry.id ?? '');
|
|
78
|
-
/* 숨긴 시각보다 **뒤에** 활동이 있으면 숨김은 풀린 것으로 본다. */
|
|
79
|
-
const hidden = !!at && time(entry.lastMessageAt) <= time(at);
|
|
80
|
-
if (hidden && !showHidden)
|
|
81
|
-
continue;
|
|
82
|
-
out.push(hidden ? { ...entry, hidden: true } : entry);
|
|
83
|
-
}
|
|
84
|
-
return out;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* 검색 — 이름과 마지막 미리보기에 대한 대소문자 무시 부분일치.
|
|
88
|
-
*
|
|
89
|
-
* **왜 메모리에서 하는가**: 이 프레임워크는 5개 DB 드라이버를 지원한다. 대소문자 무시 검색은
|
|
90
|
-
* 드라이버마다 표기가 갈리고(ILIKE=pg 전용, LOWER()+LIKE 는 되지만 정렬·NULL 취급이 또 갈린다),
|
|
91
|
-
* 목록 경로에 드라이버별 SQL 을 두는 것은 이 프로젝트의 규율에 반한다. 그래서 조회는 앵커로
|
|
92
|
-
* **상한을 두고** 가져오고(아래 INBOX_SCAN_CAP) 걸러내기·정렬·페이지는 여기서 한다.
|
|
93
|
-
* 상한을 넘으면 잘렸다는 사실을 그대로 알린다(조용히 일부만 보여주지 않는다).
|
|
94
|
-
*/
|
|
95
|
-
function searchInbox(entries, search) {
|
|
96
|
-
const q = (search ?? '').trim().toLowerCase();
|
|
97
|
-
if (!q)
|
|
98
|
-
return entries;
|
|
99
|
-
return entries.filter(e => `${e.name ?? ''}\n${e.lastMessagePreview ?? ''}`.toLowerCase().includes(q));
|
|
100
|
-
}
|
|
101
|
-
/** 한 번에 훑는 세션 상한 — 이보다 많으면 잘렸다고 알린다(정직). */
|
|
102
|
-
exports.INBOX_SCAN_CAP = 500;
|
|
103
|
-
/** 안 읽은 세션 수 — 도크 버튼 배지(개수가 아니라 **세션 수**). */
|
|
104
|
-
function countUnreadSessions(entries) {
|
|
105
|
-
return entries.filter(e => e.unread).length;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 메시지 저장 시 세션에 반영할 활동 값. 미리보기는 짧게 자르고 개행을 없앤다
|
|
109
|
-
* (목록 한 줄에 들어가야 하고, 컬럼 길이 제한이 있다).
|
|
110
|
-
*/
|
|
111
|
-
function activityPatch(content, at = new Date()) {
|
|
112
|
-
const flat = (content ?? '').replace(/\s+/g, ' ').trim();
|
|
113
|
-
return { lastMessageAt: at, lastMessagePreview: flat.slice(0, 200) };
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* 첫 발화로 세션 이름을 만든다.
|
|
117
|
-
*
|
|
118
|
-
* `세션 2` 같은 순번은 목록에서 아무것도 알려주지 않는다 — "A-DC 포화 원인" 이어야 돌아갈 대화를 찾는다.
|
|
119
|
-
* 사용자가 직접 지은 이름은 이 함수로 덮지 않는다(호출부가 이름 없을 때만 부른다).
|
|
120
|
-
*
|
|
121
|
-
* 규칙: 한 줄로 눌러 첫 문장 경계(., ?, !, 개행)까지, 최대 40자. 문장 부호로 끝나면 떼어 낸다
|
|
122
|
-
* (목록 제목에 물음표가 붙으면 길이만 먹는다).
|
|
123
|
-
*/
|
|
124
|
-
function autoSessionName(content, max = 40) {
|
|
125
|
-
const flat = (content ?? '').replace(/\s+/g, ' ').trim();
|
|
126
|
-
if (!flat)
|
|
127
|
-
return '';
|
|
128
|
-
const cut = flat.search(/[.?!\n]/);
|
|
129
|
-
const head = (cut > 0 ? flat.slice(0, cut) : flat).trim();
|
|
130
|
-
const name = head.length > max ? head.slice(0, max).trim() + '…' : head;
|
|
131
|
-
return name;
|
|
132
|
-
}
|
|
133
|
-
//# sourceMappingURL=session-inbox.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-inbox.js","sourceRoot":"","sources":["../../../server/service/chat-session/session-inbox.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 세션 목록(받은편지함) 순수 로직 — 리졸버와 분리해 단위 테스트 가능.\n *\n * ── 왜 필요한가 ─────────────────────────────────────────────────────────────\n * 대화가 늘면(가벼운 질문을 승격할 때마다 새 세션) \"어디로 갈지\"를 목록에서 골라야 하고, 다른 참여자가\n * 남긴 새 메시지를 알아야 한다. 세션 목록은 **최근 활동순**이어야 하고 **안 읽음**이 보여야 한다.\n *\n * ── 집계 쿼리를 쓰지 않는다 ─────────────────────────────────────────────────\n * 세션마다 메시지를 집계하면(MAX/COUNT + group by) 목록 한 번에 집계가 붙고, 이 프레임워크는 5개 DB\n * 드라이버를 지원해야 한다. 대신 `ChatSession.lastMessageAt` 을 비정규화해 두고(메시지 저장 시 갱신),\n * 참여자의 `lastReadAt` 과 **값 비교**로 안 읽음을 판정한다 — 조회 두 번(세션·내 참여자)으로 끝난다.\n *\n * ── v1 은 개수가 아니라 \"안 읽음 여부\" ──────────────────────────────────────\n * 정확한 미읽음 **개수**는 세션별 count 가 필요하다(목록 N개면 N번). 목록에서는 점 하나로 충분하고,\n * 숫자가 필요해지면 화면에 보이는 세션에 한해 따로 세면 된다. 처음부터 N번 세지 않는다.\n */\n\n/** 목록에 필요한 세션 필드(엔티티·typeorm 비의존). */\nexport interface InboxSessionRow {\n id?: string\n name?: string\n anchorType?: string\n anchorId?: string\n boardId?: string\n lastMessageAt?: Date | string | null\n lastMessagePreview?: string | null\n createdAt?: Date | string | null\n}\n\n/** 내 참여 기록(읽은 지점). */\nexport interface MyParticipation {\n sessionId?: string\n lastReadAt?: Date | string | null\n /** 내 목록에서 숨긴 시각 — 이후 새 활동이 생기면 다시 보인다. */\n hiddenAt?: Date | string | null\n}\n\nexport interface InboxEntry extends InboxSessionRow {\n /** 안 읽은 활동이 있는가 — 목록의 점 표시. */\n unread: boolean\n /** 내가 참여자인가 — 아니면 열어볼 수는 있어도 읽음 상태를 갖지 않는다. */\n participant: boolean\n /** 내가 숨긴 대화인가 — 목록에서 빠지지만 필터로 볼 수 있다(되돌리기 가능). */\n hidden?: boolean\n}\n\nfunction time(v: Date | string | null | undefined): number {\n if (!v) return 0\n const t = v instanceof Date ? v.getTime() : Date.parse(v)\n return Number.isFinite(t) ? t : 0\n}\n\n/**\n * 세션 + 내 참여 기록 → 목록 항목. **최근 활동순**(활동 없으면 생성순) 내림차순.\n *\n * 안 읽음 판정: 세션의 마지막 활동이 내가 읽은 지점보다 **뒤**면 안 읽음.\n * · 참여자가 아니면 안 읽음으로 표시하지 않는다(내 것이 아닌 대화에 배지를 띄우지 않는다).\n * · 참여자인데 한 번도 읽지 않았고(lastReadAt 없음) 활동이 있으면 안 읽음이다.\n * · 활동이 없는 세션(빈 대화)은 안 읽음이 아니다.\n *\n * 같은 시각 비교는 **엄격 초과**만 안 읽음으로 본다 — 읽은 직후 같은 밀리초에 저장된 활동을 안 읽음으로\n * 잡으면 방금 읽은 화면에 배지가 남는다.\n */\nexport function buildInbox(sessions: InboxSessionRow[], mine: MyParticipation[]): InboxEntry[] {\n const readBy = new Map<string, number>()\n const isParticipant = new Set<string>()\n for (const p of mine) {\n if (!p.sessionId) continue\n isParticipant.add(p.sessionId)\n readBy.set(p.sessionId, time(p.lastReadAt))\n }\n\n const entries = sessions.map(session => {\n const id = session.id ?? ''\n const activity = time(session.lastMessageAt)\n const participant = isParticipant.has(id)\n const read = readBy.get(id) ?? 0\n return {\n ...session,\n participant,\n unread: participant && activity > 0 && activity > read\n }\n })\n\n return entries.sort(\n (a, b) => (time(b.lastMessageAt) || time(b.createdAt)) - (time(a.lastMessageAt) || time(a.createdAt))\n )\n}\n\n/**\n * 숨김 표시·필터.\n *\n * 숨김은 **나에게만** 적용되고 되돌릴 수 있다. 숨긴 **뒤에 새 활동이 생기면 다시 보인다** —\n * 아직 참여 중인 대화에서 조용히 잘려 나가는 것이 목록 한 줄보다 나쁘다.\n *\n * `showHidden` 이면 숨긴 것도 함께 돌려주되 표시(hidden)를 남긴다 — 필터를 켠 사용자가 무엇이\n * 숨겨진 것인지 알아야 되돌릴 수 있다.\n */\nexport function applyHidden(entries: InboxEntry[], hiddenAt: Map<string, Date | string | null | undefined>, showHidden = false): InboxEntry[] {\n const out: InboxEntry[] = []\n for (const entry of entries) {\n const at = hiddenAt.get(entry.id ?? '')\n /* 숨긴 시각보다 **뒤에** 활동이 있으면 숨김은 풀린 것으로 본다. */\n const hidden = !!at && time(entry.lastMessageAt) <= time(at)\n if (hidden && !showHidden) continue\n out.push(hidden ? { ...entry, hidden: true } : entry)\n }\n return out\n}\n\n/**\n * 검색 — 이름과 마지막 미리보기에 대한 대소문자 무시 부분일치.\n *\n * **왜 메모리에서 하는가**: 이 프레임워크는 5개 DB 드라이버를 지원한다. 대소문자 무시 검색은\n * 드라이버마다 표기가 갈리고(ILIKE=pg 전용, LOWER()+LIKE 는 되지만 정렬·NULL 취급이 또 갈린다),\n * 목록 경로에 드라이버별 SQL 을 두는 것은 이 프로젝트의 규율에 반한다. 그래서 조회는 앵커로\n * **상한을 두고** 가져오고(아래 INBOX_SCAN_CAP) 걸러내기·정렬·페이지는 여기서 한다.\n * 상한을 넘으면 잘렸다는 사실을 그대로 알린다(조용히 일부만 보여주지 않는다).\n */\nexport function searchInbox(entries: InboxEntry[], search?: string): InboxEntry[] {\n const q = (search ?? '').trim().toLowerCase()\n if (!q) return entries\n return entries.filter(e =>\n `${e.name ?? ''}\\n${e.lastMessagePreview ?? ''}`.toLowerCase().includes(q)\n )\n}\n\n/** 한 번에 훑는 세션 상한 — 이보다 많으면 잘렸다고 알린다(정직). */\nexport const INBOX_SCAN_CAP = 500\n\n/** 안 읽은 세션 수 — 도크 버튼 배지(개수가 아니라 **세션 수**). */\nexport function countUnreadSessions(entries: InboxEntry[]): number {\n return entries.filter(e => e.unread).length\n}\n\n/**\n * 메시지 저장 시 세션에 반영할 활동 값. 미리보기는 짧게 자르고 개행을 없앤다\n * (목록 한 줄에 들어가야 하고, 컬럼 길이 제한이 있다).\n */\nexport function activityPatch(content: string, at: Date = new Date()): { lastMessageAt: Date; lastMessagePreview: string } {\n const flat = (content ?? '').replace(/\\s+/g, ' ').trim()\n return { lastMessageAt: at, lastMessagePreview: flat.slice(0, 200) }\n}\n\n/**\n * 첫 발화로 세션 이름을 만든다.\n *\n * `세션 2` 같은 순번은 목록에서 아무것도 알려주지 않는다 — \"A-DC 포화 원인\" 이어야 돌아갈 대화를 찾는다.\n * 사용자가 직접 지은 이름은 이 함수로 덮지 않는다(호출부가 이름 없을 때만 부른다).\n *\n * 규칙: 한 줄로 눌러 첫 문장 경계(., ?, !, 개행)까지, 최대 40자. 문장 부호로 끝나면 떼어 낸다\n * (목록 제목에 물음표가 붙으면 길이만 먹는다).\n */\nexport function autoSessionName(content: string, max = 40): string {\n const flat = (content ?? '').replace(/\\s+/g, ' ').trim()\n if (!flat) return ''\n const cut = flat.search(/[.?!\\n]/)\n const head = (cut > 0 ? flat.slice(0, cut) : flat).trim()\n const name = head.length > max ? head.slice(0, max).trim() + '…' : head\n return name\n}\n"]}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Domain } from '@things-factory/shell';
|
|
2
|
-
import { User } from '@things-factory/auth-base';
|
|
3
|
-
import { ChatSession } from '../chat-session/chat-session.js';
|
|
4
|
-
export declare class ChatSessionParticipant {
|
|
5
|
-
readonly id?: string;
|
|
6
|
-
domain?: Domain;
|
|
7
|
-
domainId?: string;
|
|
8
|
-
session?: ChatSession;
|
|
9
|
-
sessionId?: string;
|
|
10
|
-
user?: User;
|
|
11
|
-
userId?: string;
|
|
12
|
-
/**
|
|
13
|
-
* 참여자의 역할.
|
|
14
|
-
* - 'owner': 세션 만든 사람. rename / delete 권한.
|
|
15
|
-
* - 'member': 일반 참여자. 메시지 송수신.
|
|
16
|
-
* - 'viewer': 읽기 전용 (미래 권한 정책 활성화 시).
|
|
17
|
-
*
|
|
18
|
-
* 시작은 'owner' / 'member' 둘로 충분. 더 세분화 필요해지면 enum 확장.
|
|
19
|
-
*/
|
|
20
|
-
role: string;
|
|
21
|
-
/** 마지막 활동 시각 — presence indicator. nullable. */
|
|
22
|
-
lastSeenAt?: Date;
|
|
23
|
-
/**
|
|
24
|
-
* 이 참여자가 **읽은 지점**. 세션의 마지막 활동 시각과 비교해 안 읽음을 판정한다.
|
|
25
|
-
*
|
|
26
|
-
* `lastSeenAt`(접속 표시)과 다른 개념이다 — 창을 열어 두고 화면을 안 볼 수 있고, 접속이 끊긴 뒤에도
|
|
27
|
-
* 읽은 지점은 남는다. 두 값을 섞어 쓰면 "봤는데 안 읽음" 또는 그 반대가 된다.
|
|
28
|
-
* nullable — 한 번도 읽지 않은 참여자(초대 직후)는 세션의 모든 활동이 안 읽음이다.
|
|
29
|
-
*/
|
|
30
|
-
lastReadAt?: Date;
|
|
31
|
-
/**
|
|
32
|
-
* 이 사용자가 **자기 목록에서 숨긴 시각**. 숨김은 **나에게만** 적용된다 — 남의 목록·대화 내용은 그대로다.
|
|
33
|
-
*
|
|
34
|
-
* 왜 삭제와 나누는가: 협의는 여럿의 기록이므로 지우는 것은 **만든 사람**만 할 수 있다(되돌릴 수 없다).
|
|
35
|
-
* 그 권한이 없는 사람에게도 "내 목록을 정리할" 방법은 있어야 하고, 그것이 숨김이다.
|
|
36
|
-
*
|
|
37
|
-
* 숨긴 **뒤에 새 활동이 생기면 다시 나타난다** — 아직 참여자인 대화에서 조용히 잘려 나가는 것이
|
|
38
|
-
* 목록이 한 줄 늘어나는 것보다 나쁘다. 완전히 빠지려면 대화에서 나가야 한다(별개 기능).
|
|
39
|
-
* nullable — 값이 없으면 숨기지 않은 상태.
|
|
40
|
-
*/
|
|
41
|
-
hiddenAt?: Date;
|
|
42
|
-
creator?: User;
|
|
43
|
-
creatorId?: string;
|
|
44
|
-
updater?: User;
|
|
45
|
-
updaterId?: string;
|
|
46
|
-
createdAt?: Date;
|
|
47
|
-
updatedAt?: Date;
|
|
48
|
-
deletedAt?: Date;
|
|
49
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ChatSessionParticipant = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
/**
|
|
6
|
-
* ChatSessionParticipant — 채팅 세션의 참여 사용자.
|
|
7
|
-
*
|
|
8
|
-
* 한 ChatSession 에 여러 사용자가 참여할 수 있고, 각자 role (owner / member / viewer 등)
|
|
9
|
-
* 을 가짐. 다자간 채팅 / 권한 분화 / "내 세션 목록" / 멤버 표시 등의 기반.
|
|
10
|
-
*
|
|
11
|
-
* 현재 visibility 정책 (도메인 내 모두 공개) 은 그대로 유지 — 본 엔티티는 영속/추적
|
|
12
|
-
* 데이터 만들고, "참여자만 접근" 같은 enforcement 는 정책 굳을 때 별도 phase 에서 도입.
|
|
13
|
-
*
|
|
14
|
-
* 자동 참여 vs 명시적 초대 정책도 미정 — 일단 세션 creator 만 자동 'owner' 로 등록.
|
|
15
|
-
*/
|
|
16
|
-
const typeorm_1 = require("typeorm");
|
|
17
|
-
const type_graphql_1 = require("type-graphql");
|
|
18
|
-
const shell_1 = require("@things-factory/shell");
|
|
19
|
-
const auth_base_1 = require("@things-factory/auth-base");
|
|
20
|
-
const chat_session_js_1 = require("../chat-session/chat-session.js");
|
|
21
|
-
let ChatSessionParticipant = class ChatSessionParticipant {
|
|
22
|
-
};
|
|
23
|
-
exports.ChatSessionParticipant = ChatSessionParticipant;
|
|
24
|
-
tslib_1.__decorate([
|
|
25
|
-
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
26
|
-
(0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Unique participant id.' }),
|
|
27
|
-
tslib_1.__metadata("design:type", String)
|
|
28
|
-
], ChatSessionParticipant.prototype, "id", void 0);
|
|
29
|
-
tslib_1.__decorate([
|
|
30
|
-
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
31
|
-
(0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true, description: 'Domain to which this participant belongs.' }),
|
|
32
|
-
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
33
|
-
], ChatSessionParticipant.prototype, "domain", void 0);
|
|
34
|
-
tslib_1.__decorate([
|
|
35
|
-
(0, typeorm_1.RelationId)((p) => p.domain),
|
|
36
|
-
tslib_1.__metadata("design:type", String)
|
|
37
|
-
], ChatSessionParticipant.prototype, "domainId", void 0);
|
|
38
|
-
tslib_1.__decorate([
|
|
39
|
-
(0, typeorm_1.ManyToOne)(type => chat_session_js_1.ChatSession, { onDelete: 'CASCADE' }),
|
|
40
|
-
(0, type_graphql_1.Field)(type => chat_session_js_1.ChatSession, { nullable: true, description: 'The ChatSession this participation belongs to.' }),
|
|
41
|
-
tslib_1.__metadata("design:type", chat_session_js_1.ChatSession)
|
|
42
|
-
], ChatSessionParticipant.prototype, "session", void 0);
|
|
43
|
-
tslib_1.__decorate([
|
|
44
|
-
(0, typeorm_1.RelationId)((p) => p.session),
|
|
45
|
-
tslib_1.__metadata("design:type", String)
|
|
46
|
-
], ChatSessionParticipant.prototype, "sessionId", void 0);
|
|
47
|
-
tslib_1.__decorate([
|
|
48
|
-
(0, typeorm_1.ManyToOne)(type => auth_base_1.User),
|
|
49
|
-
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'The user participating in the session.' }),
|
|
50
|
-
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
51
|
-
], ChatSessionParticipant.prototype, "user", void 0);
|
|
52
|
-
tslib_1.__decorate([
|
|
53
|
-
(0, typeorm_1.RelationId)((p) => p.user),
|
|
54
|
-
tslib_1.__metadata("design:type", String)
|
|
55
|
-
], ChatSessionParticipant.prototype, "userId", void 0);
|
|
56
|
-
tslib_1.__decorate([
|
|
57
|
-
(0, typeorm_1.Column)({ type: 'varchar', length: 16, default: 'member' }),
|
|
58
|
-
(0, type_graphql_1.Field)({ description: 'Role of this participant: owner | member | viewer.' }),
|
|
59
|
-
tslib_1.__metadata("design:type", String)
|
|
60
|
-
], ChatSessionParticipant.prototype, "role", void 0);
|
|
61
|
-
tslib_1.__decorate([
|
|
62
|
-
(0, typeorm_1.Column)({ nullable: true }),
|
|
63
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Last seen / activity timestamp (presence indicator).' }),
|
|
64
|
-
tslib_1.__metadata("design:type", Date
|
|
65
|
-
/**
|
|
66
|
-
* 이 참여자가 **읽은 지점**. 세션의 마지막 활동 시각과 비교해 안 읽음을 판정한다.
|
|
67
|
-
*
|
|
68
|
-
* `lastSeenAt`(접속 표시)과 다른 개념이다 — 창을 열어 두고 화면을 안 볼 수 있고, 접속이 끊긴 뒤에도
|
|
69
|
-
* 읽은 지점은 남는다. 두 값을 섞어 쓰면 "봤는데 안 읽음" 또는 그 반대가 된다.
|
|
70
|
-
* nullable — 한 번도 읽지 않은 참여자(초대 직후)는 세션의 모든 활동이 안 읽음이다.
|
|
71
|
-
*/
|
|
72
|
-
)
|
|
73
|
-
], ChatSessionParticipant.prototype, "lastSeenAt", void 0);
|
|
74
|
-
tslib_1.__decorate([
|
|
75
|
-
(0, typeorm_1.Column)({ nullable: true }),
|
|
76
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Point up to which this participant has read the session. Distinct from lastSeenAt (presence): a window can be open without being read, and the read point survives disconnection. Null means nothing read yet.' }),
|
|
77
|
-
tslib_1.__metadata("design:type", Date
|
|
78
|
-
/**
|
|
79
|
-
* 이 사용자가 **자기 목록에서 숨긴 시각**. 숨김은 **나에게만** 적용된다 — 남의 목록·대화 내용은 그대로다.
|
|
80
|
-
*
|
|
81
|
-
* 왜 삭제와 나누는가: 협의는 여럿의 기록이므로 지우는 것은 **만든 사람**만 할 수 있다(되돌릴 수 없다).
|
|
82
|
-
* 그 권한이 없는 사람에게도 "내 목록을 정리할" 방법은 있어야 하고, 그것이 숨김이다.
|
|
83
|
-
*
|
|
84
|
-
* 숨긴 **뒤에 새 활동이 생기면 다시 나타난다** — 아직 참여자인 대화에서 조용히 잘려 나가는 것이
|
|
85
|
-
* 목록이 한 줄 늘어나는 것보다 나쁘다. 완전히 빠지려면 대화에서 나가야 한다(별개 기능).
|
|
86
|
-
* nullable — 값이 없으면 숨기지 않은 상태.
|
|
87
|
-
*/
|
|
88
|
-
)
|
|
89
|
-
], ChatSessionParticipant.prototype, "lastReadAt", void 0);
|
|
90
|
-
tslib_1.__decorate([
|
|
91
|
-
(0, typeorm_1.Column)({ nullable: true }),
|
|
92
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'When this user hid the session from their own list. Per-user only; the session and other participants are unaffected. Activity newer than this timestamp makes it reappear.' }),
|
|
93
|
-
tslib_1.__metadata("design:type", Date)
|
|
94
|
-
], ChatSessionParticipant.prototype, "hiddenAt", void 0);
|
|
95
|
-
tslib_1.__decorate([
|
|
96
|
-
(0, typeorm_1.ManyToOne)(type => auth_base_1.User),
|
|
97
|
-
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'User who created this participant record (typically session owner who invited).' }),
|
|
98
|
-
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
99
|
-
], ChatSessionParticipant.prototype, "creator", void 0);
|
|
100
|
-
tslib_1.__decorate([
|
|
101
|
-
(0, typeorm_1.RelationId)((p) => p.creator),
|
|
102
|
-
tslib_1.__metadata("design:type", String)
|
|
103
|
-
], ChatSessionParticipant.prototype, "creatorId", void 0);
|
|
104
|
-
tslib_1.__decorate([
|
|
105
|
-
(0, typeorm_1.ManyToOne)(type => auth_base_1.User),
|
|
106
|
-
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Last user to update this participant record (e.g., role change).' }),
|
|
107
|
-
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
108
|
-
], ChatSessionParticipant.prototype, "updater", void 0);
|
|
109
|
-
tslib_1.__decorate([
|
|
110
|
-
(0, typeorm_1.RelationId)((p) => p.updater),
|
|
111
|
-
tslib_1.__metadata("design:type", String)
|
|
112
|
-
], ChatSessionParticipant.prototype, "updaterId", void 0);
|
|
113
|
-
tslib_1.__decorate([
|
|
114
|
-
(0, typeorm_1.CreateDateColumn)(),
|
|
115
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Joined-at timestamp.' }),
|
|
116
|
-
tslib_1.__metadata("design:type", Date)
|
|
117
|
-
], ChatSessionParticipant.prototype, "createdAt", void 0);
|
|
118
|
-
tslib_1.__decorate([
|
|
119
|
-
(0, typeorm_1.UpdateDateColumn)(),
|
|
120
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Last update timestamp (role change / lastSeenAt bump).' }),
|
|
121
|
-
tslib_1.__metadata("design:type", Date)
|
|
122
|
-
], ChatSessionParticipant.prototype, "updatedAt", void 0);
|
|
123
|
-
tslib_1.__decorate([
|
|
124
|
-
(0, typeorm_1.DeleteDateColumn)(),
|
|
125
|
-
(0, type_graphql_1.Field)({ nullable: true, description: 'Soft delete (= left session) timestamp.' }),
|
|
126
|
-
tslib_1.__metadata("design:type", Date)
|
|
127
|
-
], ChatSessionParticipant.prototype, "deletedAt", void 0);
|
|
128
|
-
exports.ChatSessionParticipant = ChatSessionParticipant = tslib_1.__decorate([
|
|
129
|
-
(0, typeorm_1.Entity)('chat_session_participants'),
|
|
130
|
-
(0, typeorm_1.Index)('ix_chat_session_participant_0', ['domain', 'session', 'user'], {
|
|
131
|
-
unique: true,
|
|
132
|
-
where: '"deleted_at" IS NULL'
|
|
133
|
-
}),
|
|
134
|
-
(0, typeorm_1.Index)('ix_chat_session_participant_1', ['domain', 'user'], {
|
|
135
|
-
where: '"deleted_at" IS NULL'
|
|
136
|
-
}),
|
|
137
|
-
(0, type_graphql_1.ObjectType)({
|
|
138
|
-
description: 'Participant of a ChatSession — links a User to a session with a role. Foundation for multi-user chat / per-user filtering / member display.'
|
|
139
|
-
})
|
|
140
|
-
], ChatSessionParticipant);
|
|
141
|
-
//# sourceMappingURL=chat-session-participant.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat-session-participant.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/chat-session-participant.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSessionParticipant — 채팅 세션의 참여 사용자.\n *\n * 한 ChatSession 에 여러 사용자가 참여할 수 있고, 각자 role (owner / member / viewer 등)\n * 을 가짐. 다자간 채팅 / 권한 분화 / \"내 세션 목록\" / 멤버 표시 등의 기반.\n *\n * 현재 visibility 정책 (도메인 내 모두 공개) 은 그대로 유지 — 본 엔티티는 영속/추적\n * 데이터 만들고, \"참여자만 접근\" 같은 enforcement 는 정책 굳을 때 별도 phase 에서 도입.\n *\n * 자동 참여 vs 명시적 초대 정책도 미정 — 일단 세션 creator 만 자동 'owner' 로 등록.\n */\nimport {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nimport { ChatSession } from '../chat-session/chat-session.js'\n\n@Entity('chat_session_participants')\n@Index('ix_chat_session_participant_0', ['domain', 'session', 'user'], {\n unique: true,\n where: '\"deleted_at\" IS NULL'\n})\n@Index('ix_chat_session_participant_1', ['domain', 'user'], {\n where: '\"deleted_at\" IS NULL'\n})\n@ObjectType({\n description:\n 'Participant of a ChatSession — links a User to a session with a role. Foundation for multi-user chat / per-user filtering / member display.'\n})\nexport class ChatSessionParticipant {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique participant id.' })\n readonly id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Domain to which this participant belongs.' })\n domain?: Domain\n\n @RelationId((p: ChatSessionParticipant) => p.domain)\n domainId?: string\n\n @ManyToOne(type => ChatSession, { onDelete: 'CASCADE' })\n @Field(type => ChatSession, { nullable: true, description: 'The ChatSession this participation belongs to.' })\n session?: ChatSession\n\n @RelationId((p: ChatSessionParticipant) => p.session)\n sessionId?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'The user participating in the session.' })\n user?: User\n\n @RelationId((p: ChatSessionParticipant) => p.user)\n userId?: string\n\n /**\n * 참여자의 역할.\n * - 'owner': 세션 만든 사람. rename / delete 권한.\n * - 'member': 일반 참여자. 메시지 송수신.\n * - 'viewer': 읽기 전용 (미래 권한 정책 활성화 시).\n *\n * 시작은 'owner' / 'member' 둘로 충분. 더 세분화 필요해지면 enum 확장.\n */\n @Column({ type: 'varchar', length: 16, default: 'member' })\n @Field({ description: 'Role of this participant: owner | member | viewer.' })\n role!: string\n\n /** 마지막 활동 시각 — presence indicator. nullable. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Last seen / activity timestamp (presence indicator).' })\n lastSeenAt?: Date\n\n /**\n * 이 참여자가 **읽은 지점**. 세션의 마지막 활동 시각과 비교해 안 읽음을 판정한다.\n *\n * `lastSeenAt`(접속 표시)과 다른 개념이다 — 창을 열어 두고 화면을 안 볼 수 있고, 접속이 끊긴 뒤에도\n * 읽은 지점은 남는다. 두 값을 섞어 쓰면 \"봤는데 안 읽음\" 또는 그 반대가 된다.\n * nullable — 한 번도 읽지 않은 참여자(초대 직후)는 세션의 모든 활동이 안 읽음이다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Point up to which this participant has read the session. Distinct from lastSeenAt (presence): a window can be open without being read, and the read point survives disconnection. Null means nothing read yet.' })\n lastReadAt?: Date\n\n /**\n * 이 사용자가 **자기 목록에서 숨긴 시각**. 숨김은 **나에게만** 적용된다 — 남의 목록·대화 내용은 그대로다.\n *\n * 왜 삭제와 나누는가: 협의는 여럿의 기록이므로 지우는 것은 **만든 사람**만 할 수 있다(되돌릴 수 없다).\n * 그 권한이 없는 사람에게도 \"내 목록을 정리할\" 방법은 있어야 하고, 그것이 숨김이다.\n *\n * 숨긴 **뒤에 새 활동이 생기면 다시 나타난다** — 아직 참여자인 대화에서 조용히 잘려 나가는 것이\n * 목록이 한 줄 늘어나는 것보다 나쁘다. 완전히 빠지려면 대화에서 나가야 한다(별개 기능).\n * nullable — 값이 없으면 숨기지 않은 상태.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When this user hid the session from their own list. Per-user only; the session and other participants are unaffected. Activity newer than this timestamp makes it reappear.' })\n hiddenAt?: Date\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'User who created this participant record (typically session owner who invited).' })\n creator?: User\n\n @RelationId((p: ChatSessionParticipant) => p.creator)\n creatorId?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'Last user to update this participant record (e.g., role change).' })\n updater?: User\n\n @RelationId((p: ChatSessionParticipant) => p.updater)\n updaterId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Joined-at timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp (role change / lastSeenAt bump).' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft delete (= left session) timestamp.' })\n deletedAt?: Date\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.entities = exports.PRESENCE_TTL_MS = exports.isOnline = exports.ChatSessionParticipant = void 0;
|
|
4
|
-
const chat_session_participant_js_1 = require("./chat-session-participant.js");
|
|
5
|
-
Object.defineProperty(exports, "ChatSessionParticipant", { enumerable: true, get: function () { return chat_session_participant_js_1.ChatSessionParticipant; } });
|
|
6
|
-
var presence_js_1 = require("./presence.js");
|
|
7
|
-
Object.defineProperty(exports, "isOnline", { enumerable: true, get: function () { return presence_js_1.isOnline; } });
|
|
8
|
-
Object.defineProperty(exports, "PRESENCE_TTL_MS", { enumerable: true, get: function () { return presence_js_1.PRESENCE_TTL_MS; } });
|
|
9
|
-
exports.entities = [chat_session_participant_js_1.ChatSessionParticipant];
|
|
10
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/chat-session-participant/index.ts"],"names":[],"mappings":";;;AAAA,+EAAsE;AAE7D,uGAFA,oDAAsB,OAEA;AAC/B,6CAAyD;AAAhD,uGAAA,QAAQ,OAAA;AAAE,8GAAA,eAAe,OAAA;AAErB,QAAA,QAAQ,GAAG,CAAC,oDAAsB,CAAC,CAAA","sourcesContent":["import { ChatSessionParticipant } from './chat-session-participant.js'\n\nexport { ChatSessionParticipant }\nexport { isOnline, PRESENCE_TTL_MS } from './presence.js'\n\nexport const entities = [ChatSessionParticipant]\n"]}
|