@noita-ts/pollnet 0.2.0 → 0.3.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/async.d.ts CHANGED
@@ -1,31 +1,73 @@
1
- import pollnet from "./index";
2
- /**
3
- * Run `body` inside a reactor coroutine and get its completion as a Promise.
4
- * `body` may freely use socket.await() / other yield-based pollnet APIs.
5
- * Errors inside body reject the promise.
6
- */
7
- export declare const spawn: <T>(reactor: pollnet.Reactor, body: () => T) => Promise<T>;
1
+ import pollnet from ".";
2
+ export declare namespace compat {
3
+ /**
4
+ * Run `body` inside a reactor coroutine and get its completion as a Promise.
5
+ * `body` may freely use socket.await() / other yield-based pollnet APIs.
6
+ * Errors inside body reject the promise.
7
+ */
8
+ const asyncify: <T>(reactor: pollnet.Reactor, body: () => T) => Promise<T>;
9
+ /**
10
+ * Parks the *current coroutine* until the promise settles, then returns its
11
+ * value or rethrows its rejection.
12
+ * Only call from inside a reactor coroutine (`reactor.run(() => { .. HERE .. })`).
13
+ */
14
+ const yieldPromise: <T>(p: Promise<T>) => T;
15
+ }
8
16
  /**
9
- * Parks the *current coroutine* until the promise settles, then returns its
10
- * value or rethrows its rejection.
11
- * Only call from inside a reactor coroutine (`reactor.run(() => { .. HERE .. })`).
17
+ * Promise-friendly wrapper around a {@link pollnet.Reactor}.
18
+ *
19
+ * Lets you drive yield-based pollnet coroutines while exposing their results
20
+ * as Promises. Call {@link poll} regularly (e.g. once per frame) to advance
21
+ * all running coroutines.
12
22
  */
13
- export declare const blockOn: <T>(p: Promise<T>) => T;
23
+ export declare class AsyncReactor {
24
+ private reactor;
25
+ constructor();
26
+ /**
27
+ * Advance every coroutine currently running on the reactor by one step.
28
+ * Must be called periodically for spawned work to make progress.
29
+ */
30
+ poll(): number;
31
+ /**
32
+ * Run `body` as a reactor coroutine and return its result as a Promise.
33
+ * `body` may use yield-based pollnet APIs (e.g. `socket.await()`).
34
+ */
35
+ spawn<T>(body: () => T): Promise<T>;
36
+ /**
37
+ * Async version of `pollnet.Reactor.run_server`.
38
+ *
39
+ * Accept connections on `server_sock`, spawning a coroutine that runs
40
+ * `client_body` for each incoming client. `client_body` receives the client
41
+ * socket and its remote address, and may itself return a Promise which the
42
+ * coroutine parks on until it settles.
43
+ */
44
+ runServer(server_sock: pollnet.Socket, client_body: (sock: pollnet.Socket, addr: string) => Promise<void>): void;
45
+ }
14
46
  export declare class HttpResponse {
15
47
  status: number;
16
48
  headers: string;
17
49
  body: string;
18
50
  constructor(status: number, headers: string, body: string);
51
+ /**
52
+ * Parse the raw header block into a map.
53
+ * Header names seen more than once collapse into an array of their values, in
54
+ * order.
55
+ */
19
56
  parseHeaders(): Record<string, string | string[]>;
20
57
  }
