better-call 0.2.13-beta.2 → 0.2.13-beta.4
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/README.md +7 -1
- package/dist/adapter/node.cjs +210 -0
- package/dist/adapter/node.d.cts +19 -0
- package/dist/adapter/node.d.mts +19 -0
- package/dist/adapter/node.d.ts +19 -0
- package/dist/adapter/node.mjs +206 -0
- package/dist/client.d.cts +4 -4
- package/dist/client.d.mts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/index.cjs +94 -20
- package/dist/index.d.cts +19 -2
- package/dist/index.d.mts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.mjs +95 -20
- package/dist/shared/{better-call.342be6c5.d.cts → better-call.7c5f7404.d.cts} +335 -59
- package/dist/shared/{better-call.342be6c5.d.mts → better-call.7c5f7404.d.mts} +335 -59
- package/dist/shared/{better-call.342be6c5.d.ts → better-call.7c5f7404.d.ts} +335 -59
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
# Better Call
|
|
2
2
|
|
|
3
|
-
A tiny TypeScript web framework that lets you create endpoints that can be called like regular functions, while also serving as REST API endpoints. It comes with a very fast router
|
|
3
|
+
A tiny TypeScript web framework that lets you create endpoints that can be called like regular functions, while also serving as REST API endpoints. It comes with a very fast router [rou3](https://github.com/unjs/rou3), and an RPC client powered by [better-fetch](https://better-fetch.vercel.app) and open API generator (experimental).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm i better-call
|
|
9
|
+
```
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function splitCookiesString(cookiesString) {
|
|
4
|
+
if (Array.isArray(cookiesString)) {
|
|
5
|
+
return cookiesString;
|
|
6
|
+
}
|
|
7
|
+
if (typeof cookiesString !== "string") {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const cookiesStrings = [];
|
|
11
|
+
let pos = 0;
|
|
12
|
+
let start;
|
|
13
|
+
let ch;
|
|
14
|
+
let lastComma;
|
|
15
|
+
let nextStart;
|
|
16
|
+
let cookiesSeparatorFound;
|
|
17
|
+
function skipWhitespace() {
|
|
18
|
+
if (Array.isArray(cookiesString)) {
|
|
19
|
+
return pos < cookiesString.length;
|
|
20
|
+
}
|
|
21
|
+
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
|
22
|
+
pos += 1;
|
|
23
|
+
}
|
|
24
|
+
return pos < cookiesString.length;
|
|
25
|
+
}
|
|
26
|
+
function notSpecialChar() {
|
|
27
|
+
if (Array.isArray(cookiesString)) {
|
|
28
|
+
return pos < cookiesString.length;
|
|
29
|
+
}
|
|
30
|
+
ch = cookiesString.charAt(pos);
|
|
31
|
+
return ch !== "=" && ch !== ";" && ch !== ",";
|
|
32
|
+
}
|
|
33
|
+
while (pos < cookiesString.length) {
|
|
34
|
+
start = pos;
|
|
35
|
+
cookiesSeparatorFound = false;
|
|
36
|
+
while (skipWhitespace()) {
|
|
37
|
+
ch = cookiesString.charAt(pos);
|
|
38
|
+
if (ch === ",") {
|
|
39
|
+
lastComma = pos;
|
|
40
|
+
pos += 1;
|
|
41
|
+
skipWhitespace();
|
|
42
|
+
nextStart = pos;
|
|
43
|
+
while (pos < cookiesString.length && notSpecialChar()) {
|
|
44
|
+
pos += 1;
|
|
45
|
+
}
|
|
46
|
+
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
|
47
|
+
cookiesSeparatorFound = true;
|
|
48
|
+
pos = nextStart;
|
|
49
|
+
cookiesStrings.push(cookiesString.substring(start, lastComma));
|
|
50
|
+
start = pos;
|
|
51
|
+
} else {
|
|
52
|
+
pos = lastComma + 1;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
pos += 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
|
59
|
+
cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return cookiesStrings;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function get_raw_body(req, body_size_limit) {
|
|
66
|
+
const h = req.headers;
|
|
67
|
+
if (!h["content-type"])
|
|
68
|
+
return null;
|
|
69
|
+
const content_length = Number(h["content-length"]);
|
|
70
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
let length = content_length;
|
|
74
|
+
if (body_size_limit) {
|
|
75
|
+
if (!length) {
|
|
76
|
+
length = body_size_limit;
|
|
77
|
+
} else if (length > body_size_limit) {
|
|
78
|
+
throw Error(
|
|
79
|
+
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (req.destroyed) {
|
|
84
|
+
const readable = new ReadableStream();
|
|
85
|
+
readable.cancel();
|
|
86
|
+
return readable;
|
|
87
|
+
}
|
|
88
|
+
let size = 0;
|
|
89
|
+
let cancelled = false;
|
|
90
|
+
return new ReadableStream({
|
|
91
|
+
start(controller) {
|
|
92
|
+
req.on("error", (error) => {
|
|
93
|
+
cancelled = true;
|
|
94
|
+
controller.error(error);
|
|
95
|
+
});
|
|
96
|
+
req.on("end", () => {
|
|
97
|
+
if (cancelled)
|
|
98
|
+
return;
|
|
99
|
+
controller.close();
|
|
100
|
+
});
|
|
101
|
+
req.on("data", (chunk) => {
|
|
102
|
+
if (cancelled)
|
|
103
|
+
return;
|
|
104
|
+
size += chunk.length;
|
|
105
|
+
if (size > length) {
|
|
106
|
+
cancelled = true;
|
|
107
|
+
controller.error(
|
|
108
|
+
new Error(
|
|
109
|
+
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
controller.enqueue(chunk);
|
|
115
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
116
|
+
req.pause();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
pull() {
|
|
121
|
+
req.resume();
|
|
122
|
+
},
|
|
123
|
+
cancel(reason) {
|
|
124
|
+
cancelled = true;
|
|
125
|
+
req.destroy(reason);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function getRequest({
|
|
130
|
+
request,
|
|
131
|
+
base,
|
|
132
|
+
bodySizeLimit
|
|
133
|
+
}) {
|
|
134
|
+
return new Request(base + request.url, {
|
|
135
|
+
duplex: "half",
|
|
136
|
+
method: request.method,
|
|
137
|
+
body: get_raw_body(request, bodySizeLimit),
|
|
138
|
+
headers: request.headers
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async function setResponse(res, response) {
|
|
142
|
+
for (const [key, value] of response.headers) {
|
|
143
|
+
try {
|
|
144
|
+
res.setHeader(
|
|
145
|
+
key,
|
|
146
|
+
key === "set-cookie" ? splitCookiesString(response.headers.get(key)) : value
|
|
147
|
+
);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
150
|
+
res.writeHead(500).end(String(error));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
res.writeHead(response.status);
|
|
155
|
+
if (!response.body) {
|
|
156
|
+
res.end();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (response.body.locked) {
|
|
160
|
+
res.end(
|
|
161
|
+
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
162
|
+
);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const reader = response.body.getReader();
|
|
166
|
+
if (res.destroyed) {
|
|
167
|
+
reader.cancel();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const cancel = (error) => {
|
|
171
|
+
res.off("close", cancel);
|
|
172
|
+
res.off("error", cancel);
|
|
173
|
+
reader.cancel(error).catch(() => {
|
|
174
|
+
});
|
|
175
|
+
if (error)
|
|
176
|
+
res.destroy(error);
|
|
177
|
+
};
|
|
178
|
+
res.on("close", cancel);
|
|
179
|
+
res.on("error", cancel);
|
|
180
|
+
next();
|
|
181
|
+
async function next() {
|
|
182
|
+
try {
|
|
183
|
+
for (; ; ) {
|
|
184
|
+
const { done, value } = await reader.read();
|
|
185
|
+
if (done)
|
|
186
|
+
break;
|
|
187
|
+
if (!res.write(value)) {
|
|
188
|
+
res.once("drain", next);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
res.end();
|
|
193
|
+
} catch (error) {
|
|
194
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function toNodeHandler(handler) {
|
|
200
|
+
return async (req, res) => {
|
|
201
|
+
const protocol = req.connection?.encrypted ? "https" : "http";
|
|
202
|
+
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
203
|
+
const response = await handler(getRequest({ base, request: req }));
|
|
204
|
+
setResponse(res, response);
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
exports.getRequest = getRequest;
|
|
209
|
+
exports.setResponse = setResponse;
|
|
210
|
+
exports.toNodeHandler = toNodeHandler;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import * as undici_types from 'undici-types';
|
|
3
|
+
import { R as Router } from '../shared/better-call.7c5f7404.cjs';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi';
|
|
7
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
8
|
+
import 'stream/web';
|
|
9
|
+
|
|
10
|
+
declare function getRequest({ request, base, bodySizeLimit, }: {
|
|
11
|
+
base: string;
|
|
12
|
+
bodySizeLimit?: number;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
}): undici_types.Request;
|
|
15
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
16
|
+
|
|
17
|
+
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
18
|
+
|
|
19
|
+
export { getRequest, setResponse, toNodeHandler };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import * as undici_types from 'undici-types';
|
|
3
|
+
import { R as Router } from '../shared/better-call.7c5f7404.mjs';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi';
|
|
7
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
8
|
+
import 'stream/web';
|
|
9
|
+
|
|
10
|
+
declare function getRequest({ request, base, bodySizeLimit, }: {
|
|
11
|
+
base: string;
|
|
12
|
+
bodySizeLimit?: number;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
}): undici_types.Request;
|
|
15
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
16
|
+
|
|
17
|
+
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
18
|
+
|
|
19
|
+
export { getRequest, setResponse, toNodeHandler };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import * as undici_types from 'undici-types';
|
|
3
|
+
import { R as Router } from '../shared/better-call.7c5f7404.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi';
|
|
7
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
8
|
+
import 'stream/web';
|
|
9
|
+
|
|
10
|
+
declare function getRequest({ request, base, bodySizeLimit, }: {
|
|
11
|
+
base: string;
|
|
12
|
+
bodySizeLimit?: number;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
}): undici_types.Request;
|
|
15
|
+
declare function setResponse(res: ServerResponse, response: Response): Promise<void>;
|
|
16
|
+
|
|
17
|
+
declare function toNodeHandler(handler: Router["handler"]): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
18
|
+
|
|
19
|
+
export { getRequest, setResponse, toNodeHandler };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
function splitCookiesString(cookiesString) {
|
|
2
|
+
if (Array.isArray(cookiesString)) {
|
|
3
|
+
return cookiesString;
|
|
4
|
+
}
|
|
5
|
+
if (typeof cookiesString !== "string") {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const cookiesStrings = [];
|
|
9
|
+
let pos = 0;
|
|
10
|
+
let start;
|
|
11
|
+
let ch;
|
|
12
|
+
let lastComma;
|
|
13
|
+
let nextStart;
|
|
14
|
+
let cookiesSeparatorFound;
|
|
15
|
+
function skipWhitespace() {
|
|
16
|
+
if (Array.isArray(cookiesString)) {
|
|
17
|
+
return pos < cookiesString.length;
|
|
18
|
+
}
|
|
19
|
+
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
|
20
|
+
pos += 1;
|
|
21
|
+
}
|
|
22
|
+
return pos < cookiesString.length;
|
|
23
|
+
}
|
|
24
|
+
function notSpecialChar() {
|
|
25
|
+
if (Array.isArray(cookiesString)) {
|
|
26
|
+
return pos < cookiesString.length;
|
|
27
|
+
}
|
|
28
|
+
ch = cookiesString.charAt(pos);
|
|
29
|
+
return ch !== "=" && ch !== ";" && ch !== ",";
|
|
30
|
+
}
|
|
31
|
+
while (pos < cookiesString.length) {
|
|
32
|
+
start = pos;
|
|
33
|
+
cookiesSeparatorFound = false;
|
|
34
|
+
while (skipWhitespace()) {
|
|
35
|
+
ch = cookiesString.charAt(pos);
|
|
36
|
+
if (ch === ",") {
|
|
37
|
+
lastComma = pos;
|
|
38
|
+
pos += 1;
|
|
39
|
+
skipWhitespace();
|
|
40
|
+
nextStart = pos;
|
|
41
|
+
while (pos < cookiesString.length && notSpecialChar()) {
|
|
42
|
+
pos += 1;
|
|
43
|
+
}
|
|
44
|
+
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
|
45
|
+
cookiesSeparatorFound = true;
|
|
46
|
+
pos = nextStart;
|
|
47
|
+
cookiesStrings.push(cookiesString.substring(start, lastComma));
|
|
48
|
+
start = pos;
|
|
49
|
+
} else {
|
|
50
|
+
pos = lastComma + 1;
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
pos += 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
|
57
|
+
cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return cookiesStrings;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function get_raw_body(req, body_size_limit) {
|
|
64
|
+
const h = req.headers;
|
|
65
|
+
if (!h["content-type"])
|
|
66
|
+
return null;
|
|
67
|
+
const content_length = Number(h["content-length"]);
|
|
68
|
+
if (req.httpVersionMajor === 1 && isNaN(content_length) && h["transfer-encoding"] == null || content_length === 0) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
let length = content_length;
|
|
72
|
+
if (body_size_limit) {
|
|
73
|
+
if (!length) {
|
|
74
|
+
length = body_size_limit;
|
|
75
|
+
} else if (length > body_size_limit) {
|
|
76
|
+
throw Error(
|
|
77
|
+
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (req.destroyed) {
|
|
82
|
+
const readable = new ReadableStream();
|
|
83
|
+
readable.cancel();
|
|
84
|
+
return readable;
|
|
85
|
+
}
|
|
86
|
+
let size = 0;
|
|
87
|
+
let cancelled = false;
|
|
88
|
+
return new ReadableStream({
|
|
89
|
+
start(controller) {
|
|
90
|
+
req.on("error", (error) => {
|
|
91
|
+
cancelled = true;
|
|
92
|
+
controller.error(error);
|
|
93
|
+
});
|
|
94
|
+
req.on("end", () => {
|
|
95
|
+
if (cancelled)
|
|
96
|
+
return;
|
|
97
|
+
controller.close();
|
|
98
|
+
});
|
|
99
|
+
req.on("data", (chunk) => {
|
|
100
|
+
if (cancelled)
|
|
101
|
+
return;
|
|
102
|
+
size += chunk.length;
|
|
103
|
+
if (size > length) {
|
|
104
|
+
cancelled = true;
|
|
105
|
+
controller.error(
|
|
106
|
+
new Error(
|
|
107
|
+
`request body size exceeded ${content_length ? "'content-length'" : "BODY_SIZE_LIMIT"} of ${length}`
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
controller.enqueue(chunk);
|
|
113
|
+
if (controller.desiredSize === null || controller.desiredSize <= 0) {
|
|
114
|
+
req.pause();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
pull() {
|
|
119
|
+
req.resume();
|
|
120
|
+
},
|
|
121
|
+
cancel(reason) {
|
|
122
|
+
cancelled = true;
|
|
123
|
+
req.destroy(reason);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function getRequest({
|
|
128
|
+
request,
|
|
129
|
+
base,
|
|
130
|
+
bodySizeLimit
|
|
131
|
+
}) {
|
|
132
|
+
return new Request(base + request.url, {
|
|
133
|
+
duplex: "half",
|
|
134
|
+
method: request.method,
|
|
135
|
+
body: get_raw_body(request, bodySizeLimit),
|
|
136
|
+
headers: request.headers
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async function setResponse(res, response) {
|
|
140
|
+
for (const [key, value] of response.headers) {
|
|
141
|
+
try {
|
|
142
|
+
res.setHeader(
|
|
143
|
+
key,
|
|
144
|
+
key === "set-cookie" ? splitCookiesString(response.headers.get(key)) : value
|
|
145
|
+
);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
res.getHeaderNames().forEach((name) => res.removeHeader(name));
|
|
148
|
+
res.writeHead(500).end(String(error));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
res.writeHead(response.status);
|
|
153
|
+
if (!response.body) {
|
|
154
|
+
res.end();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (response.body.locked) {
|
|
158
|
+
res.end(
|
|
159
|
+
"Fatal error: Response body is locked. This can happen when the response was already read (for example through 'response.json()' or 'response.text()')."
|
|
160
|
+
);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const reader = response.body.getReader();
|
|
164
|
+
if (res.destroyed) {
|
|
165
|
+
reader.cancel();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const cancel = (error) => {
|
|
169
|
+
res.off("close", cancel);
|
|
170
|
+
res.off("error", cancel);
|
|
171
|
+
reader.cancel(error).catch(() => {
|
|
172
|
+
});
|
|
173
|
+
if (error)
|
|
174
|
+
res.destroy(error);
|
|
175
|
+
};
|
|
176
|
+
res.on("close", cancel);
|
|
177
|
+
res.on("error", cancel);
|
|
178
|
+
next();
|
|
179
|
+
async function next() {
|
|
180
|
+
try {
|
|
181
|
+
for (; ; ) {
|
|
182
|
+
const { done, value } = await reader.read();
|
|
183
|
+
if (done)
|
|
184
|
+
break;
|
|
185
|
+
if (!res.write(value)) {
|
|
186
|
+
res.once("drain", next);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
res.end();
|
|
191
|
+
} catch (error) {
|
|
192
|
+
cancel(error instanceof Error ? error : new Error(String(error)));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function toNodeHandler(handler) {
|
|
198
|
+
return async (req, res) => {
|
|
199
|
+
const protocol = req.connection?.encrypted ? "https" : "http";
|
|
200
|
+
const base = `${protocol}://${req.headers[":authority"] || req.headers.host}`;
|
|
201
|
+
const response = await handler(getRequest({ base, request: req }));
|
|
202
|
+
setResponse(res, response);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export { getRequest, setResponse, toNodeHandler };
|
package/dist/client.d.cts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import * as undici_types from 'undici-types';
|
|
2
1
|
import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
|
|
3
|
-
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.
|
|
2
|
+
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.7c5f7404.cjs';
|
|
4
3
|
import 'zod';
|
|
4
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
5
7
|
import 'stream/web';
|
|
6
8
|
|
|
7
9
|
type HasRequired<T extends {
|
|
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
|
|
|
28
30
|
params: true;
|
|
29
31
|
});
|
|
30
32
|
declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
|
|
31
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
32
33
|
endpoints: Record<string, Endpoint>;
|
|
33
34
|
} ? R["endpoints"] : R) extends {
|
|
34
35
|
[key: string]: infer T_1;
|
|
35
36
|
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
|
|
36
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
37
37
|
endpoints: Record<string, Endpoint>;
|
|
38
38
|
} ? R["endpoints"] : R) extends {
|
|
39
39
|
[key: string]: infer T_1;
|
package/dist/client.d.mts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import * as undici_types from 'undici-types';
|
|
2
1
|
import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
|
|
3
|
-
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.
|
|
2
|
+
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.7c5f7404.mjs';
|
|
4
3
|
import 'zod';
|
|
4
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
5
7
|
import 'stream/web';
|
|
6
8
|
|
|
7
9
|
type HasRequired<T extends {
|
|
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
|
|
|
28
30
|
params: true;
|
|
29
31
|
});
|
|
30
32
|
declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
|
|
31
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
32
33
|
endpoints: Record<string, Endpoint>;
|
|
33
34
|
} ? R["endpoints"] : R) extends {
|
|
34
35
|
[key: string]: infer T_1;
|
|
35
36
|
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
|
|
36
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
37
37
|
endpoints: Record<string, Endpoint>;
|
|
38
38
|
} ? R["endpoints"] : R) extends {
|
|
39
39
|
[key: string]: infer T_1;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import * as undici_types from 'undici-types';
|
|
2
1
|
import { BetterFetchOption, BetterFetchResponse } from '@better-fetch/fetch';
|
|
3
|
-
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.
|
|
2
|
+
import { R as Router, U as UnionToIntersection, b as Endpoint, H as HasRequiredKeys } from './shared/better-call.7c5f7404.js';
|
|
4
3
|
import 'zod';
|
|
4
|
+
import '@asteasolutions/zod-to-openapi/dist/zod-extensions';
|
|
5
|
+
import '@asteasolutions/zod-to-openapi';
|
|
6
|
+
import '@asteasolutions/zod-to-openapi/dist/openapi-registry';
|
|
5
7
|
import 'stream/web';
|
|
6
8
|
|
|
7
9
|
type HasRequired<T extends {
|
|
@@ -28,12 +30,10 @@ type RequiredOptionKeys<C extends {
|
|
|
28
30
|
params: true;
|
|
29
31
|
});
|
|
30
32
|
declare const createClient: <R extends Router | Router["endpoints"]>(options: ClientOptions) => <OPT extends UnionToIntersection<(R extends {
|
|
31
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
32
33
|
endpoints: Record<string, Endpoint>;
|
|
33
34
|
} ? R["endpoints"] : R) extends {
|
|
34
35
|
[key: string]: infer T_1;
|
|
35
36
|
} ? T_1 extends Endpoint ? { [key in T_1["options"]["method"] extends "GET" ? T_1["path"] : `@${T_1["options"]["method"] extends string ? Lowercase<T_1["options"]["method"]> : never}${T_1["path"]}`]: T_1; } : {} : {}> extends infer T ? { [K_1 in keyof T]: UnionToIntersection<(R extends {
|
|
36
|
-
handler: (request: Request) => Promise<undici_types.Response>;
|
|
37
37
|
endpoints: Record<string, Endpoint>;
|
|
38
38
|
} ? R["endpoints"] : R) extends {
|
|
39
39
|
[key: string]: infer T_1;
|