@vibexnpm/talkx 7.1.0 → 7.2.0

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/README.md CHANGED
@@ -72,7 +72,7 @@ await client.connect(jwtToken, { enablePush: true });
72
72
  |---|---|
73
73
  | [getting-started.md](docs/getting-started.md) | **처음 사용한다면 여기부터.** 설치, API Key, 빠른 시작, 프로덕션 인증 플로우 |
74
74
  | [connection.md](docs/connection.md) | 연결 관리, 설정 옵션, 재연결 정책, JWT 토큰 lifecycle, 환경 설정, 상태 확인 |
75
- | [chat.md](docs/chat.md) | 채팅방 관리, 메시지 전송, 파일 업로드, 답글, 리액션, 핀, 타이핑, 채팅방 리스트 실시간 갱신, **AI 어시스턴트 페르소나 (멘션 응답)** |
75
+ | [chat.md](docs/chat.md) | 채팅방 관리, 메시지 전송, 파일 업로드, 답글, 리액션, 핀, 타이핑, 채팅방 리스트 실시간 갱신, **AI 어시스턴트 페르소나 (멘션 응답)**, **일정 제안 카드 (`scheduleCard`)** |
76
76
  | [push.md](docs/push.md) | **웹 푸시 알림.** 권한 lifecycle, 활성화 패턴 (자동 vs 사용자 액션), 디바이스 토글, 알림 클릭 라우팅 |
77
77
  | [webrtc.md](docs/webrtc.md) | 1:1 / 그룹 통화, 미디어 제어, 디바이스 관리, TURN 서버 |
78
78
  | [vote.md](docs/vote.md) | **투표.** 생성(멱등키 필수) · 투표/재투표 · 결과 마스킹 · 이미지 선택지 · 채팅 카드 렌더링 |
package/dist/index.d.ts CHANGED
@@ -772,6 +772,58 @@ export interface ChatMessage {
772
772
  * 마스킹이 호출자마다 다르게 계산되기 때문이다.</p>
773
773
  */
774
774
  voteCard?: VoteCard | null;
775
+ /**
776
+ * 일정 제안 카드 — PM 이 대화에서 일정을 «제안» 했거나 그 결과를 알리는 메시지의 payload.
777
+ *
778
+ * <p><b>모르면 그냥 텍스트로 그려라 — 그게 정상 동작이다.</b> {@code content} 에 같은 내용과 공개 범위 고지가
779
+ * 사람이 읽는 형태로 들어 있다. 반대로 카드를 그린다면 {@code content} 를 다시 그리지 마라.</p>
780
+ *
781
+ * <p>결과(등록됨·거절·확인 불가·취소·만료)는 원래 카드를 고치지 않고 {@code kind} 가 다른 <b>새 메시지</b>로 온다.
782
+ * 지금 승인할 수 있는지는 카드가 아니라 {@code GET /api/v1/calendar/proposals/{proposalId}} 의
783
+ * {@code approvable} 이 말한다(SDK 메서드 없음 — 다른 캘린더 API 처럼 REST 로 직접 부른다).</p>
784
+ */
785
+ scheduleCard?: ScheduleCard | null;
786
+ }
787
+
788
+ /**
789
+ * 일정 제안 카드 payload — 제안 하나에 «승인할까요?» 카드 한 장, 결과 카드는 최대 한 장이다.
790
+ *
791
+ * <p>값은 발행 시점 <b>스냅샷</b>이다. 결과는 원래 카드를 고치지 않고 {@code kind} 가 다른 새 메시지로 온다.</p>
792
+ */
793
+ export interface ScheduleCard {
794
+ /** 조회·승인·취소의 키. */
795
+ proposalId: string;
796
+ /**
797
+ * {@code 'PROPOSED'}(승인 대기) | {@code 'CREATED'} | {@code 'REJECTED'} | {@code 'UNKNOWN'} |
798
+ * {@code 'CANCELLED'} | {@code 'EXPIRED'}.
799
+ *
800
+ * <p>🔴 {@code 'PROPOSED'} 는 «등록됨» 이 아니다. 🔴 {@code 'UNKNOWN'} 은 «실패» 가 아니라 «등록됐는지 모른다» 다 —
801
+ * 재시도·다시 요청 버튼을 두지 않는다(만들어졌을 수 있어 다시 만들면 일정이 둘 된다).</p>
802
+ *
803
+ * <p>🔴 <b>모르는 값이 올 수 있다</b> — switch 의 default 는 텍스트({@code content}) 폴백으로 둔다.</p>
804
+ */
805
+ kind: 'PROPOSED' | 'CREATED' | 'REJECTED' | 'UNKNOWN' | 'CANCELLED' | 'EXPIRED' | (string & {});
806
+ /** 제목 스냅샷. 비어 있을 수 있다. */
807
+ title?: string | null;
808
+ /** 사람이 읽는 시각 — 서버가 <b>제안 당시 해석 타임존</b>으로 만든 문자열(끝에 존 ID). 다시 계산하지 않는다. */
809
+ whenText?: string | null;
810
+ /** 장소 스냅샷. 비어 있을 수 있다. */
811
+ location?: string | null;
812
+ /** 초대 대상 표시 이름. 비어 있어도 공개 범위는 방 전체다({@link ScheduleCard.visibilityNotice}). */
813
+ participantNames?: string[] | null;
814
+ /**
815
+ * 🔴 공개 범위 고지 — <b>참가자 수와 관계없이 항상</b> 온다. 카드를 그린다면 반드시 표시한다.
816
+ * 초대한 사람이 없어도 이 방 구성원 전원에게 보이는 일정이다.
817
+ */
818
+ visibilityNotice: string;
819
+ /**
820
+ * 거절 사유 <b>코드</b> — 🔴 {@code kind === 'REJECTED'} 일 때만 오고, 그때도 없을 수 있다.
821
+ *
822
+ * <p>문구 변환은 화면이 한다. 코드가 없거나 모르는 코드면 <b>일반 거절 문구</b>
823
+ * («일정을 등록하지 못했습니다») 를 보여주고 «다시 요청해 주세요» 를 붙인다. 상류 원문 메시지는 오지 않는다.
824
+ * 수동 입력 폼의 오류 안내(필드별 표시 등)를 쓰지 않는다 — 제안에는 고칠 폼이 없다.</p>
825
+ */
826
+ failureCode?: string;
775
827
  }
