@claudetree/core 0.1.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/LICENSE +21 -0
- package/dist/application/SessionManager.d.ts +18 -0
- package/dist/application/SessionManager.d.ts.map +1 -0
- package/dist/application/SessionManager.js +86 -0
- package/dist/application/SessionManager.js.map +1 -0
- package/dist/application/WorktreeSyncService.d.ts +17 -0
- package/dist/application/WorktreeSyncService.d.ts.map +1 -0
- package/dist/application/WorktreeSyncService.js +63 -0
- package/dist/application/WorktreeSyncService.js.map +1 -0
- package/dist/application/index.d.ts +3 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +3 -0
- package/dist/application/index.js.map +1 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +2 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/repositories/ICodeReviewRepository.d.ts +7 -0
- package/dist/domain/repositories/ICodeReviewRepository.d.ts.map +1 -0
- package/dist/domain/repositories/ICodeReviewRepository.js +2 -0
- package/dist/domain/repositories/ICodeReviewRepository.js.map +1 -0
- package/dist/domain/repositories/IEventRepository.d.ts +8 -0
- package/dist/domain/repositories/IEventRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IEventRepository.js +2 -0
- package/dist/domain/repositories/IEventRepository.js.map +1 -0
- package/dist/domain/repositories/ISessionRepository.d.ts +31 -0
- package/dist/domain/repositories/ISessionRepository.d.ts.map +1 -0
- package/dist/domain/repositories/ISessionRepository.js +2 -0
- package/dist/domain/repositories/ISessionRepository.js.map +1 -0
- package/dist/domain/repositories/IToolApprovalRepository.d.ts +8 -0
- package/dist/domain/repositories/IToolApprovalRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IToolApprovalRepository.js +2 -0
- package/dist/domain/repositories/IToolApprovalRepository.js.map +1 -0
- package/dist/domain/repositories/IWorktreeRepository.d.ts +8 -0
- package/dist/domain/repositories/IWorktreeRepository.d.ts.map +1 -0
- package/dist/domain/repositories/IWorktreeRepository.js +2 -0
- package/dist/domain/repositories/IWorktreeRepository.js.map +1 -0
- package/dist/domain/repositories/index.d.ts +6 -0
- package/dist/domain/repositories/index.d.ts.map +1 -0
- package/dist/domain/repositories/index.js +2 -0
- package/dist/domain/repositories/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.d.ts +17 -0
- package/dist/infra/claude/ClaudeSessionAdapter.d.ts.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.js +162 -0
- package/dist/infra/claude/ClaudeSessionAdapter.js.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.d.ts +2 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.d.ts.map +1 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.js +122 -0
- package/dist/infra/claude/ClaudeSessionAdapter.test.js.map +1 -0
- package/dist/infra/claude/index.d.ts +2 -0
- package/dist/infra/claude/index.d.ts.map +1 -0
- package/dist/infra/claude/index.js +2 -0
- package/dist/infra/claude/index.js.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.d.ts +14 -0
- package/dist/infra/git/GitWorktreeAdapter.d.ts.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.js +74 -0
- package/dist/infra/git/GitWorktreeAdapter.js.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.test.d.ts +2 -0
- package/dist/infra/git/GitWorktreeAdapter.test.d.ts.map +1 -0
- package/dist/infra/git/GitWorktreeAdapter.test.js +104 -0
- package/dist/infra/git/GitWorktreeAdapter.test.js.map +1 -0
- package/dist/infra/git/index.d.ts +2 -0
- package/dist/infra/git/index.d.ts.map +1 -0
- package/dist/infra/git/index.js +2 -0
- package/dist/infra/git/index.js.map +1 -0
- package/dist/infra/github/GitHubAdapter.d.ts +20 -0
- package/dist/infra/github/GitHubAdapter.d.ts.map +1 -0
- package/dist/infra/github/GitHubAdapter.js +61 -0
- package/dist/infra/github/GitHubAdapter.js.map +1 -0
- package/dist/infra/github/GitHubAdapter.test.d.ts +2 -0
- package/dist/infra/github/GitHubAdapter.test.d.ts.map +1 -0
- package/dist/infra/github/GitHubAdapter.test.js +116 -0
- package/dist/infra/github/GitHubAdapter.test.js.map +1 -0
- package/dist/infra/github/index.d.ts +3 -0
- package/dist/infra/github/index.d.ts.map +1 -0
- package/dist/infra/github/index.js +2 -0
- package/dist/infra/github/index.js.map +1 -0
- package/dist/infra/index.d.ts +6 -0
- package/dist/infra/index.d.ts.map +1 -0
- package/dist/infra/index.js +6 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/storage/FileCodeReviewRepository.d.ts +14 -0
- package/dist/infra/storage/FileCodeReviewRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileCodeReviewRepository.js +67 -0
- package/dist/infra/storage/FileCodeReviewRepository.js.map +1 -0
- package/dist/infra/storage/FileEventRepository.d.ts +16 -0
- package/dist/infra/storage/FileEventRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileEventRepository.js +58 -0
- package/dist/infra/storage/FileEventRepository.js.map +1 -0
- package/dist/infra/storage/FileSessionRepository.d.ts +17 -0
- package/dist/infra/storage/FileSessionRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileSessionRepository.js +68 -0
- package/dist/infra/storage/FileSessionRepository.js.map +1 -0
- package/dist/infra/storage/FileSessionRepository.test.d.ts +2 -0
- package/dist/infra/storage/FileSessionRepository.test.d.ts.map +1 -0
- package/dist/infra/storage/FileSessionRepository.test.js +84 -0
- package/dist/infra/storage/FileSessionRepository.test.js.map +1 -0
- package/dist/infra/storage/FileToolApprovalRepository.d.ts +17 -0
- package/dist/infra/storage/FileToolApprovalRepository.d.ts.map +1 -0
- package/dist/infra/storage/FileToolApprovalRepository.js +90 -0
- package/dist/infra/storage/FileToolApprovalRepository.js.map +1 -0
- package/dist/infra/storage/index.d.ts +5 -0
- package/dist/infra/storage/index.d.ts.map +1 -0
- package/dist/infra/storage/index.js +5 -0
- package/dist/infra/storage/index.js.map +1 -0
- package/dist/infra/websocket/WebSocketServer.d.ts +15 -0
- package/dist/infra/websocket/WebSocketServer.d.ts.map +1 -0
- package/dist/infra/websocket/WebSocketServer.js +45 -0
- package/dist/infra/websocket/WebSocketServer.js.map +1 -0
- package/dist/infra/websocket/index.d.ts +3 -0
- package/dist/infra/websocket/index.d.ts.map +1 -0
- package/dist/infra/websocket/index.js +2 -0
- package/dist/infra/websocket/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infra/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/infra/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CodeReview, ReviewStatus } from '@claudetree/shared';
|
|
2
|
+
import type { ICodeReviewRepository } from '../../domain/repositories/ICodeReviewRepository.js';
|
|
3
|
+
export declare class FileCodeReviewRepository implements ICodeReviewRepository {
|
|
4
|
+
private readonly reviewsDir;
|
|
5
|
+
constructor(configDir: string);
|
|
6
|
+
findBySessionId(sessionId: string): Promise<CodeReview | null>;
|
|
7
|
+
save(review: CodeReview): Promise<void>;
|
|
8
|
+
updateStatus(id: string, status: ReviewStatus, comment?: string): Promise<void>;
|
|
9
|
+
private getFilePath;
|
|
10
|
+
private getAllSessionIds;
|
|
11
|
+
private serialize;
|
|
12
|
+
private deserialize;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=FileCodeReviewRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileCodeReviewRepository.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/FileCodeReviewRepository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EAEb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAIhG,qBAAa,wBAAyB,YAAW,qBAAqB;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,SAAS,EAAE,MAAM;IAIvB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU9D,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IASvC,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgBhB,OAAO,CAAC,WAAW;YAIL,gBAAgB;IAY9B,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const REVIEWS_DIR = 'reviews';
|
|
4
|
+
export class FileCodeReviewRepository {
|
|
5
|
+
reviewsDir;
|
|
6
|
+
constructor(configDir) {
|
|
7
|
+
this.reviewsDir = join(configDir, REVIEWS_DIR);
|
|
8
|
+
}
|
|
9
|
+
async findBySessionId(sessionId) {
|
|
10
|
+
try {
|
|
11
|
+
const content = await readFile(this.getFilePath(sessionId), 'utf-8');
|
|
12
|
+
const data = JSON.parse(content);
|
|
13
|
+
return this.deserialize(data);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async save(review) {
|
|
20
|
+
await mkdir(this.reviewsDir, { recursive: true });
|
|
21
|
+
const data = this.serialize(review);
|
|
22
|
+
await writeFile(this.getFilePath(review.sessionId), JSON.stringify(data, null, 2));
|
|
23
|
+
}
|
|
24
|
+
async updateStatus(id, status, comment) {
|
|
25
|
+
const allFiles = await this.getAllSessionIds();
|
|
26
|
+
for (const sessionId of allFiles) {
|
|
27
|
+
const review = await this.findBySessionId(sessionId);
|
|
28
|
+
if (review && review.id === id) {
|
|
29
|
+
review.status = status;
|
|
30
|
+
review.comment = comment ?? review.comment;
|
|
31
|
+
review.resolvedAt = new Date();
|
|
32
|
+
await this.save(review);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
getFilePath(sessionId) {
|
|
38
|
+
return join(this.reviewsDir, `${sessionId}.json`);
|
|
39
|
+
}
|
|
40
|
+
async getAllSessionIds() {
|
|
41
|
+
try {
|
|
42
|
+
const { readdir } = await import('node:fs/promises');
|
|
43
|
+
const files = await readdir(this.reviewsDir);
|
|
44
|
+
return files
|
|
45
|
+
.filter((f) => f.endsWith('.json'))
|
|
46
|
+
.map((f) => f.replace('.json', ''));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
serialize(review) {
|
|
53
|
+
return {
|
|
54
|
+
...review,
|
|
55
|
+
requestedAt: review.requestedAt.toISOString(),
|
|
56
|
+
resolvedAt: review.resolvedAt?.toISOString() ?? null,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
deserialize(data) {
|
|
60
|
+
return {
|
|
61
|
+
...data,
|
|
62
|
+
requestedAt: new Date(data.requestedAt),
|
|
63
|
+
resolvedAt: data.resolvedAt ? new Date(data.resolvedAt) : null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=FileCodeReviewRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileCodeReviewRepository.js","sourceRoot":"","sources":["../../../src/infra/storage/FileCodeReviewRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SessionEvent } from '@claudetree/shared';
|
|
2
|
+
import type { IEventRepository } from '../../domain/repositories/IEventRepository.js';
|
|
3
|
+
export declare class FileEventRepository implements IEventRepository {
|
|
4
|
+
private readonly eventsDir;
|
|
5
|
+
constructor(configDir: string);
|
|
6
|
+
findBySessionId(sessionId: string): Promise<SessionEvent[]>;
|
|
7
|
+
append(event: SessionEvent): Promise<void>;
|
|
8
|
+
getLatest(sessionId: string, limit: number): Promise<SessionEvent[]>;
|
|
9
|
+
clear(sessionId: string): Promise<void>;
|
|
10
|
+
private getFilePath;
|
|
11
|
+
private loadEvents;
|
|
12
|
+
private saveEvents;
|
|
13
|
+
private serialize;
|
|
14
|
+
private deserialize;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=FileEventRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileEventRepository.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/FileEventRepository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAKtF,qBAAa,mBAAoB,YAAW,gBAAgB;IAC1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,SAAS,EAAE,MAAM;IAIvB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI3D,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1C,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAKpE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,OAAO,CAAC,WAAW;YAIL,UAAU;YAUV,UAAU;IASxB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,WAAW;CAMpB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const EVENTS_DIR = 'events';
|
|
4
|
+
const MAX_EVENTS = 1000;
|
|
5
|
+
export class FileEventRepository {
|
|
6
|
+
eventsDir;
|
|
7
|
+
constructor(configDir) {
|
|
8
|
+
this.eventsDir = join(configDir, EVENTS_DIR);
|
|
9
|
+
}
|
|
10
|
+
async findBySessionId(sessionId) {
|
|
11
|
+
return this.loadEvents(sessionId);
|
|
12
|
+
}
|
|
13
|
+
async append(event) {
|
|
14
|
+
const events = await this.loadEvents(event.sessionId);
|
|
15
|
+
events.push(event);
|
|
16
|
+
// Rotate if over max
|
|
17
|
+
const trimmed = events.slice(-MAX_EVENTS);
|
|
18
|
+
await this.saveEvents(event.sessionId, trimmed);
|
|
19
|
+
}
|
|
20
|
+
async getLatest(sessionId, limit) {
|
|
21
|
+
const events = await this.loadEvents(sessionId);
|
|
22
|
+
return events.slice(-limit);
|
|
23
|
+
}
|
|
24
|
+
async clear(sessionId) {
|
|
25
|
+
await this.saveEvents(sessionId, []);
|
|
26
|
+
}
|
|
27
|
+
getFilePath(sessionId) {
|
|
28
|
+
return join(this.eventsDir, `${sessionId}.json`);
|
|
29
|
+
}
|
|
30
|
+
async loadEvents(sessionId) {
|
|
31
|
+
try {
|
|
32
|
+
const content = await readFile(this.getFilePath(sessionId), 'utf-8');
|
|
33
|
+
const data = JSON.parse(content);
|
|
34
|
+
return data.map(this.deserialize);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async saveEvents(sessionId, events) {
|
|
41
|
+
await mkdir(this.eventsDir, { recursive: true });
|
|
42
|
+
const data = events.map(this.serialize);
|
|
43
|
+
await writeFile(this.getFilePath(sessionId), JSON.stringify(data, null, 2));
|
|
44
|
+
}
|
|
45
|
+
serialize(event) {
|
|
46
|
+
return {
|
|
47
|
+
...event,
|
|
48
|
+
timestamp: event.timestamp.toISOString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
deserialize(data) {
|
|
52
|
+
return {
|
|
53
|
+
...data,
|
|
54
|
+
timestamp: new Date(data.timestamp),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=FileEventRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileEventRepository.js","sourceRoot":"","sources":["../../../src/infra/storage/FileEventRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,OAAO,mBAAmB;IACb,SAAS,CAAS;IAEnC,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,SAAiB;QACrC,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAmB;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnB,qBAAqB;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,SAAiB,EAAE,KAAa;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAChD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAiB;QAC3B,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAEO,WAAW,CAAC,SAAiB;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,SAAS,OAAO,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,SAAiB;QACxC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA6B,CAAC;YAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CACtB,SAAiB,EACjB,MAAsB;QAEtB,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,MAAM,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;IAEO,SAAS,CAAC,KAAmB;QACnC,OAAO;YACL,GAAG,KAAK;YACR,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE;SACzC,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,IAA4B;QAC9C,OAAO;YACL,GAAG,IAAI;YACP,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;SACpC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Session } from '@claudetree/shared';
|
|
2
|
+
import type { ISessionRepository } from '../../domain/repositories/ISessionRepository.js';
|
|
3
|
+
export declare class FileSessionRepository implements ISessionRepository {
|
|
4
|
+
private readonly configDir;
|
|
5
|
+
private readonly filePath;
|
|
6
|
+
constructor(configDir: string);
|
|
7
|
+
findById(id: string): Promise<Session | null>;
|
|
8
|
+
findByWorktreeId(worktreeId: string): Promise<Session | null>;
|
|
9
|
+
findAll(): Promise<Session[]>;
|
|
10
|
+
save(session: Session): Promise<void>;
|
|
11
|
+
delete(id: string): Promise<void>;
|
|
12
|
+
private loadSessions;
|
|
13
|
+
private saveSessions;
|
|
14
|
+
private serializeSession;
|
|
15
|
+
private deserializeSession;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=FileSessionRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSessionRepository.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/FileSessionRepository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAI1F,qBAAa,qBAAsB,YAAW,kBAAkB;IAGlD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEL,SAAS,EAAE,MAAM;IAIxC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAK7C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAK7D,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI7B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAarC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAMzB,YAAY;YAUZ,YAAY;IAM1B,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,kBAAkB;CAO3B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const SESSIONS_FILE = 'sessions.json';
|
|
4
|
+
export class FileSessionRepository {
|
|
5
|
+
configDir;
|
|
6
|
+
filePath;
|
|
7
|
+
constructor(configDir) {
|
|
8
|
+
this.configDir = configDir;
|
|
9
|
+
this.filePath = join(configDir, SESSIONS_FILE);
|
|
10
|
+
}
|
|
11
|
+
async findById(id) {
|
|
12
|
+
const sessions = await this.loadSessions();
|
|
13
|
+
return sessions.find((s) => s.id === id) ?? null;
|
|
14
|
+
}
|
|
15
|
+
async findByWorktreeId(worktreeId) {
|
|
16
|
+
const sessions = await this.loadSessions();
|
|
17
|
+
return sessions.find((s) => s.worktreeId === worktreeId) ?? null;
|
|
18
|
+
}
|
|
19
|
+
async findAll() {
|
|
20
|
+
return this.loadSessions();
|
|
21
|
+
}
|
|
22
|
+
async save(session) {
|
|
23
|
+
const sessions = await this.loadSessions();
|
|
24
|
+
const index = sessions.findIndex((s) => s.id === session.id);
|
|
25
|
+
if (index >= 0) {
|
|
26
|
+
sessions[index] = session;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
sessions.push(session);
|
|
30
|
+
}
|
|
31
|
+
await this.saveSessions(sessions);
|
|
32
|
+
}
|
|
33
|
+
async delete(id) {
|
|
34
|
+
const sessions = await this.loadSessions();
|
|
35
|
+
const filtered = sessions.filter((s) => s.id !== id);
|
|
36
|
+
await this.saveSessions(filtered);
|
|
37
|
+
}
|
|
38
|
+
async loadSessions() {
|
|
39
|
+
try {
|
|
40
|
+
const content = await readFile(this.filePath, 'utf-8');
|
|
41
|
+
const data = JSON.parse(content);
|
|
42
|
+
return data.map(this.deserializeSession);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async saveSessions(sessions) {
|
|
49
|
+
await mkdir(this.configDir, { recursive: true });
|
|
50
|
+
const data = sessions.map(this.serializeSession);
|
|
51
|
+
await writeFile(this.filePath, JSON.stringify(data, null, 2));
|
|
52
|
+
}
|
|
53
|
+
serializeSession(session) {
|
|
54
|
+
return {
|
|
55
|
+
...session,
|
|
56
|
+
createdAt: session.createdAt.toISOString(),
|
|
57
|
+
updatedAt: session.updatedAt.toISOString(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
deserializeSession(data) {
|
|
61
|
+
return {
|
|
62
|
+
...data,
|
|
63
|
+
createdAt: new Date(data.createdAt),
|
|
64
|
+
updatedAt: new Date(data.updatedAt),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=FileSessionRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSessionRepository.js","sourceRoot":"","sources":["../../../src/infra/storage/FileSessionRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSessionRepository.test.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/FileSessionRepository.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { FileSessionRepository } from './FileSessionRepository.js';
|
|
6
|
+
describe('FileSessionRepository', () => {
|
|
7
|
+
let testDir;
|
|
8
|
+
let repo;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
testDir = await mkdtemp(join(tmpdir(), 'claudetree-session-test-'));
|
|
11
|
+
repo = new FileSessionRepository(testDir);
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await rm(testDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
const createTestSession = (overrides = {}) => ({
|
|
17
|
+
id: 'test-session-1',
|
|
18
|
+
worktreeId: 'worktree-1',
|
|
19
|
+
claudeSessionId: null,
|
|
20
|
+
status: 'pending',
|
|
21
|
+
issueNumber: null,
|
|
22
|
+
prompt: 'Test prompt',
|
|
23
|
+
createdAt: new Date('2024-01-01'),
|
|
24
|
+
updatedAt: new Date('2024-01-01'),
|
|
25
|
+
...overrides,
|
|
26
|
+
});
|
|
27
|
+
describe('save and findById', () => {
|
|
28
|
+
it('should save and retrieve a session', async () => {
|
|
29
|
+
const session = createTestSession();
|
|
30
|
+
await repo.save(session);
|
|
31
|
+
const found = await repo.findById(session.id);
|
|
32
|
+
expect(found).not.toBeNull();
|
|
33
|
+
expect(found?.id).toBe(session.id);
|
|
34
|
+
expect(found?.worktreeId).toBe(session.worktreeId);
|
|
35
|
+
expect(found?.status).toBe(session.status);
|
|
36
|
+
});
|
|
37
|
+
it('should return null for non-existent session', async () => {
|
|
38
|
+
const found = await repo.findById('non-existent');
|
|
39
|
+
expect(found).toBeNull();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('findByWorktreeId', () => {
|
|
43
|
+
it('should find session by worktree id', async () => {
|
|
44
|
+
const session = createTestSession({ worktreeId: 'wt-123' });
|
|
45
|
+
await repo.save(session);
|
|
46
|
+
const found = await repo.findByWorktreeId('wt-123');
|
|
47
|
+
expect(found).not.toBeNull();
|
|
48
|
+
expect(found?.worktreeId).toBe('wt-123');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('findAll', () => {
|
|
52
|
+
it('should return all sessions', async () => {
|
|
53
|
+
await repo.save(createTestSession({ id: 's1' }));
|
|
54
|
+
await repo.save(createTestSession({ id: 's2' }));
|
|
55
|
+
await repo.save(createTestSession({ id: 's3' }));
|
|
56
|
+
const all = await repo.findAll();
|
|
57
|
+
expect(all).toHaveLength(3);
|
|
58
|
+
});
|
|
59
|
+
it('should return empty array when no sessions', async () => {
|
|
60
|
+
const all = await repo.findAll();
|
|
61
|
+
expect(all).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('delete', () => {
|
|
65
|
+
it('should delete a session', async () => {
|
|
66
|
+
const session = createTestSession();
|
|
67
|
+
await repo.save(session);
|
|
68
|
+
await repo.delete(session.id);
|
|
69
|
+
const found = await repo.findById(session.id);
|
|
70
|
+
expect(found).toBeNull();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('update', () => {
|
|
74
|
+
it('should update existing session', async () => {
|
|
75
|
+
const session = createTestSession();
|
|
76
|
+
await repo.save(session);
|
|
77
|
+
const updated = { ...session, status: 'running' };
|
|
78
|
+
await repo.save(updated);
|
|
79
|
+
const found = await repo.findById(session.id);
|
|
80
|
+
expect(found?.status).toBe('running');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=FileSessionRepository.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSessionRepository.test.js","sourceRoot":"","sources":["../../../src/infra/storage/FileSessionRepository.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ApprovalStatus, ToolApproval } from '@claudetree/shared';
|
|
2
|
+
import type { IToolApprovalRepository } from '../../domain/repositories/IToolApprovalRepository.js';
|
|
3
|
+
export declare class FileToolApprovalRepository implements IToolApprovalRepository {
|
|
4
|
+
private readonly approvalsDir;
|
|
5
|
+
constructor(configDir: string);
|
|
6
|
+
findBySessionId(sessionId: string): Promise<ToolApproval[]>;
|
|
7
|
+
findPending(sessionId: string): Promise<ToolApproval[]>;
|
|
8
|
+
save(approval: ToolApproval): Promise<void>;
|
|
9
|
+
updateStatus(id: string, status: ApprovalStatus, approvedBy?: string): Promise<void>;
|
|
10
|
+
private getFilePath;
|
|
11
|
+
private getAllSessionIds;
|
|
12
|
+
private loadApprovals;
|
|
13
|
+
private saveApprovals;
|
|
14
|
+
private serialize;
|
|
15
|
+
private deserialize;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=FileToolApprovalRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileToolApprovalRepository.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/FileToolApprovalRepository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAEd,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sDAAsD,CAAC;AAIpG,qBAAa,0BAA2B,YAAW,uBAAuB;IACxE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,SAAS,EAAE,MAAM;IAIvB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI3D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAKvD,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3C,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,EACtB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAqBhB,OAAO,CAAC,WAAW;YAIL,gBAAgB;YAYhB,aAAa;YAUb,aAAa;IAS3B,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const APPROVALS_DIR = 'approvals';
|
|
4
|
+
export class FileToolApprovalRepository {
|
|
5
|
+
approvalsDir;
|
|
6
|
+
constructor(configDir) {
|
|
7
|
+
this.approvalsDir = join(configDir, APPROVALS_DIR);
|
|
8
|
+
}
|
|
9
|
+
async findBySessionId(sessionId) {
|
|
10
|
+
return this.loadApprovals(sessionId);
|
|
11
|
+
}
|
|
12
|
+
async findPending(sessionId) {
|
|
13
|
+
const approvals = await this.loadApprovals(sessionId);
|
|
14
|
+
return approvals.filter((a) => a.status === 'pending');
|
|
15
|
+
}
|
|
16
|
+
async save(approval) {
|
|
17
|
+
const approvals = await this.loadApprovals(approval.sessionId);
|
|
18
|
+
const index = approvals.findIndex((a) => a.id === approval.id);
|
|
19
|
+
if (index >= 0) {
|
|
20
|
+
approvals[index] = approval;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
approvals.push(approval);
|
|
24
|
+
}
|
|
25
|
+
await this.saveApprovals(approval.sessionId, approvals);
|
|
26
|
+
}
|
|
27
|
+
async updateStatus(id, status, approvedBy) {
|
|
28
|
+
// Find which session has this approval
|
|
29
|
+
const allFiles = await this.getAllSessionIds();
|
|
30
|
+
for (const sessionId of allFiles) {
|
|
31
|
+
const approvals = await this.loadApprovals(sessionId);
|
|
32
|
+
const index = approvals.findIndex((a) => a.id === id);
|
|
33
|
+
if (index >= 0) {
|
|
34
|
+
const approval = approvals[index];
|
|
35
|
+
if (approval) {
|
|
36
|
+
approval.status = status;
|
|
37
|
+
approval.approvedBy = approvedBy ?? null;
|
|
38
|
+
approval.resolvedAt = new Date();
|
|
39
|
+
await this.saveApprovals(sessionId, approvals);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
getFilePath(sessionId) {
|
|
46
|
+
return join(this.approvalsDir, `${sessionId}.json`);
|
|
47
|
+
}
|
|
48
|
+
async getAllSessionIds() {
|
|
49
|
+
try {
|
|
50
|
+
const { readdir } = await import('node:fs/promises');
|
|
51
|
+
const files = await readdir(this.approvalsDir);
|
|
52
|
+
return files
|
|
53
|
+
.filter((f) => f.endsWith('.json'))
|
|
54
|
+
.map((f) => f.replace('.json', ''));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async loadApprovals(sessionId) {
|
|
61
|
+
try {
|
|
62
|
+
const content = await readFile(this.getFilePath(sessionId), 'utf-8');
|
|
63
|
+
const data = JSON.parse(content);
|
|
64
|
+
return data.map(this.deserialize);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async saveApprovals(sessionId, approvals) {
|
|
71
|
+
await mkdir(this.approvalsDir, { recursive: true });
|
|
72
|
+
const data = approvals.map(this.serialize);
|
|
73
|
+
await writeFile(this.getFilePath(sessionId), JSON.stringify(data, null, 2));
|
|
74
|
+
}
|
|
75
|
+
serialize(approval) {
|
|
76
|
+
return {
|
|
77
|
+
...approval,
|
|
78
|
+
requestedAt: approval.requestedAt.toISOString(),
|
|
79
|
+
resolvedAt: approval.resolvedAt?.toISOString() ?? null,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
deserialize(data) {
|
|
83
|
+
return {
|
|
84
|
+
...data,
|
|
85
|
+
requestedAt: new Date(data.requestedAt),
|
|
86
|
+
resolvedAt: data.resolvedAt ? new Date(data.resolvedAt) : null,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=FileToolApprovalRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileToolApprovalRepository.js","sourceRoot":"","sources":["../../../src/infra/storage/FileToolApprovalRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { FileSessionRepository } from './FileSessionRepository.js';
|
|
2
|
+
export { FileEventRepository } from './FileEventRepository.js';
|
|
3
|
+
export { FileToolApprovalRepository } from './FileToolApprovalRepository.js';
|
|
4
|
+
export { FileCodeReviewRepository } from './FileCodeReviewRepository.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infra/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { FileSessionRepository } from './FileSessionRepository.js';
|
|
2
|
+
export { FileEventRepository } from './FileEventRepository.js';
|
|
3
|
+
export { FileToolApprovalRepository } from './FileToolApprovalRepository.js';
|
|
4
|
+
export { FileCodeReviewRepository } from './FileCodeReviewRepository.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/infra/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type EventType = 'session:started' | 'session:updated' | 'session:stopped' | 'session:output' | 'worktree:created' | 'worktree:deleted' | 'event:created' | 'approval:requested' | 'approval:resolved' | 'review:requested' | 'review:resolved';
|
|
2
|
+
export interface WSMessage {
|
|
3
|
+
type: EventType;
|
|
4
|
+
payload: unknown;
|
|
5
|
+
timestamp: Date;
|
|
6
|
+
}
|
|
7
|
+
export declare class WebSocketBroadcaster {
|
|
8
|
+
private wss;
|
|
9
|
+
private clients;
|
|
10
|
+
constructor(port: number);
|
|
11
|
+
broadcast(message: WSMessage): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
get clientCount(): number;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=WebSocketServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketServer.d.ts","sourceRoot":"","sources":["../../../src/infra/websocket/WebSocketServer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,oBAAoB,GACpB,mBAAmB,GACnB,kBAAkB,GAClB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,GAAG,CAAW;IACtB,OAAO,CAAC,OAAO,CAAwB;gBAE3B,IAAI,EAAE,MAAM;IAyBxB,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAanC,KAAK,IAAI,IAAI;IAOb,IAAI,WAAW,IAAI,MAAM,CAExB;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { WebSocketServer as WSServer, WebSocket } from 'ws';
|
|
2
|
+
export class WebSocketBroadcaster {
|
|
3
|
+
wss;
|
|
4
|
+
clients = new Set();
|
|
5
|
+
constructor(port) {
|
|
6
|
+
this.wss = new WSServer({ port });
|
|
7
|
+
this.wss.on('connection', (ws) => {
|
|
8
|
+
this.clients.add(ws);
|
|
9
|
+
console.log(`WebSocket client connected (${this.clients.size} total)`);
|
|
10
|
+
ws.on('close', () => {
|
|
11
|
+
this.clients.delete(ws);
|
|
12
|
+
console.log(`WebSocket client disconnected (${this.clients.size} total)`);
|
|
13
|
+
});
|
|
14
|
+
ws.on('error', (err) => {
|
|
15
|
+
console.error('WebSocket error:', err.message);
|
|
16
|
+
this.clients.delete(ws);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
this.wss.on('error', (err) => {
|
|
20
|
+
console.error('WebSocket server error:', err.message);
|
|
21
|
+
});
|
|
22
|
+
console.log(`WebSocket server listening on port ${port}`);
|
|
23
|
+
}
|
|
24
|
+
broadcast(message) {
|
|
25
|
+
const data = JSON.stringify({
|
|
26
|
+
...message,
|
|
27
|
+
timestamp: message.timestamp.toISOString(),
|
|
28
|
+
});
|
|
29
|
+
for (const client of this.clients) {
|
|
30
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
31
|
+
client.send(data);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
close() {
|
|
36
|
+
for (const client of this.clients) {
|
|
37
|
+
client.close();
|
|
38
|
+
}
|
|
39
|
+
this.wss.close();
|
|
40
|
+
}
|
|
41
|
+
get clientCount() {
|
|
42
|
+
return this.clients.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=WebSocketServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketServer.js","sourceRoot":"","sources":["../../../src/infra/websocket/WebSocketServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,QAAQ,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAqB5D,MAAM,OAAO,oBAAoB;IACvB,GAAG,CAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;IAEvC,YAAY,IAAY;QACtB,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAElC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE;YAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC;YAEvE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACrB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC/C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,sCAAsC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,SAAS,CAAC,OAAkB;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,GAAG,OAAO;YACV,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE;SAC3C,CAAC,CAAC;QAEH,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF"}
|