@tienne/gestalt 0.109.0 → 0.110.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/dist/package.json +1 -1
- package/dist/src/cli/commands/peer.d.ts +30 -0
- package/dist/src/cli/commands/peer.d.ts.map +1 -1
- package/dist/src/cli/commands/peer.js +159 -4
- package/dist/src/cli/commands/peer.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +48 -2
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/peer/daemon.d.ts +17 -5
- package/dist/src/peer/daemon.d.ts.map +1 -1
- package/dist/src/peer/daemon.js +124 -15
- package/dist/src/peer/daemon.js.map +1 -1
- package/dist/src/peer/feed.d.ts +103 -0
- package/dist/src/peer/feed.d.ts.map +1 -0
- package/dist/src/peer/feed.js +167 -0
- package/dist/src/peer/feed.js.map +1 -0
- package/dist/src/peer/index.d.ts +10 -0
- package/dist/src/peer/index.d.ts.map +1 -1
- package/dist/src/peer/index.js +5 -0
- package/dist/src/peer/index.js.map +1 -1
- package/dist/src/peer/keys.d.ts +26 -0
- package/dist/src/peer/keys.d.ts.map +1 -0
- package/dist/src/peer/keys.js +95 -0
- package/dist/src/peer/keys.js.map +1 -0
- package/dist/src/peer/lock.d.ts +32 -0
- package/dist/src/peer/lock.d.ts.map +1 -0
- package/dist/src/peer/lock.js +147 -0
- package/dist/src/peer/lock.js.map +1 -0
- package/dist/src/peer/mirror.d.ts +21 -0
- package/dist/src/peer/mirror.d.ts.map +1 -0
- package/dist/src/peer/mirror.js +68 -0
- package/dist/src/peer/mirror.js.map +1 -0
- package/dist/src/peer/network.d.ts +148 -0
- package/dist/src/peer/network.d.ts.map +1 -0
- package/dist/src/peer/network.js +809 -0
- package/dist/src/peer/network.js.map +1 -0
- package/dist/src/peer/protocol.d.ts +52 -1
- package/dist/src/peer/protocol.d.ts.map +1 -1
- package/dist/src/peer/protocol.js +1 -0
- package/dist/src/peer/protocol.js.map +1 -1
- package/dist/src/peer/relay.d.ts +70 -0
- package/dist/src/peer/relay.d.ts.map +1 -0
- package/dist/src/peer/relay.js +410 -0
- package/dist/src/peer/relay.js.map +1 -0
- package/dist/src/peer/roster.d.ts +89 -0
- package/dist/src/peer/roster.d.ts.map +1 -0
- package/dist/src/peer/roster.js +160 -0
- package/dist/src/peer/roster.js.map +1 -0
- package/dist/src/peer/seal.d.ts +37 -0
- package/dist/src/peer/seal.d.ts.map +1 -0
- package/dist/src/peer/seal.js +115 -0
- package/dist/src/peer/seal.js.map +1 -0
- package/dist/src/peer/share.d.ts +4 -86
- package/dist/src/peer/share.d.ts.map +1 -1
- package/dist/src/peer/share.js +6 -140
- package/dist/src/peer/share.js.map +1 -1
- package/dist/src/peer/state.d.ts +35 -4
- package/dist/src/peer/state.d.ts.map +1 -1
- package/dist/src/peer/state.js +65 -3
- package/dist/src/peer/state.js.map +1 -1
- package/dist/src/peer/transport.d.ts +89 -0
- package/dist/src/peer/transport.d.ts.map +1 -0
- package/dist/src/peer/transport.js +345 -0
- package/dist/src/peer/transport.js.map +1 -0
- package/dist/src/peer/viewer-html.d.ts.map +1 -1
- package/dist/src/peer/viewer-html.js +10 -2
- package/dist/src/peer/viewer-html.js.map +1 -1
- package/dist/src/peer/viewer.d.ts +2 -2
- package/dist/src/peer/viewer.d.ts.map +1 -1
- package/dist/src/peer/viewer.js.map +1 -1
- package/dist/src/peer/wire.d.ts +90 -0
- package/dist/src/peer/wire.d.ts.map +1 -0
- package/dist/src/peer/wire.js +10 -0
- package/dist/src/peer/wire.js.map +1 -0
- package/dist/src/peer/ws.d.ts +47 -0
- package/dist/src/peer/ws.d.ts.map +1 -0
- package/dist/src/peer/ws.js +308 -0
- package/dist/src/peer/ws.js.map +1 -0
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
package/dist/src/peer/share.js
CHANGED
|
@@ -1,53 +1,27 @@
|
|
|
1
1
|
import { TranscriptTail } from './tail.js';
|
|
2
2
|
import { TranscriptTransformer } from './transform.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
* 새 뷰어에게 다시 보낼 앞부분의 상한. 넘으면 오래된 것부터 버린다. 공유는 최대 7일
|
|
6
|
-
* 열려 있고 도구 출력이 크면 events가 끝없이 는다.
|
|
7
|
-
*/
|
|
8
|
-
export const DEFAULT_MAX_BACKLOG_BYTES = 32 * 1024 * 1024;
|
|
3
|
+
import { ShareFeed } from './feed.js';
|
|
4
|
+
export { DEFAULT_MAX_BACKLOG_BYTES } from './feed.js';
|
|
9
5
|
/**
|
|
10
6
|
* 공유 하나. 대화 기록을 따라 읽어 바꾼 이벤트를 메모리에 쌓고 붙은 뷰어에 흘린다.
|
|
11
7
|
*
|
|
12
8
|
* 바꾼 결과만 메모리에 들고 원문 줄은 들지 않는다. 디스크에는 아무것도 안 쓴다.
|
|
13
9
|
* 처음 붙는 뷰어가 앞부분을 받아야 해서 바꾼 이벤트를 직렬화한 글자로 상한까지 남긴다.
|
|
14
|
-
*
|
|
15
|
-
* seq는 공유가 연 뒤로 나온 이벤트의 번호다. 앞부분을 버려도 번호는 안 당긴다.
|
|
16
|
-
* 배열 위치로 매기면 버린 만큼 번호가 밀려 Last-Event-ID로 이어 받을 때 겹치거나 빠진다.
|
|
17
10
|
*/
|
|
18
|
-
export class ShareStream {
|
|
19
|
-
id;
|
|
11
|
+
export class ShareStream extends ShareFeed {
|
|
20
12
|
transcriptPath;
|
|
21
13
|
tools;
|
|
22
14
|
tail;
|
|
23
15
|
transformer;
|
|
24
|
-
/**
|
|
25
|
-
* `events[head]`부터가 살아 있다. 앞에서 하나씩 shift하면 큰 배열에서 매번 다 옮긴다.
|
|
26
|
-
* head 앞 칸은 버릴 때 비워 둔다. 압축은 head가 1024를 넘어야 돌아서 칸에 참조를
|
|
27
|
-
* 남기면 버린 이벤트를 GC가 못 가져간다.
|
|
28
|
-
*/
|
|
29
|
-
events = [];
|
|
30
|
-
head = 0;
|
|
31
|
-
/** `events[0]` 앞에서 잘라 낸 이벤트 수. `events[i]`의 seq는 `base + i + 1`이다 */
|
|
32
|
-
base = 0;
|
|
33
|
-
backlogBytes = 0;
|
|
34
|
-
maxBacklogBytes;
|
|
35
|
-
listeners = new Set();
|
|
36
|
-
status = 'live';
|
|
37
16
|
title;
|
|
38
17
|
lastUnknown = 0;
|
|
39
|
-
closedReason;
|
|
40
18
|
constructor(options) {
|
|
41
|
-
|
|
19
|
+
super(options.id, options.maxBacklogBytes);
|
|
42
20
|
this.transcriptPath = options.transcriptPath;
|
|
43
21
|
this.tools = options.tools;
|
|
44
|
-
this.maxBacklogBytes = options.maxBacklogBytes ?? DEFAULT_MAX_BACKLOG_BYTES;
|
|
45
22
|
this.tail = new TranscriptTail(options.transcriptPath, options.tail);
|
|
46
23
|
this.transformer = new TranscriptTransformer({ tools: options.tools, home: options.home });
|
|
47
24
|
}
|
|
48
|
-
get currentStatus() {
|
|
49
|
-
return this.status;
|
|
50
|
-
}
|
|
51
25
|
get unknownLines() {
|
|
52
26
|
return this.transformer.unknownLines;
|
|
53
27
|
}
|
|
@@ -63,25 +37,12 @@ export class ShareStream {
|
|
|
63
37
|
get sessionTitle() {
|
|
64
38
|
return this.title;
|
|
65
39
|
}
|
|
66
|
-
get eventCount() {
|
|
67
|
-
return this.base + this.events.length;
|
|
68
|
-
}
|
|
69
|
-
/** 상한에 밀려 버린 이벤트 수 */
|
|
70
|
-
get droppedEvents() {
|
|
71
|
-
return this.base + this.head;
|
|
72
|
-
}
|
|
73
|
-
get viewerCount() {
|
|
74
|
-
return this.listeners.size;
|
|
75
|
-
}
|
|
76
|
-
get isClosed() {
|
|
77
|
-
return this.closedReason !== undefined;
|
|
78
|
-
}
|
|
79
40
|
/**
|
|
80
41
|
* 새로 쓰인 줄을 읽어 흘린다. 데몬이 주기적으로 부른다.
|
|
81
42
|
* 모르는 줄 수가 늘었으면 true — 데몬이 감사 로그에 버전을 남길 때 쓴다.
|
|
82
43
|
*/
|
|
83
44
|
poll() {
|
|
84
|
-
if (this.
|
|
45
|
+
if (this.isClosed || this.status === 'truncated') {
|
|
85
46
|
return { unknownGrew: false };
|
|
86
47
|
}
|
|
87
48
|
const { lines, status } = this.tail.read();
|
|
@@ -90,11 +51,7 @@ export class ShareStream {
|
|
|
90
51
|
for (const event of this.transformer.push(line)) {
|
|
91
52
|
if (event.kind === 'title')
|
|
92
53
|
this.title = event.text;
|
|
93
|
-
|
|
94
|
-
const bytes = Buffer.byteLength(json);
|
|
95
|
-
this.events.push({ json, bytes });
|
|
96
|
-
this.backlogBytes += bytes;
|
|
97
|
-
this.emit({ type: 'event', seq: this.eventCount, json });
|
|
54
|
+
this.pushEvent(JSON.stringify(event));
|
|
98
55
|
}
|
|
99
56
|
}
|
|
100
57
|
this.trim();
|
|
@@ -106,97 +63,6 @@ export class ShareStream {
|
|
|
106
63
|
}
|
|
107
64
|
return { unknownGrew };
|
|
108
65
|
}
|
|
109
|
-
/**
|
|
110
|
-
* 쌓인 것 중 `afterSeq` 뒤를 `maxBytes`쯤까지 꺼낸다. 이벤트 하나가 상한보다 커도 하나는
|
|
111
|
-
* 꺼낸다. 뷰어가 소켓이 비는 만큼씩 앞부분을 보내려고 쓴다. 한 번에 다 넘기면 안 읽는
|
|
112
|
-
* 뷰어마다 앞부분 전체가 소켓 버퍼에 쌓인다.
|
|
113
|
-
*/
|
|
114
|
-
backlogAfter(afterSeq, maxBytes) {
|
|
115
|
-
if (this.closedReason !== undefined)
|
|
116
|
-
return { dropped: 0, items: [] };
|
|
117
|
-
const droppedTotal = this.droppedEvents;
|
|
118
|
-
const after = Math.max(0, afterSeq);
|
|
119
|
-
const items = [];
|
|
120
|
-
let bytes = 0;
|
|
121
|
-
for (let i = Math.max(after, droppedTotal) - this.base; i < this.events.length; i++) {
|
|
122
|
-
const held = this.events[i];
|
|
123
|
-
if (items.length > 0 && bytes + held.bytes > maxBytes)
|
|
124
|
-
break;
|
|
125
|
-
items.push({ seq: this.base + i + 1, json: held.json });
|
|
126
|
-
bytes += held.bytes;
|
|
127
|
-
}
|
|
128
|
-
return { dropped: after < droppedTotal ? droppedTotal - after : 0, items };
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* 뷰어를 붙인다. 지금 상태와 `afterSeq` 뒤 앞부분을 한 번에 보내고 이후는 생기는 대로.
|
|
132
|
-
* 떼어내는 함수를 돌려준다. 앞부분이 큰 뷰어는 backlogAfter로 먼저 따라잡은 뒤 이벤트
|
|
133
|
-
* 루프로 돌아가기 전에 바로 붙어야 사이에 poll이 끼어 이벤트가 빠지지 않는다.
|
|
134
|
-
*/
|
|
135
|
-
subscribe(listener, afterSeq = 0) {
|
|
136
|
-
listener({ type: 'state', status: this.status });
|
|
137
|
-
listener({ type: 'stats', unknownLines: this.transformer.unknownLines });
|
|
138
|
-
const { dropped, items } = this.backlogAfter(afterSeq, Infinity);
|
|
139
|
-
if (dropped > 0)
|
|
140
|
-
listener({ type: 'trimmed', dropped });
|
|
141
|
-
for (const item of items)
|
|
142
|
-
listener({ type: 'event', ...item });
|
|
143
|
-
if (this.closedReason !== undefined) {
|
|
144
|
-
// close가 events를 비워도 base를 늘려 두므로 eventCount는 그때까지 나온 전체 개수다
|
|
145
|
-
listener({
|
|
146
|
-
type: 'closed',
|
|
147
|
-
reason: this.closedReason,
|
|
148
|
-
missed: Math.max(0, this.eventCount - afterSeq),
|
|
149
|
-
});
|
|
150
|
-
return () => { };
|
|
151
|
-
}
|
|
152
|
-
this.listeners.add(listener);
|
|
153
|
-
return () => {
|
|
154
|
-
this.listeners.delete(listener);
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
close(reason) {
|
|
158
|
-
if (this.closedReason !== undefined)
|
|
159
|
-
return;
|
|
160
|
-
this.closedReason = reason;
|
|
161
|
-
this.emit({ type: 'closed', reason });
|
|
162
|
-
this.listeners.clear();
|
|
163
|
-
// 종료된 공유의 내용을 메모리에 붙잡아 둘 이유가 없다
|
|
164
|
-
this.base += this.events.length;
|
|
165
|
-
this.events = [];
|
|
166
|
-
this.head = 0;
|
|
167
|
-
this.backlogBytes = 0;
|
|
168
|
-
}
|
|
169
|
-
/** 가장 최근 이벤트 하나는 상한을 넘어도 남긴다. 다 버리면 새 뷰어가 지금 상태를 못 본다 */
|
|
170
|
-
trim() {
|
|
171
|
-
while (this.backlogBytes > this.maxBacklogBytes && this.events.length - this.head > 1) {
|
|
172
|
-
this.backlogBytes -= this.events[this.head].bytes;
|
|
173
|
-
this.events[this.head] = undefined;
|
|
174
|
-
this.head++;
|
|
175
|
-
}
|
|
176
|
-
if (this.head > 1024 && this.head * 2 > this.events.length) {
|
|
177
|
-
this.base += this.head;
|
|
178
|
-
this.events = this.events.slice(this.head);
|
|
179
|
-
this.head = 0;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
setStatus(next) {
|
|
183
|
-
if (next === this.status)
|
|
184
|
-
return;
|
|
185
|
-
this.status = next;
|
|
186
|
-
this.emit({ type: 'state', status: next });
|
|
187
|
-
}
|
|
188
|
-
emit(frame) {
|
|
189
|
-
for (const listener of [...this.listeners]) {
|
|
190
|
-
try {
|
|
191
|
-
listener(frame);
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
// 뷰어 하나가 끊겨 쓰기에 실패해도 다른 뷰어와 데몬은 계속 돈다
|
|
195
|
-
this.listeners.delete(listener);
|
|
196
|
-
process.stderr.write(`[peer] viewer listener failed: ${errMessage(err)}\n`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
66
|
}
|
|
201
67
|
function toShareStatus(status) {
|
|
202
68
|
return status === 'ok' ? 'live' : status;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../../src/peer/share.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../../src/peer/share.ts"],"names":[],"mappings":"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"}
|
package/dist/src/peer/state.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ToolsLevel } from './redact.js';
|
|
2
|
+
import type { SignedRoster } from './roster.js';
|
|
2
3
|
export type ShareCloseReason = 'unshare' | 'expired' | 'daemon_stop' | 'daemon_restart' | 'error';
|
|
3
4
|
export interface ShareRow {
|
|
4
5
|
id: string;
|
|
@@ -10,7 +11,24 @@ export interface ShareRow {
|
|
|
10
11
|
closedAt: number | null;
|
|
11
12
|
closeReason: string | null;
|
|
12
13
|
}
|
|
13
|
-
export type AuditAction = 'share_open' | 'share_close' | 'viewer_connect' | 'viewer_disconnect' | 'unknown_lines';
|
|
14
|
+
export type AuditAction = 'share_open' | 'share_close' | 'viewer_connect' | 'viewer_disconnect' | 'unknown_lines' | 'team_init' | 'team_join' | 'invite_create' | 'member_join' | 'member_remove' | 'roster_accept' | 'roster_reject' | 'remote_watch' | 'remote_watch_end' | 'watch_open' | 'watch_close';
|
|
15
|
+
/** 이 기기가 든 팀. 한 기기는 팀 하나에만 든다 */
|
|
16
|
+
export interface TeamConfig {
|
|
17
|
+
team: string;
|
|
18
|
+
relay: string;
|
|
19
|
+
person: string;
|
|
20
|
+
/** 명단을 하나도 못 들고 있을 때 믿을 관리자 키. 팀을 만든 기기면 자기 자신이다 */
|
|
21
|
+
anchor: string;
|
|
22
|
+
}
|
|
23
|
+
export interface InviteRow {
|
|
24
|
+
id: string;
|
|
25
|
+
secret: string;
|
|
26
|
+
person: string;
|
|
27
|
+
createdAt: number;
|
|
28
|
+
expiresAt: number;
|
|
29
|
+
usedAt: number | null;
|
|
30
|
+
usedBy: string | null;
|
|
31
|
+
}
|
|
14
32
|
export interface AuditRow {
|
|
15
33
|
at: number;
|
|
16
34
|
shareId: string | null;
|
|
@@ -18,9 +36,12 @@ export interface AuditRow {
|
|
|
18
36
|
detail: string | null;
|
|
19
37
|
}
|
|
20
38
|
/**
|
|
21
|
-
* 공유
|
|
22
|
-
* 숫자와 이름만 남긴다. 공유
|
|
23
|
-
* 종료된 걸로 치고 새로 연다.
|
|
39
|
+
* 공유 목록, 팀 설정과 명단, 초대, 감사 로그. 대화 내용은 한 글자도 여기 안 들어온다 —
|
|
40
|
+
* 줄 수나 버전 같은 숫자와 이름만 남긴다. 공유 토큰과 공유 키도 저장하지 않는다. 데몬이
|
|
41
|
+
* 다시 뜨면 이전 공유는 종료된 걸로 치고 새로 연다.
|
|
42
|
+
*
|
|
43
|
+
* 초대 비밀은 저장한다. 관리자 데몬이 나중에 온 join 요청의 증명을 맞춰 봐야 해서다.
|
|
44
|
+
* 파일은 0600이고 쓰고 나면 used_at이 찬다.
|
|
24
45
|
*/
|
|
25
46
|
export declare class PeerState {
|
|
26
47
|
private db;
|
|
@@ -30,6 +51,16 @@ export declare class PeerState {
|
|
|
30
51
|
/** 데몬이 죽어서 종료 기록 없이 남은 공유를 종료한다. 종료한 id 목록을 돌려준다 */
|
|
31
52
|
closeDangling(reason: ShareCloseReason, at?: number): string[];
|
|
32
53
|
getShare(id: string): ShareRow | undefined;
|
|
54
|
+
getTeam(): TeamConfig | null;
|
|
55
|
+
setTeam(team: TeamConfig): void;
|
|
56
|
+
/** 받은 명단 중 가장 새것. 받을지는 부르는 쪽이 checkRosterUpdate로 정한 뒤다 */
|
|
57
|
+
getRoster(): SignedRoster | null;
|
|
58
|
+
setRoster(roster: SignedRoster): void;
|
|
59
|
+
insertInvite(row: Omit<InviteRow, 'usedAt' | 'usedBy'>): void;
|
|
60
|
+
getInvite(id: string): InviteRow | undefined;
|
|
61
|
+
useInvite(id: string, machineKey: string, at?: number): void;
|
|
62
|
+
private getJson;
|
|
63
|
+
private setJson;
|
|
33
64
|
audit(action: AuditAction, shareId: string | null, detail?: string, at?: number): void;
|
|
34
65
|
auditLog(shareId?: string): AuditRow[];
|
|
35
66
|
close(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/peer/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/peer/state.ts"],"names":[],"mappings":"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"}
|
package/dist/src/peer/state.js
CHANGED
|
@@ -11,9 +11,12 @@ function loadSqlite() {
|
|
|
11
11
|
throw new Error('better-sqlite3 did not export a Database constructor');
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* 공유
|
|
15
|
-
* 숫자와 이름만 남긴다. 공유
|
|
16
|
-
* 종료된 걸로 치고 새로 연다.
|
|
14
|
+
* 공유 목록, 팀 설정과 명단, 초대, 감사 로그. 대화 내용은 한 글자도 여기 안 들어온다 —
|
|
15
|
+
* 줄 수나 버전 같은 숫자와 이름만 남긴다. 공유 토큰과 공유 키도 저장하지 않는다. 데몬이
|
|
16
|
+
* 다시 뜨면 이전 공유는 종료된 걸로 치고 새로 연다.
|
|
17
|
+
*
|
|
18
|
+
* 초대 비밀은 저장한다. 관리자 데몬이 나중에 온 join 요청의 증명을 맞춰 봐야 해서다.
|
|
19
|
+
* 파일은 0600이고 쓰고 나면 used_at이 찬다.
|
|
17
20
|
*/
|
|
18
21
|
export class PeerState {
|
|
19
22
|
db;
|
|
@@ -38,6 +41,19 @@ export class PeerState {
|
|
|
38
41
|
closed_at INTEGER,
|
|
39
42
|
close_reason TEXT
|
|
40
43
|
);
|
|
44
|
+
CREATE TABLE IF NOT EXISTS kv (
|
|
45
|
+
key TEXT PRIMARY KEY,
|
|
46
|
+
value TEXT NOT NULL
|
|
47
|
+
);
|
|
48
|
+
CREATE TABLE IF NOT EXISTS invites (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
secret TEXT NOT NULL,
|
|
51
|
+
person TEXT NOT NULL,
|
|
52
|
+
created_at INTEGER NOT NULL,
|
|
53
|
+
expires_at INTEGER NOT NULL,
|
|
54
|
+
used_at INTEGER,
|
|
55
|
+
used_by TEXT
|
|
56
|
+
);
|
|
41
57
|
CREATE TABLE IF NOT EXISTS audit (
|
|
42
58
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43
59
|
at INTEGER NOT NULL,
|
|
@@ -69,6 +85,52 @@ export class PeerState {
|
|
|
69
85
|
const r = this.db.prepare(`SELECT * FROM shares WHERE id = ?`).get(id);
|
|
70
86
|
return r ? toShare(r) : undefined;
|
|
71
87
|
}
|
|
88
|
+
getTeam() {
|
|
89
|
+
return this.getJson('team');
|
|
90
|
+
}
|
|
91
|
+
setTeam(team) {
|
|
92
|
+
this.setJson('team', team);
|
|
93
|
+
}
|
|
94
|
+
/** 받은 명단 중 가장 새것. 받을지는 부르는 쪽이 checkRosterUpdate로 정한 뒤다 */
|
|
95
|
+
getRoster() {
|
|
96
|
+
return this.getJson('roster');
|
|
97
|
+
}
|
|
98
|
+
setRoster(roster) {
|
|
99
|
+
this.setJson('roster', roster);
|
|
100
|
+
}
|
|
101
|
+
insertInvite(row) {
|
|
102
|
+
this.db
|
|
103
|
+
.prepare(`INSERT INTO invites (id, secret, person, created_at, expires_at) VALUES (?, ?, ?, ?, ?)`)
|
|
104
|
+
.run(row.id, row.secret, row.person, row.createdAt, row.expiresAt);
|
|
105
|
+
}
|
|
106
|
+
getInvite(id) {
|
|
107
|
+
const r = this.db.prepare(`SELECT * FROM invites WHERE id = ?`).get(id);
|
|
108
|
+
if (!r)
|
|
109
|
+
return undefined;
|
|
110
|
+
return {
|
|
111
|
+
id: r.id,
|
|
112
|
+
secret: r.secret,
|
|
113
|
+
person: r.person,
|
|
114
|
+
createdAt: r.created_at,
|
|
115
|
+
expiresAt: r.expires_at,
|
|
116
|
+
usedAt: r.used_at,
|
|
117
|
+
usedBy: r.used_by,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
useInvite(id, machineKey, at = Date.now()) {
|
|
121
|
+
this.db
|
|
122
|
+
.prepare(`UPDATE invites SET used_at = ?, used_by = ? WHERE id = ? AND used_at IS NULL`)
|
|
123
|
+
.run(at, machineKey, id);
|
|
124
|
+
}
|
|
125
|
+
getJson(key) {
|
|
126
|
+
const r = this.db.prepare(`SELECT value FROM kv WHERE key = ?`).get(key);
|
|
127
|
+
return r ? JSON.parse(r.value) : null;
|
|
128
|
+
}
|
|
129
|
+
setJson(key, value) {
|
|
130
|
+
this.db
|
|
131
|
+
.prepare(`INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`)
|
|
132
|
+
.run(key, JSON.stringify(value));
|
|
133
|
+
}
|
|
72
134
|
audit(action, shareId, detail, at = Date.now()) {
|
|
73
135
|
this.db
|
|
74
136
|
.prepare(`INSERT INTO audit (at, share_id, action, detail) VALUES (?, ?, ?, ?)`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/peer/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/peer/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { MachineKey } from './keys.js';
|
|
3
|
+
import type { SignedRoster } from './roster.js';
|
|
4
|
+
import type { HelloMode } from './wire.js';
|
|
5
|
+
/**
|
|
6
|
+
* 데몬끼리 봉인한 바이트를 주고받는 통로. 1차 구현은 RelayTransport 하나다.
|
|
7
|
+
* 나중에 P2P 통로를 더할 때 같은 모양을 맞춘다.
|
|
8
|
+
*/
|
|
9
|
+
export interface PeerTransport {
|
|
10
|
+
connect(roster: SignedRoster | null): Promise<void>;
|
|
11
|
+
/** 릴레이가 받는 기기에게 넘겼으면 delivered. PR 2 릴레이는 쌓지 않아서 queued는 아직 안 나온다 */
|
|
12
|
+
send(to: string, sealed: Uint8Array): Promise<'queued' | 'delivered'>;
|
|
13
|
+
onReceive(handler: (from: string, sealed: Uint8Array) => void): void;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export type TransportState = 'idle' | 'connecting' | 'online' | 'offline' | 'removed' | 'closed';
|
|
17
|
+
export interface RelayTransportOptions {
|
|
18
|
+
url: string;
|
|
19
|
+
team: string;
|
|
20
|
+
key: MachineKey;
|
|
21
|
+
mode?: HelloMode;
|
|
22
|
+
/** 끊기면 다시 붙는다. join 모드는 기본 끔 */
|
|
23
|
+
reconnect?: boolean;
|
|
24
|
+
minBackoffMs?: number;
|
|
25
|
+
maxBackoffMs?: number;
|
|
26
|
+
ackTimeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare class RelaySendError extends Error {
|
|
29
|
+
readonly reason: string;
|
|
30
|
+
constructor(reason: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 릴레이 접속 하나. 이벤트:
|
|
34
|
+
* - `state`(TransportState)
|
|
35
|
+
* - `welcome`(roster, online) — member로 붙었다. 다시 붙을 때마다 온다
|
|
36
|
+
* - `roster`(SignedRoster) — 릴레이가 새 명단을 돌렸다. 받을지는 부른 쪽이 다시 확인한다
|
|
37
|
+
* - `presence`(key, online)
|
|
38
|
+
* - `join`(from, sealed) — 관리자에게 온 join 요청
|
|
39
|
+
* - `relay-error`(code, message)
|
|
40
|
+
*/
|
|
41
|
+
export declare class RelayTransport extends EventEmitter implements PeerTransport {
|
|
42
|
+
private readonly options;
|
|
43
|
+
private ws;
|
|
44
|
+
private roster;
|
|
45
|
+
private status;
|
|
46
|
+
private nextId;
|
|
47
|
+
private acks;
|
|
48
|
+
private resolves;
|
|
49
|
+
private receivers;
|
|
50
|
+
private backoff;
|
|
51
|
+
private retry;
|
|
52
|
+
private announced;
|
|
53
|
+
constructor(options: RelayTransportOptions);
|
|
54
|
+
get state(): TransportState;
|
|
55
|
+
get bufferedAmount(): number;
|
|
56
|
+
/** 다음 hello에 들고 갈 명단 */
|
|
57
|
+
setRoster(roster: SignedRoster | null): void;
|
|
58
|
+
/**
|
|
59
|
+
* 처음 붙는다. member면 welcome, join 모드면 pending까지 기다린다. 첫 시도가 실패하면
|
|
60
|
+
* 던지고 reconnect가 켜져 있으면 뒤에서 계속 다시 붙는다.
|
|
61
|
+
*/
|
|
62
|
+
connect(roster: SignedRoster | null): Promise<void>;
|
|
63
|
+
onReceive(handler: (from: string, sealed: Uint8Array) => void): void;
|
|
64
|
+
send(to: string, sealed: Uint8Array): Promise<'queued' | 'delivered'>;
|
|
65
|
+
/**
|
|
66
|
+
* 답을 안 기다리고 보낸다. 공유 스트림 프레임처럼 자주 가는 것에 쓴다. 릴레이도 ack를
|
|
67
|
+
* 안 돌려준다. 받는 쪽이 없으면 조용히 버려진다.
|
|
68
|
+
*/
|
|
69
|
+
post(to: string, sealed: Uint8Array): boolean;
|
|
70
|
+
/** 공유 id를 연 기기를 릴레이에 묻는다 */
|
|
71
|
+
resolveShare(share: string, timeoutMs?: number): Promise<string | null>;
|
|
72
|
+
/** 지금 연 공유 id 전부를 알린다. 다시 붙을 때도 같은 목록을 다시 보낸다 */
|
|
73
|
+
announce(shares: string[]): void;
|
|
74
|
+
publishRoster(roster: SignedRoster): void;
|
|
75
|
+
sendJoin(to: string, sealed: Uint8Array): boolean;
|
|
76
|
+
close(): Promise<void>;
|
|
77
|
+
private attempt;
|
|
78
|
+
private lost;
|
|
79
|
+
/**
|
|
80
|
+
* 릴레이가 보낸 프레임. 릴레이도 믿지 않는 쪽이라 꼴이 틀린 프레임은 버린다. 여기서
|
|
81
|
+
* 던지면 소켓 data 핸들러 밖으로 나가 데몬이 죽는다.
|
|
82
|
+
*/
|
|
83
|
+
private onMessage;
|
|
84
|
+
private dispatch;
|
|
85
|
+
private write;
|
|
86
|
+
private failPending;
|
|
87
|
+
private setState;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/peer/transport.ts"],"names":[],"mappings":"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"}
|