776
828
 
777
829
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibexnpm/talkx",
3
- "version": "7.1.0",
3
+ "version": "7.2.0",
4
4
  "type": "module",
5
5
  "description": "TalkFlow SDK - Chat & WebRTC unified client",
6
6
  "main": "dist/talkflow-sdk.umd.js",
@@ -0,0 +1,51 @@
1
+ /**
2
+ * 일정 제안 카드 타입 — 소비자 코드가 <b>실제로 컴파일되는지</b>.
3
+ *
4
+ * <p>jest 는 `.d.ts` 를 보지 않는다. 카드 렌더러가 쓰는 모양(모르는 kind 폴백 · REJECTED 에서만 읽는 사유 코드 ·
5
+ * 항상 있는 공개 범위 고지)이 선언과 맞는지 여기서 tsc 로 고정한다.</p>
6
+ *
7
+ * <p>실행: {@code npm run typecheck}</p>
8
+ */
9
+ import type { ChatMessage, ScheduleCard } from '../index';
10
+
11
+ declare const message: ChatMessage;
12
+
13
+ // 1) 메시지에는 없을 수 있다 — 일반 메시지는 필드가 부재.
14
+ const maybeCard: ScheduleCard | null | undefined = message.scheduleCard;
15
+
16
+ // 2) 공개 범위 고지는 항상 문자열이다 — 카드를 그리면 반드시 표시한다.
17
+ function notice(card: ScheduleCard): string {
18
+ return card.visibilityNotice;
19
+ }
20
+
21
+ // 3) kind 는 열린 문자열이다 — 알려진 값 분기 + default 텍스트 폴백이 성립해야 한다.
22
+ function headline(card: ScheduleCard, fallbackContent: string | null): string {
23
+ switch (card.kind) {
24
+ case 'PROPOSED': return '일정을 등록할까요?';
25
+ case 'CREATED': return '일정을 등록했습니다';
26
+ case 'REJECTED': return rejectedText(card.failureCode);
27
+ case 'UNKNOWN': return '등록됐는지 확인하지 못했습니다. 캘린더에서 확인해 주세요';
28
+ case 'CANCELLED': return '일정 제안을 취소했습니다';
29
+ case 'EXPIRED': return '만료되었습니다. 다시 요청해 주세요';
30
+ default: return fallbackContent ?? ''; // 모르는 kind — content 로 폴백
31
+ }
32
+ }
33
+
34
+ // 4) 사유 코드는 선택 필드다 — 없거나 모르는 코드는 일반 거절 문구.
35
+ function rejectedText(code: string | undefined): string {
36
+ const known: Record<string, string> = {
37
+ PARTICIPANT_LIMIT_EXCEEDED: '참여자가 너무 많아(최대 100명) 등록하지 못했습니다',
38
+ };
39
+ return (code !== undefined && known[code] !== undefined ? known[code] : '일정을 등록하지 못했습니다')
40
+ + '. 다시 요청해 주세요';
41
+ }
42
+
43
+ // 5) 선택 필드는 null 일 수 있다 — 그대로 비교·병합할 수 있어야 한다.
44
+ function names(card: ScheduleCard): string {
45
+ return (card.participantNames ?? []).join(', ') + (card.title ?? '') + (card.whenText ?? '') + (card.location ?? '');
46
+ }
47
+
48
+ // 6) 알 수 없는 kind 문자열도 받아들인다(구버전 호환).
49
+ const future: ScheduleCard = { proposalId: 'p-1', kind: 'SOMETHING_NEW', visibilityNotice: '이 방 구성원에게 공개되는 일정입니다' };
50
+
51
+ export { maybeCard, notice, headline, names, future };
package/types/index.d.ts CHANGED
@@ -772,6 +772,58 @@ export interface ChatMessage {
772
772
  * 마스킹이 호출자마다 다르게 계산되기 때문이다.</p>
773
773
  */
774
774
  voteCard?: VoteCard | null;
775
+ /**
776
+ * 일정 제안 카드 — PM 이 대화에서 일정을 «제안» 했거나 그 결과를 알리는 메시지의 payload.
777
+ *
778
+ * <p><b>모르면 그냥 텍스트로 그려라 — 그게 정상 동작이다.</b> {@code content} 에 같은 내용과 공개 범위 고지가
779
+ * 사람이 읽는 형태로 들어 있다. 반대로 카드를 그린다면 {@code content} 를 다시 그리지 마라.</p>
780
+ *
781
+ * <p>결과(등록됨·거절·확인 불가·취소·만료)는 원래 카드를 고치지 않고 {@code kind} 가 다른 <b>새 메시지</b>로 온다.
782
+ * 지금 승인할 수 있는지는 카드가 아니라 {@code GET /api/v1/calendar/proposals/{proposalId}} 의
783
+ * {@code approvable} 이 말한다(SDK 메서드 없음 — 다른 캘린더 API 처럼 REST 로 직접 부른다).</p>
784
+ */
785
+ scheduleCard?: ScheduleCard | null;
786
+ }
787
+
788
+ /**
789
+ * 일정 제안 카드 payload — 제안 하나에 «승인할까요?» 카드 한 장, 결과 카드는 최대 한 장이다.
790
+ *
791
+ * <p>값은 발행 시점 <b>스냅샷</b>이다. 결과는 원래 카드를 고치지 않고 {@code kind} 가 다른 새 메시지로 온다.</p>
792
+ */
793
+ export interface ScheduleCard {
794
+ /** 조회·승인·취소의 키. */
795
+ proposalId: string;
796
+ /**
797
+ * {@code 'PROPOSED'}(승인 대기) | {@code 'CREATED'} | {@code 'REJECTED'} | {@code 'UNKNOWN'} |
798
+ * {@code 'CANCELLED'} | {@code 'EXPIRED'}.
799
+ *
800
+ * <p>🔴 {@code 'PROPOSED'} 는 «등록됨» 이 아니다. 🔴 {@code 'UNKNOWN'} 은 «실패» 가 아니라 «등록됐는지 모른다» 다 —
801
+ * 재시도·다시 요청 버튼을 두지 않는다(만들어졌을 수 있어 다시 만들면 일정이 둘 된다).</p>
802
+ *
803
+ * <p>🔴 <b>모르는 값이 올 수 있다</b> — switch 의 default 는 텍스트({@code content}) 폴백으로 둔다.</p>
804
+ */
805
+ kind: 'PROPOSED' | 'CREATED' | 'REJECTED' | 'UNKNOWN' | 'CANCELLED' | 'EXPIRED' | (string & {});
806
+ /** 제목 스냅샷. 비어 있을 수 있다. */
807
+ title?: string | null;
808
+ /** 사람이 읽는 시각 — 서버가 <b>제안 당시 해석 타임존</b>으로 만든 문자열(끝에 존 ID). 다시 계산하지 않는다. */
809
+ whenText?: string | null;
810
+ /** 장소 스냅샷. 비어 있을 수 있다. */
811
+ location?: string | null;
812
+ /** 초대 대상 표시 이름. 비어 있어도 공개 범위는 방 전체다({@link ScheduleCard.visibilityNotice}). */
813
+ participantNames?: string[] | null;
814
+ /**
815
+ * 🔴 공개 범위 고지 — <b>참가자 수와 관계없이 항상</b> 온다. 카드를 그린다면 반드시 표시한다.
816
+ * 초대한 사람이 없어도 이 방 구성원 전원에게 보이는 일정이다.
817
+ */
818
+ visibilityNotice: string;
819
+ /**
820
+ * 거절 사유 <b>코드</b> — 🔴 {@code kind === 'REJECTED'} 일 때만 오고, 그때도 없을 수 있다.
821
+ *
822
+ * <p>문구 변환은 화면이 한다. 코드가 없거나 모르는 코드면 <b>일반 거절 문구</b>
823
+ * («일정을 등록하지 못했습니다») 를 보여주고 «다시 요청해 주세요» 를 붙인다. 상류 원문 메시지는 오지 않는다.
824
+ * 수동 입력 폼의 오류 안내(필드별 표시 등)를 쓰지 않는다 — 제안에는 고칠 폼이 없다.</p>
825
+ */
826
+ failureCode?: string;
775
827
  }
776
828
 
777
829
  /**