@fncts/http 0.0.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/Body/api.d.ts +63 -0
- package/Body/definition.d.ts +53 -0
- package/Body.d.ts +2 -0
- package/BodyError.d.ts +30 -0
- package/Headers.d.ts +42 -0
- package/HttpApp.d.ts +46 -0
- package/IncomingMessage/api.d.ts +19 -0
- package/IncomingMessage/definition.d.ts +21 -0
- package/IncomingMessage.d.ts +2 -0
- package/Method.d.ts +2 -0
- package/Middleware.d.ts +24 -0
- package/QueryParams.d.ts +7 -0
- package/RequestError.d.ts +10 -0
- package/ResponseError.d.ts +14 -0
- package/Route/api.d.ts +37 -0
- package/Route/definition.d.ts +35 -0
- package/Route/internal.d.ts +17 -0
- package/Route.d.ts +2 -0
- package/RouteNotFound.d.ts +8 -0
- package/Router/api.d.ts +96 -0
- package/Router/definition.d.ts +28 -0
- package/Router/internal.d.ts +26 -0
- package/Router.d.ts +2 -0
- package/Server.d.ts +53 -0
- package/ServerError.d.ts +9 -0
- package/ServerRequest/api.d.ts +6 -0
- package/ServerRequest/definition.d.ts +30 -0
- package/ServerRequest/internal.d.ts +33 -0
- package/ServerRequest.d.ts +2 -0
- package/ServerResponse/api.d.ts +69 -0
- package/ServerResponse/definition.d.ts +30 -0
- package/ServerResponse.d.ts +2 -0
- package/Socket.d.ts +107 -0
- package/UrlParams.d.ts +21 -0
- package/_cjs/Body/api.cjs +93 -0
- package/_cjs/Body/api.cjs.map +1 -0
- package/_cjs/Body/definition.cjs +71 -0
- package/_cjs/Body/definition.cjs.map +1 -0
- package/_cjs/Body.cjs +28 -0
- package/_cjs/Body.cjs.map +1 -0
- package/_cjs/BodyError.cjs +43 -0
- package/_cjs/BodyError.cjs.map +1 -0
- package/_cjs/Headers.cjs +87 -0
- package/_cjs/Headers.cjs.map +1 -0
- package/_cjs/HttpApp.cjs +109 -0
- package/_cjs/HttpApp.cjs.map +1 -0
- package/_cjs/IncomingMessage/api.cjs +35 -0
- package/_cjs/IncomingMessage/api.cjs.map +1 -0
- package/_cjs/IncomingMessage/definition.cjs +20 -0
- package/_cjs/IncomingMessage/definition.cjs.map +1 -0
- package/_cjs/IncomingMessage.cjs +28 -0
- package/_cjs/IncomingMessage.cjs.map +1 -0
- package/_cjs/Method.cjs +10 -0
- package/_cjs/Method.cjs.map +1 -0
- package/_cjs/Middleware.cjs +16 -0
- package/_cjs/Middleware.cjs.map +1 -0
- package/_cjs/QueryParams.cjs +6 -0
- package/_cjs/QueryParams.cjs.map +1 -0
- package/_cjs/RequestError.cjs +19 -0
- package/_cjs/RequestError.cjs.map +1 -0
- package/_cjs/ResponseError.cjs +27 -0
- package/_cjs/ResponseError.cjs.map +1 -0
- package/_cjs/Route/api.cjs +61 -0
- package/_cjs/Route/api.cjs.map +1 -0
- package/_cjs/Route/definition.cjs +35 -0
- package/_cjs/Route/definition.cjs.map +1 -0
- package/_cjs/Route/internal.cjs +31 -0
- package/_cjs/Route/internal.cjs.map +1 -0
- package/_cjs/Route.cjs +28 -0
- package/_cjs/Route.cjs.map +1 -0
- package/_cjs/RouteNotFound.cjs +18 -0
- package/_cjs/RouteNotFound.cjs.map +1 -0
- package/_cjs/Router/api.cjs +141 -0
- package/_cjs/Router/api.cjs.map +1 -0
- package/_cjs/Router/definition.cjs +22 -0
- package/_cjs/Router/definition.cjs.map +1 -0
- package/_cjs/Router/internal.cjs +85 -0
- package/_cjs/Router/internal.cjs.map +1 -0
- package/_cjs/Router.cjs +28 -0
- package/_cjs/Router.cjs.map +1 -0
- package/_cjs/Server.cjs +53 -0
- package/_cjs/Server.cjs.map +1 -0
- package/_cjs/ServerError.cjs +21 -0
- package/_cjs/ServerError.cjs.map +1 -0
- package/_cjs/ServerRequest/api.cjs +14 -0
- package/_cjs/ServerRequest/api.cjs.map +1 -0
- package/_cjs/ServerRequest/definition.cjs +29 -0
- package/_cjs/ServerRequest/definition.cjs.map +1 -0
- package/_cjs/ServerRequest/internal.cjs +77 -0
- package/_cjs/ServerRequest/internal.cjs.map +1 -0
- package/_cjs/ServerRequest.cjs +28 -0
- package/_cjs/ServerRequest.cjs.map +1 -0
- package/_cjs/ServerResponse/api.cjs +157 -0
- package/_cjs/ServerResponse/api.cjs.map +1 -0
- package/_cjs/ServerResponse/definition.cjs +44 -0
- package/_cjs/ServerResponse/definition.cjs.map +1 -0
- package/_cjs/ServerResponse.cjs +28 -0
- package/_cjs/ServerResponse.cjs.map +1 -0
- package/_cjs/Socket.cjs +221 -0
- package/_cjs/Socket.cjs.map +1 -0
- package/_cjs/UrlParams.cjs +34 -0
- package/_cjs/UrlParams.cjs.map +1 -0
- package/_cjs/global.cjs +6 -0
- package/_cjs/global.cjs.map +1 -0
- package/_mjs/Body/api.mjs +78 -0
- package/_mjs/Body/api.mjs.map +1 -0
- package/_mjs/Body/definition.mjs +58 -0
- package/_mjs/Body/definition.mjs.map +1 -0
- package/_mjs/Body.mjs +5 -0
- package/_mjs/Body.mjs.map +1 -0
- package/_mjs/BodyError.mjs +33 -0
- package/_mjs/BodyError.mjs.map +1 -0
- package/_mjs/Headers.mjs +75 -0
- package/_mjs/Headers.mjs.map +1 -0
- package/_mjs/HttpApp.mjs +96 -0
- package/_mjs/HttpApp.mjs.map +1 -0
- package/_mjs/IncomingMessage/api.mjs +25 -0
- package/_mjs/IncomingMessage/api.mjs.map +1 -0
- package/_mjs/IncomingMessage/definition.mjs +13 -0
- package/_mjs/IncomingMessage/definition.mjs.map +1 -0
- package/_mjs/IncomingMessage.mjs +5 -0
- package/_mjs/IncomingMessage.mjs.map +1 -0
- package/_mjs/Method.mjs +4 -0
- package/_mjs/Method.mjs.map +1 -0
- package/_mjs/Middleware.mjs +9 -0
- package/_mjs/Middleware.mjs.map +1 -0
- package/_mjs/QueryParams.mjs +2 -0
- package/_mjs/QueryParams.mjs.map +1 -0
- package/_mjs/RequestError.mjs +12 -0
- package/_mjs/RequestError.mjs.map +1 -0
- package/_mjs/ResponseError.mjs +20 -0
- package/_mjs/ResponseError.mjs.map +1 -0
- package/_mjs/Route/api.mjs +48 -0
- package/_mjs/Route/api.mjs.map +1 -0
- package/_mjs/Route/definition.mjs +25 -0
- package/_mjs/Route/definition.mjs.map +1 -0
- package/_mjs/Route/internal.mjs +21 -0
- package/_mjs/Route/internal.mjs.map +1 -0
- package/_mjs/Route.mjs +5 -0
- package/_mjs/Route.mjs.map +1 -0
- package/_mjs/RouteNotFound.mjs +11 -0
- package/_mjs/RouteNotFound.mjs.map +1 -0
- package/_mjs/Router/api.mjs +123 -0
- package/_mjs/Router/api.mjs.map +1 -0
- package/_mjs/Router/definition.mjs +15 -0
- package/_mjs/Router/definition.mjs.map +1 -0
- package/_mjs/Router/internal.mjs +76 -0
- package/_mjs/Router/internal.mjs.map +1 -0
- package/_mjs/Router.mjs +5 -0
- package/_mjs/Router.mjs.map +1 -0
- package/_mjs/Server.mjs +41 -0
- package/_mjs/Server.mjs.map +1 -0
- package/_mjs/ServerError.mjs +14 -0
- package/_mjs/ServerError.mjs.map +1 -0
- package/_mjs/ServerRequest/api.mjs +8 -0
- package/_mjs/ServerRequest/api.mjs.map +1 -0
- package/_mjs/ServerRequest/definition.mjs +20 -0
- package/_mjs/ServerRequest/definition.mjs.map +1 -0
- package/_mjs/ServerRequest/internal.mjs +68 -0
- package/_mjs/ServerRequest/internal.mjs.map +1 -0
- package/_mjs/ServerRequest.mjs +5 -0
- package/_mjs/ServerRequest.mjs.map +1 -0
- package/_mjs/ServerResponse/api.mjs +138 -0
- package/_mjs/ServerResponse/api.mjs.map +1 -0
- package/_mjs/ServerResponse/definition.mjs +34 -0
- package/_mjs/ServerResponse/definition.mjs.map +1 -0
- package/_mjs/ServerResponse.mjs +5 -0
- package/_mjs/ServerResponse.mjs.map +1 -0
- package/_mjs/Socket.mjs +202 -0
- package/_mjs/Socket.mjs.map +1 -0
- package/_mjs/UrlParams.mjs +25 -0
- package/_mjs/UrlParams.mjs.map +1 -0
- package/_mjs/global.mjs +2 -0
- package/_mjs/global.mjs.map +1 -0
- package/_src/Body/api.ts +106 -0
- package/_src/Body/definition.ts +74 -0
- package/_src/Body.ts +5 -0
- package/_src/BodyError.ts +38 -0
- package/_src/Headers.ts +84 -0
- package/_src/HttpApp.ts +129 -0
- package/_src/IncomingMessage/api.ts +25 -0
- package/_src/IncomingMessage/definition.ts +20 -0
- package/_src/IncomingMessage.ts +5 -0
- package/_src/Method.ts +5 -0
- package/_src/Middleware.ts +29 -0
- package/_src/QueryParams.ts +7 -0
- package/_src/RequestError.ts +13 -0
- package/_src/ResponseError.ts +25 -0
- package/_src/Route/api.ts +53 -0
- package/_src/Route/definition.ts +40 -0
- package/_src/Route/internal.ts +25 -0
- package/_src/Route.ts +5 -0
- package/_src/RouteNotFound.ts +14 -0
- package/_src/Router/api.ts +161 -0
- package/_src/Router/definition.ts +29 -0
- package/_src/Router/internal.ts +95 -0
- package/_src/Router.ts +5 -0
- package/_src/Server.ts +88 -0
- package/_src/ServerError.ts +14 -0
- package/_src/ServerRequest/api.ts +10 -0
- package/_src/ServerRequest/definition.ts +33 -0
- package/_src/ServerRequest/internal.ts +106 -0
- package/_src/ServerRequest.ts +5 -0
- package/_src/ServerResponse/api.ts +177 -0
- package/_src/ServerResponse/definition.ts +51 -0
- package/_src/ServerResponse.ts +5 -0
- package/_src/Socket.ts +294 -0
- package/_src/UrlParams.ts +28 -0
- package/_src/global.ts +2 -0
- package/global.d.ts +1 -0
- package/package.json +27 -0
package/_src/Socket.ts
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import type { AsyncInputProducer } from "@fncts/io/Channel/internal/AsyncInputProducer";
|
|
2
|
+
|
|
3
|
+
import { CauseTag } from "@fncts/base/data/Cause";
|
|
4
|
+
import { WebSocket as IsoWs } from "isows";
|
|
5
|
+
|
|
6
|
+
export const SocketTypeId = Symbol.for("fncts.http.Socket");
|
|
7
|
+
export type SocketTypeId = typeof SocketTypeId;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @tsplus type fncts.http.Socket
|
|
11
|
+
* @tsplus companion fncts.http.SocketOps
|
|
12
|
+
*/
|
|
13
|
+
export abstract class Socket {
|
|
14
|
+
readonly [SocketTypeId]: SocketTypeId = SocketTypeId;
|
|
15
|
+
abstract run<R, E, A>(handler: (_: Uint8Array) => IO<R, E, A>): IO<R, E | SocketError, void>;
|
|
16
|
+
abstract writer: IO<Scope, never, (chunk: Uint8Array | CloseEvent) => UIO<void>>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @tsplus static fncts.http.SocketOps Tag
|
|
21
|
+
*/
|
|
22
|
+
export const SocketTag = Tag<Socket>();
|
|
23
|
+
|
|
24
|
+
export const SocketGenericErrorTypeId = Symbol.for("fncts.http.Socket.SocketGenericError");
|
|
25
|
+
export type SocketGenericErrorTypeId = typeof SocketGenericErrorTypeId;
|
|
26
|
+
|
|
27
|
+
export class SocketGenericError extends Error {
|
|
28
|
+
readonly [SocketGenericErrorTypeId]: SocketGenericErrorTypeId = SocketGenericErrorTypeId;
|
|
29
|
+
constructor(
|
|
30
|
+
readonly reason: "Write" | "Read" | "Open" | "OpenTimeout",
|
|
31
|
+
readonly error: unknown,
|
|
32
|
+
) {
|
|
33
|
+
super();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const SocketCloseErrorTypeId = Symbol.for("fncts.http.Socket.SocketCloseError");
|
|
38
|
+
export type SocketCloseErrorTypeId = typeof SocketCloseErrorTypeId;
|
|
39
|
+
|
|
40
|
+
export class SocketCloseError extends Error {
|
|
41
|
+
readonly [SocketCloseErrorTypeId]: SocketCloseErrorTypeId = SocketCloseErrorTypeId;
|
|
42
|
+
constructor(
|
|
43
|
+
readonly reason: "Close",
|
|
44
|
+
readonly code: number,
|
|
45
|
+
readonly closeReason: string | undefined,
|
|
46
|
+
readonly error: unknown,
|
|
47
|
+
) {
|
|
48
|
+
super();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static isClean(isClean: (code: number) => boolean) {
|
|
52
|
+
return (u: unknown): u is SocketCloseError => {
|
|
53
|
+
return isSocketCloseError(u) && isClean(u.code);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isSocketCloseError(u: unknown): u is SocketCloseError {
|
|
59
|
+
return isObject(u) && SocketCloseErrorTypeId in u;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type SocketError = SocketGenericError | SocketCloseError;
|
|
63
|
+
|
|
64
|
+
export const CloseEventTypeId = Symbol.for("fncts.http.Socket.CloseEvent");
|
|
65
|
+
export type CloseEventTypeId = typeof CloseEventTypeId;
|
|
66
|
+
|
|
67
|
+
export class CloseEvent {
|
|
68
|
+
readonly [CloseEventTypeId]: CloseEventTypeId = CloseEventTypeId;
|
|
69
|
+
constructor(
|
|
70
|
+
readonly code = 1000,
|
|
71
|
+
readonly reason?: string,
|
|
72
|
+
) {}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isCloseEvent(u: unknown): u is CloseEvent {
|
|
76
|
+
return isObject(u) && CloseEventTypeId in u;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @tsplus fluent fncts.http.Socket toChannel
|
|
81
|
+
*/
|
|
82
|
+
export function toChannel<IE>(
|
|
83
|
+
self: Socket,
|
|
84
|
+
): Channel<never, IE, Conc<Uint8Array | CloseEvent>, unknown, SocketError | IE, Conc<Uint8Array>, void> {
|
|
85
|
+
return Channel.unwrap(
|
|
86
|
+
Do((Δ) => {
|
|
87
|
+
const writeScope = Δ(Scope.make);
|
|
88
|
+
const write = Δ(writeScope.extend(self.writer));
|
|
89
|
+
const exitQueue = Δ(Queue.makeUnbounded<Exit<SocketError | IE, Conc<Uint8Array>>>());
|
|
90
|
+
|
|
91
|
+
const input: AsyncInputProducer<IE, Conc<Uint8Array | CloseEvent>, unknown> = {
|
|
92
|
+
awaitRead: IO.unit,
|
|
93
|
+
emit(chunk) {
|
|
94
|
+
return IO.foreachDiscard(chunk, write).catchAllCause((cause) => exitQueue.offer(Exit.failCause(cause)));
|
|
95
|
+
},
|
|
96
|
+
error(error) {
|
|
97
|
+
return writeScope.close(Exit.unit) > exitQueue.offer(Exit.failCause(error));
|
|
98
|
+
},
|
|
99
|
+
done() {
|
|
100
|
+
return writeScope.close(Exit.unit);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
Δ(
|
|
105
|
+
self
|
|
106
|
+
.run((data) => exitQueue.offer(Exit.succeed(Conc.single(data))))
|
|
107
|
+
.zipRight(IO.failCauseNow(Cause.empty<IE | SocketError>()))
|
|
108
|
+
.result.tap((exit) => exitQueue.offer(exit)).fork.interruptible,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const loop: Channel<never, unknown, unknown, unknown, SocketError | IE, Conc<Uint8Array>, void> = Channel.fromIO(
|
|
112
|
+
exitQueue.take,
|
|
113
|
+
).flatMap((exit) =>
|
|
114
|
+
exit.match(
|
|
115
|
+
(cause) => (cause._tag === CauseTag.Empty ? Channel.unit : Channel.failCause(cause)),
|
|
116
|
+
(chunk) => Channel.write(chunk) > loop,
|
|
117
|
+
),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return loop.embedInput(input);
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @tsplus fluent fncts.http.Socket toChannelWith
|
|
127
|
+
*/
|
|
128
|
+
export function toChannelWith<IE = never>(
|
|
129
|
+
self: Socket,
|
|
130
|
+
): Channel<never, IE, Conc<Uint8Array | CloseEvent>, unknown, SocketError | IE, Conc<Uint8Array>, void> {
|
|
131
|
+
return self.toChannel<IE>();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @tsplus companion fncts.http.WebSocketOps
|
|
136
|
+
*/
|
|
137
|
+
export interface WebSocket {
|
|
138
|
+
readonly _: unique symbol;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @tsplus static fncts.http.WebSocketOps Tag
|
|
143
|
+
*/
|
|
144
|
+
export const WebSocketTag = Tag<WebSocket>();
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @tsplus static fncts.http.SocketOps makeWebSocket
|
|
148
|
+
* @tsplus static fncts.http.WebSocketOps __call
|
|
149
|
+
*/
|
|
150
|
+
export function makeWebSocket(
|
|
151
|
+
url: string,
|
|
152
|
+
options?: {
|
|
153
|
+
readonly closeCodeIsError?: (code: number) => boolean;
|
|
154
|
+
readonly openTimeout?: Duration;
|
|
155
|
+
},
|
|
156
|
+
): UIO<Socket> {
|
|
157
|
+
return Socket.fromWebSocket(
|
|
158
|
+
IO.acquireRelease(
|
|
159
|
+
IO(() => {
|
|
160
|
+
if ("WebSocket" in globalThis) {
|
|
161
|
+
return new globalThis.WebSocket(url);
|
|
162
|
+
}
|
|
163
|
+
return new IsoWs(url);
|
|
164
|
+
}),
|
|
165
|
+
(ws) => IO(ws.close()),
|
|
166
|
+
),
|
|
167
|
+
options,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @tsplus static fncts.http.SocketOps fromWebSocket
|
|
173
|
+
*/
|
|
174
|
+
export function fromWebSocket(
|
|
175
|
+
acquire: IO<Scope, SocketError, globalThis.WebSocket>,
|
|
176
|
+
options?: {
|
|
177
|
+
readonly closeCodeIsError?: (code: number) => boolean;
|
|
178
|
+
readonly openTimeout?: Duration;
|
|
179
|
+
},
|
|
180
|
+
): UIO<Socket> {
|
|
181
|
+
return Do((Δ) => {
|
|
182
|
+
const closeCodeIsError = options?.closeCodeIsError ?? ((code) => code !== 1000 && code !== 1006);
|
|
183
|
+
const sendQueue = Δ(Queue.makeUnbounded<Uint8Array | CloseEvent>());
|
|
184
|
+
const run = <R, E>(handler: (_: Uint8Array) => IO<R, E, any>) =>
|
|
185
|
+
Do((Δ) => {
|
|
186
|
+
const ws = Δ(acquire);
|
|
187
|
+
const encoder = new TextEncoder();
|
|
188
|
+
const fiberSet = Δ(FiberSet.make<E | SocketError, any>());
|
|
189
|
+
const run = Δ(
|
|
190
|
+
fiberSet.runtime<E | SocketError, any, R>().provideSomeService(ws as unknown as WebSocket, WebSocket.Tag),
|
|
191
|
+
);
|
|
192
|
+
let open = false;
|
|
193
|
+
ws.onmessage = (event) => {
|
|
194
|
+
run(
|
|
195
|
+
handler(
|
|
196
|
+
event.data instanceof Uint8Array
|
|
197
|
+
? event.data
|
|
198
|
+
: typeof event.data === "string"
|
|
199
|
+
? encoder.encode(event.data)
|
|
200
|
+
: new Uint8Array(event.data),
|
|
201
|
+
),
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
ws.onclose = (event) => {
|
|
206
|
+
fiberSet.future.unsafeDone(IO.fail(new SocketCloseError("Close", event.code, event.reason, undefined)));
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
ws.onerror = (error) => {
|
|
210
|
+
fiberSet.future.unsafeDone(IO.fail(new SocketGenericError(open ? "Read" : "Open", error)));
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
Δ(
|
|
214
|
+
IO.defer(() => {
|
|
215
|
+
if (ws.readyState !== 1) {
|
|
216
|
+
return IO.async<never, SocketError, void>((resume) => {
|
|
217
|
+
ws.onopen = () => {
|
|
218
|
+
resume(IO.unit);
|
|
219
|
+
};
|
|
220
|
+
})
|
|
221
|
+
.timeoutFail(
|
|
222
|
+
options?.openTimeout ?? (10).seconds,
|
|
223
|
+
new SocketGenericError("OpenTimeout", 'timeout waiting for "open"'),
|
|
224
|
+
)
|
|
225
|
+
.raceFirst(fiberSet.join);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return IO.unit;
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
Δ(IO((open = true)));
|
|
233
|
+
|
|
234
|
+
Δ(
|
|
235
|
+
fiberSet.run(
|
|
236
|
+
sendQueue.take.tap((chunk) => {
|
|
237
|
+
if (isCloseEvent(chunk)) {
|
|
238
|
+
return IO.fail(() => {
|
|
239
|
+
ws.close(chunk.code, chunk.reason);
|
|
240
|
+
return new SocketCloseError("Close", chunk.code, chunk.reason, chunk);
|
|
241
|
+
});
|
|
242
|
+
} else {
|
|
243
|
+
return IO.tryCatch(ws.send(chunk), (error) => new SocketGenericError("Write", error));
|
|
244
|
+
}
|
|
245
|
+
}).forever,
|
|
246
|
+
),
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
Δ(
|
|
250
|
+
fiberSet.join.catchJust(
|
|
251
|
+
Maybe.partial(
|
|
252
|
+
(miss) => (error) =>
|
|
253
|
+
SocketCloseError.isClean((code) => !closeCodeIsError(code))(error) ? IO.unit : miss(),
|
|
254
|
+
),
|
|
255
|
+
),
|
|
256
|
+
);
|
|
257
|
+
}).scoped.interruptible;
|
|
258
|
+
|
|
259
|
+
const write = (chunk: Uint8Array | CloseEvent) => sendQueue.offer(chunk);
|
|
260
|
+
|
|
261
|
+
const writer = IO(() => write);
|
|
262
|
+
|
|
263
|
+
return new (class extends Socket {
|
|
264
|
+
writer = writer;
|
|
265
|
+
run = run;
|
|
266
|
+
})();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @tsplus static fncts.http.SocketOps makeWebSocketChannel
|
|
272
|
+
* @tsplus static fncts.http.WebSocketOps makeChannel
|
|
273
|
+
*/
|
|
274
|
+
export function makeWebSocketChannel<IE = never>(
|
|
275
|
+
url: string,
|
|
276
|
+
options?: {
|
|
277
|
+
readonly closeCodeIsError?: (code: number) => boolean;
|
|
278
|
+
},
|
|
279
|
+
): Channel<never, IE, Conc<Uint8Array>, unknown, IE | SocketError, Conc<Uint8Array | string | CloseEvent>, void> {
|
|
280
|
+
return Channel.unwrap(makeWebSocket(url, options).map((socket) => socket.toChannel<IE>()));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @tsplus static fncts.http.SocketOps liveWebSocket
|
|
285
|
+
* @tsplus static fncts.http.WebSocketOps live
|
|
286
|
+
*/
|
|
287
|
+
export function live(
|
|
288
|
+
url: string,
|
|
289
|
+
options?: {
|
|
290
|
+
readonly closeCodeIsError?: (code: number) => boolean;
|
|
291
|
+
},
|
|
292
|
+
): Layer<never, never, Socket> {
|
|
293
|
+
return Layer.scoped(WebSocket(url, options), Socket.Tag);
|
|
294
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tsplus type fncts.http.UrlParams
|
|
3
|
+
* @tsplus type fncts.http.UrlParamsOps
|
|
4
|
+
*/
|
|
5
|
+
export class UrlParams {
|
|
6
|
+
constructor(readonly backing: ReadonlyArray<readonly [string, string]>) {}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export declare module UrlParams {
|
|
10
|
+
export type Input = Readonly<Record<string, string>> | Iterable<readonly [string, string]> | URLSearchParams;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @tsplus static fncts.http.UrlParamsOps __call
|
|
15
|
+
*/
|
|
16
|
+
export function make(input: UrlParams.Input): UrlParams {
|
|
17
|
+
if (Symbol.iterator in input) {
|
|
18
|
+
return new UrlParams(Array.from(input));
|
|
19
|
+
}
|
|
20
|
+
return new UrlParams(Array.from(Object.entries(input)));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @tsplus fluent fncts.http.UrlParams toString
|
|
25
|
+
*/
|
|
26
|
+
export function toString(self: UrlParams): string {
|
|
27
|
+
return new URLSearchParams(self.backing as Array<[string, string]>).toString();
|
|
28
|
+
}
|
package/_src/global.ts
ADDED
package/global.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fncts/http",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@fncts/base": "0.0.33",
|
|
6
|
+
"@fncts/io": "0.0.41",
|
|
7
|
+
"@fncts/schema": "0.0.13",
|
|
8
|
+
"@fncts/typelevel": "0.0.16",
|
|
9
|
+
"find-my-way": "^8.1.0",
|
|
10
|
+
"find-my-way-ts": "^0.1.1",
|
|
11
|
+
"isows": "^1.0.4",
|
|
12
|
+
"uuid": "^9.0.1"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
"./*": {
|
|
16
|
+
"import": "./_mjs/*.mjs",
|
|
17
|
+
"require": "./_cjs/*.cjs"
|
|
18
|
+
},
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./_mjs/index.mjs",
|
|
21
|
+
"require": "./_cjs/index.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
}
|
|
27
|
+
}
|