21
- export default class AsyncReactor {
58
+ /**
59
+ * Tiny async HTTP client built on top of an {@link AsyncReactor}.
60
+ * Requests run as reactor coroutines and resolve to an {@link HttpResponse}.
61
+ */
62
+ export declare class HttpClient {
22
63
  private reactor;
23
- constructor();
24
- update(): number;
25
- /** Runs a coroutine thread */
26
- run(thread_body: (this: pollnet.Reactor) => void): void;
27
- /** Runs a server with client handler */
28
- run_server(server_sock: pollnet.Socket, client_body: (sock: pollnet.Socket, addr: string) => void): void;
29
- http_get(url: string, headers?: Record<string, string | string[]> | string): Promise<HttpResponse>;
30
- http_post(url: string, headers?: Record<string, string | string[]> | string, body?: string): Promise<HttpResponse>;
64
+ constructor(reactor: AsyncReactor);
65
+ /**
66
+ * Perform an HTTP GET.
67
+ */
68
+ get(url: string, headers?: Record<string, string | string[]> | string): Promise<HttpResponse>;
69
+ /**
70
+ * Perform an HTTP POST with an optional request `body`.
71
+ */
72
+ post(url: string, headers?: Record<string, string | string[]> | string, body?: string): Promise<HttpResponse>;
31
73
  }
package/dist/async.lua CHANGED
@@ -11,61 +11,91 @@ local SyntaxError = ____lualib.SyntaxError
11
11
  local TypeError = ____lualib.TypeError
12
12
  local URIError = ____lualib.URIError
13
13
  local ____exports = {}
14
- local ____index = require("index")
15
- local pollnet = ____index.default
16
- --- Run `body` inside a reactor coroutine and get its completion as a Promise.
17
- -- `body` may freely use socket.await() / other yield-based pollnet APIs.
18
- -- Errors inside body reject the promise.
19
- ____exports.spawn = function(____, reactor, body)
20
- return __TS__New(
21
- __TS__Promise,
22
- function(____, resolve, reject)
23
- reactor:run(function()
24
- do
25
- local function ____catch(e)
26
- reject(nil, e)
14
+ local _____2E = require("index")
15
+ local pollnet = _____2E.default
16
+ ____exports.compat = {}
17
+ local compat = ____exports.compat
18
+ do
19
+ --- Run `body` inside a reactor coroutine and get its completion as a Promise.
20
+ -- `body` may freely use socket.await() / other yield-based pollnet APIs.
21
+ -- Errors inside body reject the promise.
22
+ compat.asyncify = function(____, reactor, body)
23
+ return __TS__New(
24
+ __TS__Promise,
25
+ function(____, resolve, reject)
26
+ reactor:run(function()
27
+ do
28
+ local function ____catch(e)
29
+ reject(nil, e)
30
+ end
31
+ local ____try, ____hasReturned = pcall(function()
32
+ resolve(
33
+ nil,
34
+ body(nil)
35
+ )
36
+ end)
37
+ if not ____try then
38
+ ____catch(____hasReturned)
39
+ end
27
40
  end
28
- local ____try, ____hasReturned = pcall(function()
29
- resolve(
30
- nil,
31
- body(nil)
32
- )
33
- end)
34
- if not ____try then
35
- ____catch(____hasReturned)
36
- end
37
- end
38
- end)
41
+ end)
42
+ end
43
+ )
44
+ end
45
+ --- Parks the *current coroutine* until the promise settles, then returns its
46
+ -- value or rethrows its rejection.
47
+ -- Only call from inside a reactor coroutine (`reactor.run(() => { .. HERE .. })`).
48
+ compat.yieldPromise = function(____, p)
49
+ local done = false
50
+ local ok = false
51
+ local result
52
+ p["then"](
53
+ p,
54
+ function(____, v)
55
+ done = true
56
+ ok = true
57
+ result = v
58
+ end,
59
+ function(____, e)
60
+ done = true
61
+ ok = false
62
+ result = e
63
+ end
64
+ )
65
+ while not done do
66
+ coroutine.yield()
39
67
  end
40
- )
41
- end
42
- --- Parks the *current coroutine* until the promise settles, then returns its
43
- -- value or rethrows its rejection.
44
- -- Only call from inside a reactor coroutine (`reactor.run(() => { .. HERE .. })`).
45
- ____exports.blockOn = function(____, p)
46
- local done = false
47
- local ok = false
48
- local result
49
- p["then"](
50
- p,
51
- function(____, v)
52
- done = true
53
- ok = true
54
- result = v
55
- end,
56
- function(____, e)
57
- done = true
58
- ok = false
59
- result = e
68
+ if not ok then
69
+ error(result, 0)
60
70
  end
61
- )
62
- while not done do
63
- coroutine.yield()
64
- end
65
- if not ok then
66
- error(result, 0)
71
+ return result
67
72
  end
68
- return result
73
+ end
74
+ --- Promise-friendly wrapper around a {@link pollnet.Reactor}.
75
+ --
76
+ -- Lets you drive yield-based pollnet coroutines while exposing their results
77
+ -- as Promises. Call {@link poll} regularly (e.g. once per frame) to advance
78
+ -- all running coroutines.
79
+ ____exports.AsyncReactor = __TS__Class()
80
+ local AsyncReactor = ____exports.AsyncReactor
81
+ AsyncReactor.name = "AsyncReactor"
82
+ function AsyncReactor.prototype.____constructor(self)
83
+ self.reactor = pollnet.Reactor()
84
+ end
85
+ function AsyncReactor.prototype.poll(self)
86
+ return self.reactor:update()
87
+ end
88
+ function AsyncReactor.prototype.spawn(self, body)
89
+ return ____exports.compat:asyncify(self.reactor, body)
90
+ end
91
+ function AsyncReactor.prototype.runServer(self, server_sock, client_body)
92
+ server_sock:on_connection(function(client_sock, addr)
93
+ self.reactor:run(function() return ____exports.compat:yieldPromise(client_body(nil, client_sock, addr)) end)
94
+ end)
95
+ self.reactor:run(function()
96
+ while (server_sock:await()) do
97
+ end
98
+ end)
69
99
  end
70
100
  ____exports.HttpResponse = __TS__Class()
71
101
  local HttpResponse = ____exports.HttpResponse
@@ -85,12 +115,12 @@ function HttpResponse.prototype.parseHeaders(self)
85
115
  2
86
116
  )
