@fireproof/core-protocols-cloud 0.22.0-keybag → 0.23.1-dev-issue-1057
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.md +197 -228
- package/README.md +269 -0
- package/http-connection.d.ts +1 -1
- package/http-connection.js.map +1 -1
- package/index.js.map +1 -1
- package/msg-raw-connection-base.js.map +1 -1
- package/msger.js +5 -0
- package/msger.js.map +1 -1
- package/package.json +7 -7
- package/ws-connection.js.map +1 -1
- package/http-connection.ts +0 -204
- package/index.ts +0 -4
- package/msg-raw-connection-base.ts +0 -38
- package/msger.ts +0 -551
- package/tsconfig.json +0 -18
- package/ws-connection.ts +0 -270
package/ws-connection.ts
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { exception2Result, Future, Logger, Result, top_uint8 } from "@adviser/cement";
|
|
2
|
-
import {
|
|
3
|
-
MsgBase,
|
|
4
|
-
MsgIsError,
|
|
5
|
-
buildErrorMsg,
|
|
6
|
-
ReqOpen,
|
|
7
|
-
WaitForTid,
|
|
8
|
-
MsgWithError,
|
|
9
|
-
RequestOpts,
|
|
10
|
-
MsgRawConnection,
|
|
11
|
-
} from "@fireproof/core-types-protocols-cloud";
|
|
12
|
-
import { ActiveStream, ExchangedGestalt, MsgerParamsWithEnDe, OnMsgFn, UnReg } from "./msger.js";
|
|
13
|
-
import { MsgRawConnectionBase } from "./msg-raw-connection-base.js";
|
|
14
|
-
import { SuperThis } from "@fireproof/core-types-base";
|
|
15
|
-
import { ensureLogger } from "@fireproof/core-runtime";
|
|
16
|
-
|
|
17
|
-
export interface WSReqOpen {
|
|
18
|
-
readonly reqOpen: ReqOpen;
|
|
19
|
-
readonly ws: WebSocket; // this WS is opened with a specific URL-Param
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface WaitForTidItem {
|
|
23
|
-
readonly opts: WaitForTid;
|
|
24
|
-
readonly timeout?: ReturnType<typeof setTimeout>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
class WaitForTids {
|
|
28
|
-
readonly waitForTids = new Map<string, WaitForTidItem>();
|
|
29
|
-
|
|
30
|
-
start(sthis: SuperThis, logger: Logger, waitFor: WaitForTid) {
|
|
31
|
-
let timeout: ReturnType<typeof setTimeout> | undefined = undefined;
|
|
32
|
-
if (typeof waitFor.timeout === "number" && waitFor.timeout > 0) {
|
|
33
|
-
timeout = setTimeout(() => {
|
|
34
|
-
this.waitForTids.delete(waitFor.tid);
|
|
35
|
-
waitFor.future.resolve(
|
|
36
|
-
buildErrorMsg(
|
|
37
|
-
{ logger, sthis },
|
|
38
|
-
{
|
|
39
|
-
tid: waitFor.tid,
|
|
40
|
-
} as MsgBase,
|
|
41
|
-
logger.Error().Any({ tid: waitFor }).Msg("Timeout").AsError(),
|
|
42
|
-
),
|
|
43
|
-
);
|
|
44
|
-
}, waitFor.timeout);
|
|
45
|
-
}
|
|
46
|
-
// console.log("waitForTids", waitFor.tid, waitFor.timeout);
|
|
47
|
-
this.waitForTids.set(waitFor.tid, {
|
|
48
|
-
opts: waitFor,
|
|
49
|
-
timeout,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
stop(tid: string) {
|
|
54
|
-
const item = this.waitForTids.get(tid);
|
|
55
|
-
if (!item) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (item.timeout) {
|
|
59
|
-
clearTimeout(item.timeout);
|
|
60
|
-
}
|
|
61
|
-
this.waitForTids.delete(tid);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
resolve(msg: MsgBase): WaitForTidItem | undefined {
|
|
65
|
-
const item = this.waitForTids.get(msg.tid);
|
|
66
|
-
if (!item) {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
if (item.opts.waitFor(msg)) {
|
|
70
|
-
if (item.timeout) {
|
|
71
|
-
clearTimeout(item.timeout);
|
|
72
|
-
}
|
|
73
|
-
item.opts.future.resolve(msg);
|
|
74
|
-
}
|
|
75
|
-
return item;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const DefaultRoundTripTime = 1000;
|
|
80
|
-
|
|
81
|
-
export class WSConnection extends MsgRawConnectionBase implements MsgRawConnection {
|
|
82
|
-
readonly logger: Logger;
|
|
83
|
-
readonly msgP: MsgerParamsWithEnDe;
|
|
84
|
-
readonly ws: WebSocket;
|
|
85
|
-
// readonly baseURI: URI;
|
|
86
|
-
|
|
87
|
-
readonly #onMsg = new Map<string, OnMsgFn>();
|
|
88
|
-
readonly #onClose = new Map<string, UnReg>();
|
|
89
|
-
|
|
90
|
-
readonly waitForTid = new WaitForTids();
|
|
91
|
-
|
|
92
|
-
readonly id: string;
|
|
93
|
-
|
|
94
|
-
isReady = false;
|
|
95
|
-
|
|
96
|
-
constructor(sthis: SuperThis, ws: WebSocket, msgP: MsgerParamsWithEnDe, exGestalt: ExchangedGestalt) {
|
|
97
|
-
super(sthis, exGestalt);
|
|
98
|
-
this.id = sthis.nextId().str;
|
|
99
|
-
this.logger = ensureLogger(sthis, "WSConnection");
|
|
100
|
-
this.msgP = msgP;
|
|
101
|
-
this.ws = ws;
|
|
102
|
-
// this.wqs = { ...wsq };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async start(): Promise<Result<void>> {
|
|
106
|
-
const onOpenFuture: Future<Result<unknown>> = new Future<Result<unknown>>();
|
|
107
|
-
const timer = setTimeout(() => {
|
|
108
|
-
const err = this.logger.Error().Dur("timeout", this.msgP.timeout).Msg("Timeout").AsError();
|
|
109
|
-
this.toMsg(buildErrorMsg(this, {} as MsgBase, err));
|
|
110
|
-
onOpenFuture.resolve(Result.Err(err));
|
|
111
|
-
}, this.msgP.timeout);
|
|
112
|
-
|
|
113
|
-
this.ws.onopen = () => {
|
|
114
|
-
this.isReady = true;
|
|
115
|
-
onOpenFuture.resolve(Result.Ok(undefined));
|
|
116
|
-
};
|
|
117
|
-
this.ws.onerror = (ierr) => {
|
|
118
|
-
// console.log("onerror", this.id, ierr);
|
|
119
|
-
const err = this.logger.Error().Err(ierr).Msg("WS Error").AsError();
|
|
120
|
-
onOpenFuture.resolve(Result.Err(err));
|
|
121
|
-
const res = this.buildErrorMsg(this, {}, err);
|
|
122
|
-
this.toMsg(res);
|
|
123
|
-
};
|
|
124
|
-
this.ws.onmessage = (evt) => {
|
|
125
|
-
if (!this.isReady) {
|
|
126
|
-
this.toMsg(buildErrorMsg(this, {} as MsgBase, this.logger.Error().Msg("Received message before onOpen").AsError()));
|
|
127
|
-
}
|
|
128
|
-
this.#wsOnMessage(evt);
|
|
129
|
-
};
|
|
130
|
-
this.ws.onclose = () => {
|
|
131
|
-
this.isReady = false;
|
|
132
|
-
// console.log("onclose", this.id);
|
|
133
|
-
this.close().catch((ierr) => {
|
|
134
|
-
const err = this.logger.Error().Err(ierr).Msg("close error").AsError();
|
|
135
|
-
onOpenFuture.resolve(Result.Err(err));
|
|
136
|
-
this.toMsg(buildErrorMsg(this, { tid: "internal" } as MsgBase, err));
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
/* wait for onOpen */
|
|
140
|
-
const rOpen = await onOpenFuture.asPromise().finally(() => {
|
|
141
|
-
clearTimeout(timer);
|
|
142
|
-
});
|
|
143
|
-
if (rOpen.isErr()) {
|
|
144
|
-
return rOpen;
|
|
145
|
-
}
|
|
146
|
-
// const resOpen = await this.request(this.wqs.reqOpen, { waitFor: MsgIsResOpen });
|
|
147
|
-
// if (!MsgIsResOpen(resOpen)) {
|
|
148
|
-
// return Result.Err(this.logger.Error().Any("ErrMsg", resOpen).Msg("Invalid response").AsError());
|
|
149
|
-
// }
|
|
150
|
-
// this.wqs.resOpen = resOpen;
|
|
151
|
-
return Result.Ok(undefined);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
readonly #wsOnMessage = async (event: MessageEvent) => {
|
|
155
|
-
const rMsg = await exception2Result(async () => {
|
|
156
|
-
const msg = this.msgP.ende.decode(await top_uint8(event.data)) as MsgBase;
|
|
157
|
-
return msg;
|
|
158
|
-
});
|
|
159
|
-
if (rMsg.isErr()) {
|
|
160
|
-
this.logger.Error().Err(rMsg).Any({ event }).Msg("Invalid message");
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
const msg = rMsg.Ok();
|
|
164
|
-
// console.log("wsOnMessage", this.id, msg);
|
|
165
|
-
this.waitForTid.resolve(msg);
|
|
166
|
-
// console.log("wsOnMessage", msg, this.#onMsg.size);
|
|
167
|
-
Array.from(this.#onMsg.values()).forEach((cb) => {
|
|
168
|
-
// console.log("cb-onmessage", this.id, msg, cb.toString());
|
|
169
|
-
cb(msg);
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
async close(): Promise<Result<void>> {
|
|
174
|
-
this.#onClose.forEach((fn) => fn());
|
|
175
|
-
this.#onClose.clear();
|
|
176
|
-
this.#onMsg.clear();
|
|
177
|
-
// console.lows.id, ion", this.id, new Error().stack);
|
|
178
|
-
this.ws.close();
|
|
179
|
-
return Result.Ok(undefined);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
toMsg<S extends MsgBase>(msg: MsgWithError<S>): MsgWithError<S> {
|
|
183
|
-
this.#onMsg.forEach((fn) => fn(msg));
|
|
184
|
-
return msg;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
send<Q extends MsgBase, S extends MsgBase>(msg: Q): Promise<S> {
|
|
188
|
-
// console.log("send", msg);
|
|
189
|
-
this.ws.send(this.msgP.ende.encode(msg));
|
|
190
|
-
return Promise.resolve(msg as unknown as S);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
onMsg<S extends MsgBase>(fn: OnMsgFn<S>): UnReg {
|
|
194
|
-
const key = this.sthis.nextId().str;
|
|
195
|
-
this.#onMsg.set(key, fn as OnMsgFn);
|
|
196
|
-
return () => this.#onMsg.delete(key);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
onClose(fn: UnReg): UnReg {
|
|
200
|
-
const key = this.sthis.nextId().str;
|
|
201
|
-
this.#onClose.set(key, fn);
|
|
202
|
-
return () => this.#onClose.delete(key);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
readonly activeBinds = new Map<string, ActiveStream>();
|
|
206
|
-
bind<Q extends MsgBase, S extends MsgBase>(req: Q, opts: RequestOpts): ReadableStream<MsgWithError<S>> {
|
|
207
|
-
const state: ActiveStream = {
|
|
208
|
-
id: this.sthis.nextId().str,
|
|
209
|
-
bind: {
|
|
210
|
-
msg: req,
|
|
211
|
-
opts,
|
|
212
|
-
},
|
|
213
|
-
// timeout: undefined,
|
|
214
|
-
controller: undefined,
|
|
215
|
-
} satisfies ActiveStream;
|
|
216
|
-
this.activeBinds.set(state.id, state);
|
|
217
|
-
const ret = new ReadableStream<MsgWithError<S>>({
|
|
218
|
-
cancel: () => {
|
|
219
|
-
// clearTimeout(state.timeout as number);
|
|
220
|
-
this.activeBinds.delete(state.id);
|
|
221
|
-
},
|
|
222
|
-
start: (controller) => {
|
|
223
|
-
state.controller = controller; // set controller in ActiveStream
|
|
224
|
-
this.onMsg<S>((msg) => {
|
|
225
|
-
try {
|
|
226
|
-
if (MsgIsError(msg)) {
|
|
227
|
-
controller.enqueue(msg);
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
if (!opts.waitFor) {
|
|
231
|
-
controller.enqueue(msg);
|
|
232
|
-
} else if (opts.waitFor(msg)) {
|
|
233
|
-
controller.enqueue(msg);
|
|
234
|
-
}
|
|
235
|
-
} catch (err) {
|
|
236
|
-
this.logger.Error().Err(err).Any({ msg }).Msg("Error in onMsg callback[ignored]");
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
this.send(req);
|
|
240
|
-
const future = new Future<S>();
|
|
241
|
-
this.waitForTid.start(this.sthis, this.logger, { tid: req.tid, future, waitFor: opts.waitFor });
|
|
242
|
-
future.asPromise().then((msg) => {
|
|
243
|
-
if (MsgIsError(msg)) {
|
|
244
|
-
// double err emitting
|
|
245
|
-
controller.enqueue(msg);
|
|
246
|
-
controller.close();
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
return ret;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
async request<Q extends MsgBase, S extends MsgBase>(req: Q, opts: RequestOpts): Promise<MsgWithError<S>> {
|
|
255
|
-
const future = new Future<S>();
|
|
256
|
-
this.waitForTid.start(this.sthis, this.logger, {
|
|
257
|
-
tid: req.tid,
|
|
258
|
-
future,
|
|
259
|
-
waitFor: opts.waitFor,
|
|
260
|
-
timeout: opts.timeout ?? DefaultRoundTripTime,
|
|
261
|
-
});
|
|
262
|
-
await this.send(req);
|
|
263
|
-
return future.asPromise();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// toOnMessage<T extends MsgBase>(msg: WithErrorMsg<T>): Result<WithErrorMsg<T>> {
|
|
267
|
-
// this.mec.msgFn?.(msg as unknown as MessageEvent<MsgBase>);
|
|
268
|
-
// return Result.Ok(msg);
|
|
269
|
-
// }
|
|
270
|
-
}
|