1- import { createOk , isErr , type Result , unwrapOk } from "option-t/plain_result" ;
21import type {
32 NotFoundError ,
43 NotLoggedInError ,
54 NotMemberError ,
65} from "@cosense/types/rest" ;
7- import type {
8- ProjectUpdatesStreamCommit ,
9- ProjectUpdatesStreamEvent ,
10- } from "./emit.ts" ;
116import type { HTTPError } from "../../rest/responseIntoResult.ts" ;
127import type { AbortError , NetworkError } from "../../rest/robustFetch.ts" ;
13- import { getProjectId } from "./pull.ts" ;
14- import { connect , disconnect } from "./socket.ts" ;
15- import type { Socket } from "socket.io-client" ;
8+ import type { ScrapboxSocket } from "./socket.ts" ;
9+ import type { ListenEvents } from "./listen-events.ts" ;
1610
1711export type {
1812 ProjectUpdatesStreamCommit ,
1913 ProjectUpdatesStreamEvent ,
20- } from "./websocket-types .ts" ;
14+ } from "./listen-events .ts" ;
2115
2216export interface ListenStreamOptions {
23- socket ?: Socket ;
17+ signal ?: AbortSignal ;
18+ once ?: boolean ;
2419}
2520
2621export type ListenStreamError =
@@ -37,46 +32,21 @@ export type ListenStreamError =
3732 * @param events 購読したいevent。配列で指定する
3833 * @param options 使用したいSocketがあれば指定する
3934 */
40- export async function * listenStream (
41- project : string ,
42- events : [ "commit" | "event" , ...( "commit" | "event" ) [ ] ] ,
35+ export const listen = < EventName extends keyof ListenEvents > (
36+ socket : ScrapboxSocket ,
37+ event : EventName ,
38+ listener : ListenEvents [ EventName ] ,
4339 options ?: ListenStreamOptions ,
44- ) : AsyncGenerator <
45- Result <
46- ProjectUpdatesStreamEvent | ProjectUpdatesStreamCommit ,
47- ListenStreamError
48- > ,
49- void ,
50- unknown
51- > {
52- const result = await getProjectId ( project ) ;
53- if ( isErr ( result ) ) {
54- yield result ;
55- return ;
56- }
57- const projectId = unwrapOk ( result ) ;
40+ ) : void => {
41+ if ( options ?. signal ?. aborted ) return ;
5842
59- const injectedSocket = options ?. socket ;
60- const result2 = await connect ( injectedSocket ) ;
61- if ( isErr ( result2 ) ) throw new Error ( "Failed to connect to websocket" ) ;
62- const socket = unwrapOk ( result2 ) ;
63- const { request, response } = wrap ( socket ) ;
43+ // deno-lint-ignore no-explicit-any
44+ ( options ?. once ? socket . once : socket . on ) ( event , listener as any ) ;
6445
65- try {
66- // 部屋に入って購読し始める
67- await request ( "socket.io-request" , {
68- method : "room:join" ,
69- data : { projectId, pageId : null , projectUpdatesStream : true } ,
70- } ) ;
71-
72- for await (
73- const streamEvent of response (
74- ...events . map ( ( event ) => `projectUpdatesStream:${ event } ` as const ) ,
75- )
76- ) {
77- yield createOk ( streamEvent ) ;
78- }
79- } finally {
80- if ( ! injectedSocket ) await disconnect ( socket ) ;
81- }
82- }
46+ options ?. signal ?. addEventListener ?.(
47+ "abort" ,
48+ // deno-lint-ignore no-explicit-any
49+ ( ) => socket . off ( event , listener as any ) ,
50+ { once : true } ,
51+ ) ;
52+ } ;
0 commit comments