87
117
  if not key or not value then
88
- goto __continue14
118
+ goto __continue23
89
119
  end
90
120
  local prev = headers[key]
91
121
  if not prev then
92
122
  headers[key] = value
93
- goto __continue14
123
+ goto __continue23
94
124
  end
95
125
  if __TS__ArrayIsArray(prev) then
96
126
  prev[#prev + 1] = value
@@ -98,61 +128,46 @@ function HttpResponse.prototype.parseHeaders(self)
98
128
  headers[key] = {prev, value}
99
129
  end
100
130
  end
101
- ::__continue14::
131
+ ::__continue23::
102
132
  end
103
133
  return headers
104
134
  end
105
- ____exports.default = __TS__Class()
106
- local AsyncReactor = ____exports.default
107
- AsyncReactor.name = "AsyncReactor"
108
- function AsyncReactor.prototype.____constructor(self)
109
- self.reactor = pollnet.Reactor()
110
- end
111
- function AsyncReactor.prototype.update(self)
112
- return self.reactor:update()
135
+ --- Tiny async HTTP client built on top of an {@link AsyncReactor}.
136
+ -- Requests run as reactor coroutines and resolve to an {@link HttpResponse}.
137
+ ____exports.HttpClient = __TS__Class()
138
+ local HttpClient = ____exports.HttpClient
139
+ HttpClient.name = "HttpClient"
140
+ function HttpClient.prototype.____constructor(self, reactor)
141
+ self.reactor = reactor
113
142
  end
114
- function AsyncReactor.prototype.run(self, thread_body)
115
- self.reactor:run(thread_body)
116
- end
117
- function AsyncReactor.prototype.run_server(self, server_sock, client_body)
118
- self.reactor:run_server(server_sock, client_body)
119
- end
120
- function AsyncReactor.prototype.http_get(self, url, headers)
121
- return ____exports.spawn(
122
- nil,
123
- self.reactor,
124
- function()
125
- local socket = pollnet.http_get(url, headers, false)
126
- local msgs, ____error = socket:await_n(3)
127
- if not msgs then
128
- error(
129
- __TS__New(Error, "socket error: " .. ____error),
130
- 0
131
- )
132
- end
133
- local statusStr, headersStr, respBody = unpack(msgs, 1, 3)
134
- local status = tonumber({string.match("^%d+", statusStr)}) or 500
135
- return __TS__New(____exports.HttpResponse, status, headersStr, respBody)
143
+ function HttpClient.prototype.get(self, url, headers)
144
+ return self.reactor:spawn(function()
145
+ local socket = pollnet.http_get(url, headers, false)
146
+ local msgs, ____error = socket:await_n(3)
147
+ if not msgs then
148
+ error(
149
+ __TS__New(Error, "socket error: " .. ____error),
150
+ 0
151
+ )
136
152
  end
137
- )
153
+ local statusStr, headersStr, respBody = unpack(msgs, 1, 3)
154
+ local status = tonumber({string.match("^%d+", statusStr)}) or 500
155
+ return __TS__New(____exports.HttpResponse, status, headersStr, respBody)
156
+ end)
138
157
  end
139
- function AsyncReactor.prototype.http_post(self, url, headers, body)
140
- return ____exports.spawn(
141
- nil,
142
- self.reactor,
143
- function()
144
- local socket = pollnet.http_post(url, headers, body, false)
145
- local msgs, ____error = socket:await_n(3)
146
- if not msgs then
147
- error(
148
- __TS__New(Error, "socket error: " .. ____error),
149
- 0
150
- )
151
- end
152
- local statusStr, headersStr, respBody = unpack(msgs, 1, 3)
153
- local status = tonumber({string.match("^%d+", statusStr)}) or 500
154
- return __TS__New(____exports.HttpResponse, status, headersStr, respBody)
158
+ function HttpClient.prototype.post(self, url, headers, body)
159
+ return self.reactor:spawn(function()
160
+ local socket = pollnet.http_post(url, headers, body, false)
161
+ local msgs, ____error = socket:await_n(3)
162
+ if not msgs then
163
+ error(
164
+ __TS__New(Error, "socket error: " .. ____error),
165
+ 0
166
+ )
155
167
  end
156
- )
168
+ local statusStr, headersStr, respBody = unpack(msgs, 1, 3)
169
+ local status = tonumber({string.match("^%d+", statusStr)}) or 500
170
+ return __TS__New(____exports.HttpResponse, status, headersStr, respBody)
171
+ end)
157
172
  end
158
173
  return ____exports