h3 1.10.0 → 1.10.2
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 +1 -1
- package/dist/index.cjs +38 -16
- package/dist/index.d.cts +5 -3
- package/dist/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +38 -16
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -222,7 +222,7 @@ H3 has a concept of composable utilities that accept `event` (from `eventHandler
|
|
|
222
222
|
- `getMethod(event, default?)`
|
|
223
223
|
- `isMethod(event, expected, allowHead?)`
|
|
224
224
|
- `assertMethod(event, expected, allowHead?)`
|
|
225
|
-
- `getRequestHeaders(event
|
|
225
|
+
- `getRequestHeaders(event)` (alias: `getHeaders`)
|
|
226
226
|
- `getRequestHeader(event, name)` (alias: `getHeader`)
|
|
227
227
|
- `getRequestURL(event)`
|
|
228
228
|
- `getRequestHost(event)`
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const ufo = require('ufo');
|
|
4
4
|
const cookieEs = require('cookie-es');
|
|
5
|
+
const ohash = require('ohash');
|
|
5
6
|
const radix3 = require('radix3');
|
|
6
7
|
const destr = require('destr');
|
|
7
8
|
const defu = require('defu');
|
|
@@ -363,7 +364,7 @@ function getRequestIP(event, opts = {}) {
|
|
|
363
364
|
return event.context.clientAddress;
|
|
364
365
|
}
|
|
365
366
|
if (opts.xForwardedFor) {
|
|
366
|
-
const xForwardedFor = getRequestHeader(event, "x-forwarded-for")?.split(",")?.
|
|
367
|
+
const xForwardedFor = getRequestHeader(event, "x-forwarded-for")?.split(",").shift()?.trim();
|
|
367
368
|
if (xForwardedFor) {
|
|
368
369
|
return xForwardedFor;
|
|
369
370
|
}
|
|
@@ -482,7 +483,23 @@ function getRequestWebStream(event) {
|
|
|
482
483
|
if (!PayloadMethods$1.includes(event.method)) {
|
|
483
484
|
return;
|
|
484
485
|
}
|
|
485
|
-
|
|
486
|
+
const bodyStream = event.web?.request?.body || event._requestBody;
|
|
487
|
+
if (bodyStream) {
|
|
488
|
+
return bodyStream;
|
|
489
|
+
}
|
|
490
|
+
const _hasRawBody = RawBodySymbol in event.node.req || "rawBody" in event.node.req || "body" in event.node.req || "__unenv__" in event.node.req;
|
|
491
|
+
if (_hasRawBody) {
|
|
492
|
+
return new ReadableStream({
|
|
493
|
+
async start(controller) {
|
|
494
|
+
const _rawBody = await readRawBody(event, false);
|
|
495
|
+
if (_rawBody) {
|
|
496
|
+
controller.enqueue(_rawBody);
|
|
497
|
+
}
|
|
498
|
+
controller.close();
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
return new ReadableStream({
|
|
486
503
|
start: (controller) => {
|
|
487
504
|
event.node.req.on("data", (chunk) => {
|
|
488
505
|
controller.enqueue(chunk);
|
|
@@ -587,16 +604,15 @@ function getCookie(event, name) {
|
|
|
587
604
|
return parseCookies(event)[name];
|
|
588
605
|
}
|
|
589
606
|
function setCookie(event, name, value, serializeOptions) {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
...serializeOptions
|
|
593
|
-
});
|
|
607
|
+
serializeOptions = { path: "/", ...serializeOptions };
|
|
608
|
+
const cookieStr = cookieEs.serialize(name, value, serializeOptions);
|
|
594
609
|
let setCookies = event.node.res.getHeader("set-cookie");
|
|
595
610
|
if (!Array.isArray(setCookies)) {
|
|
596
611
|
setCookies = [setCookies];
|
|
597
612
|
}
|
|
613
|
+
const _optionsHash = ohash.objectHash(serializeOptions);
|
|
598
614
|
setCookies = setCookies.filter((cookieValue) => {
|
|
599
|
-
return cookieValue &&
|
|
615
|
+
return cookieValue && _optionsHash !== ohash.objectHash(cookieEs.parse(cookieValue));
|
|
600
616
|
});
|
|
601
617
|
event.node.res.setHeader("set-cookie", [...setCookies, cookieStr]);
|
|
602
618
|
}
|
|
@@ -708,7 +724,7 @@ function getResponseStatusText(event) {
|
|
|
708
724
|
return event.node.res.statusMessage;
|
|
709
725
|
}
|
|
710
726
|
function defaultContentType(event, type) {
|
|
711
|
-
if (type && !event.node.res.getHeader("content-type")) {
|
|
727
|
+
if (type && event.node.res.statusCode !== 304 && !event.node.res.getHeader("content-type")) {
|
|
712
728
|
event.node.res.setHeader("content-type", type);
|
|
713
729
|
}
|
|
714
730
|
}
|
|
@@ -1053,7 +1069,8 @@ const ignoredHeaders = /* @__PURE__ */ new Set([
|
|
|
1053
1069
|
"keep-alive",
|
|
1054
1070
|
"upgrade",
|
|
1055
1071
|
"expect",
|
|
1056
|
-
"host"
|
|
1072
|
+
"host",
|
|
1073
|
+
"accept"
|
|
1057
1074
|
]);
|
|
1058
1075
|
async function proxyRequest(event, target, opts = {}) {
|
|
1059
1076
|
let body;
|
|
@@ -1215,6 +1232,7 @@ function mergeHeaders(defaults, ...inputs) {
|
|
|
1215
1232
|
return merged;
|
|
1216
1233
|
}
|
|
1217
1234
|
|
|
1235
|
+
const getSessionPromise = Symbol("getSession");
|
|
1218
1236
|
const DEFAULT_NAME = "h3";
|
|
1219
1237
|
const DEFAULT_COOKIE = {
|
|
1220
1238
|
path: "/",
|
|
@@ -1247,8 +1265,9 @@ async function getSession(event, config) {
|
|
|
1247
1265
|
if (!event.context.sessions) {
|
|
1248
1266
|
event.context.sessions = /* @__PURE__ */ Object.create(null);
|
|
1249
1267
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1268
|
+
const existingSession = event.context.sessions[sessionName];
|
|
1269
|
+
if (existingSession) {
|
|
1270
|
+
return existingSession[getSessionPromise] || existingSession;
|
|
1252
1271
|
}
|
|
1253
1272
|
const session = {
|
|
1254
1273
|
id: "",
|
|
@@ -1268,11 +1287,14 @@ async function getSession(event, config) {
|
|
|
1268
1287
|
sealedSession = getCookie(event, sessionName);
|
|
1269
1288
|
}
|
|
1270
1289
|
if (sealedSession) {
|
|
1271
|
-
const
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1290
|
+
const promise = unsealSession(event, config, sealedSession).catch(() => {
|
|
1291
|
+
}).then((unsealed) => {
|
|
1292
|
+
Object.assign(session, unsealed);
|
|
1293
|
+
delete event.context.sessions[sessionName][getSessionPromise];
|
|
1294
|
+
return session;
|
|
1295
|
+
});
|
|
1296
|
+
event.context.sessions[sessionName][getSessionPromise] = promise;
|
|
1297
|
+
await promise;
|
|
1276
1298
|
}
|
|
1277
1299
|
if (!session.id) {
|
|
1278
1300
|
session.id = config.generateId?.() ?? (config.crypto || crypto__default).randomUUID();
|
package/dist/index.d.cts
CHANGED
|
@@ -107,10 +107,12 @@ declare const H3Response: {
|
|
|
107
107
|
|
|
108
108
|
type SessionDataT = Record<string, any>;
|
|
109
109
|
type SessionData<T extends SessionDataT = SessionDataT> = T;
|
|
110
|
+
declare const getSessionPromise: unique symbol;
|
|
110
111
|
interface Session<T extends SessionDataT = SessionDataT> {
|
|
111
112
|
id: string;
|
|
112
113
|
createdAt: number;
|
|
113
114
|
data: SessionData<T>;
|
|
115
|
+
[getSessionPromise]?: Promise<Session<T>>;
|
|
114
116
|
}
|
|
115
117
|
interface SessionConfig {
|
|
116
118
|
/** Private key used to encrypt session tokens */
|
|
@@ -580,9 +582,9 @@ declare function getResponseStatus(event: H3Event): number;
|
|
|
580
582
|
declare function getResponseStatusText(event: H3Event): string;
|
|
581
583
|
declare function defaultContentType(event: H3Event, type?: string): void;
|
|
582
584
|
declare function sendRedirect(event: H3Event, location: string, code?: number): Promise<void>;
|
|
583
|
-
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["res"]["getHeaders"]>;
|
|
584
|
-
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["res"]["getHeader"]>;
|
|
585
|
-
declare function setResponseHeaders(event: H3Event, headers: Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]
|
|
585
|
+
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["node"]["res"]["getHeaders"]>;
|
|
586
|
+
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["node"]["res"]["getHeader"]>;
|
|
587
|
+
declare function setResponseHeaders(event: H3Event, headers: Partial<Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]>>): void;
|
|
586
588
|
declare const setHeaders: typeof setResponseHeaders;
|
|
587
589
|
declare function setResponseHeader(event: H3Event, name: HTTPHeaderName, value: Parameters<OutgoingMessage["setHeader"]>[1]): void;
|
|
588
590
|
declare const setHeader: typeof setResponseHeader;
|
package/dist/index.d.mts
CHANGED
|
@@ -107,10 +107,12 @@ declare const H3Response: {
|
|
|
107
107
|
|
|
108
108
|
type SessionDataT = Record<string, any>;
|
|
109
109
|
type SessionData<T extends SessionDataT = SessionDataT> = T;
|
|
110
|
+
declare const getSessionPromise: unique symbol;
|
|
110
111
|
interface Session<T extends SessionDataT = SessionDataT> {
|
|
111
112
|
id: string;
|
|
112
113
|
createdAt: number;
|
|
113
114
|
data: SessionData<T>;
|
|
115
|
+
[getSessionPromise]?: Promise<Session<T>>;
|
|
114
116
|
}
|
|
115
117
|
interface SessionConfig {
|
|
116
118
|
/** Private key used to encrypt session tokens */
|
|
@@ -580,9 +582,9 @@ declare function getResponseStatus(event: H3Event): number;
|
|
|
580
582
|
declare function getResponseStatusText(event: H3Event): string;
|
|
581
583
|
declare function defaultContentType(event: H3Event, type?: string): void;
|
|
582
584
|
declare function sendRedirect(event: H3Event, location: string, code?: number): Promise<void>;
|
|
583
|
-
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["res"]["getHeaders"]>;
|
|
584
|
-
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["res"]["getHeader"]>;
|
|
585
|
-
declare function setResponseHeaders(event: H3Event, headers: Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]
|
|
585
|
+
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["node"]["res"]["getHeaders"]>;
|
|
586
|
+
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["node"]["res"]["getHeader"]>;
|
|
587
|
+
declare function setResponseHeaders(event: H3Event, headers: Partial<Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]>>): void;
|
|
586
588
|
declare const setHeaders: typeof setResponseHeaders;
|
|
587
589
|
declare function setResponseHeader(event: H3Event, name: HTTPHeaderName, value: Parameters<OutgoingMessage["setHeader"]>[1]): void;
|
|
588
590
|
declare const setHeader: typeof setResponseHeader;
|
package/dist/index.d.ts
CHANGED
|
@@ -107,10 +107,12 @@ declare const H3Response: {
|
|
|
107
107
|
|
|
108
108
|
type SessionDataT = Record<string, any>;
|
|
109
109
|
type SessionData<T extends SessionDataT = SessionDataT> = T;
|
|
110
|
+
declare const getSessionPromise: unique symbol;
|
|
110
111
|
interface Session<T extends SessionDataT = SessionDataT> {
|
|
111
112
|
id: string;
|
|
112
113
|
createdAt: number;
|
|
113
114
|
data: SessionData<T>;
|
|
115
|
+
[getSessionPromise]?: Promise<Session<T>>;
|
|
114
116
|
}
|
|
115
117
|
interface SessionConfig {
|
|
116
118
|
/** Private key used to encrypt session tokens */
|
|
@@ -580,9 +582,9 @@ declare function getResponseStatus(event: H3Event): number;
|
|
|
580
582
|
declare function getResponseStatusText(event: H3Event): string;
|
|
581
583
|
declare function defaultContentType(event: H3Event, type?: string): void;
|
|
582
584
|
declare function sendRedirect(event: H3Event, location: string, code?: number): Promise<void>;
|
|
583
|
-
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["res"]["getHeaders"]>;
|
|
584
|
-
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["res"]["getHeader"]>;
|
|
585
|
-
declare function setResponseHeaders(event: H3Event, headers: Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]
|
|
585
|
+
declare function getResponseHeaders(event: H3Event): ReturnType<H3Event["node"]["res"]["getHeaders"]>;
|
|
586
|
+
declare function getResponseHeader(event: H3Event, name: HTTPHeaderName): ReturnType<H3Event["node"]["res"]["getHeader"]>;
|
|
587
|
+
declare function setResponseHeaders(event: H3Event, headers: Partial<Record<HTTPHeaderName, Parameters<OutgoingMessage["setHeader"]>[1]>>): void;
|
|
586
588
|
declare const setHeaders: typeof setResponseHeaders;
|
|
587
589
|
declare function setResponseHeader(event: H3Event, name: HTTPHeaderName, value: Parameters<OutgoingMessage["setHeader"]>[1]): void;
|
|
588
590
|
declare const setHeader: typeof setResponseHeader;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { withoutTrailingSlash, withoutBase, getQuery as getQuery$1, decode, decodePath, withLeadingSlash, parseURL } from 'ufo';
|
|
2
2
|
import { parse as parse$1, serialize } from 'cookie-es';
|
|
3
|
+
import { objectHash } from 'ohash';
|
|
3
4
|
import { createRouter as createRouter$1, toRouteMatcher } from 'radix3';
|
|
4
5
|
import destr from 'destr';
|
|
5
6
|
import { defu } from 'defu';
|
|
@@ -356,7 +357,7 @@ function getRequestIP(event, opts = {}) {
|
|
|
356
357
|
return event.context.clientAddress;
|
|
357
358
|
}
|
|
358
359
|
if (opts.xForwardedFor) {
|
|
359
|
-
const xForwardedFor = getRequestHeader(event, "x-forwarded-for")?.split(",")?.
|
|
360
|
+
const xForwardedFor = getRequestHeader(event, "x-forwarded-for")?.split(",").shift()?.trim();
|
|
360
361
|
if (xForwardedFor) {
|
|
361
362
|
return xForwardedFor;
|
|
362
363
|
}
|
|
@@ -475,7 +476,23 @@ function getRequestWebStream(event) {
|
|
|
475
476
|
if (!PayloadMethods$1.includes(event.method)) {
|
|
476
477
|
return;
|
|
477
478
|
}
|
|
478
|
-
|
|
479
|
+
const bodyStream = event.web?.request?.body || event._requestBody;
|
|
480
|
+
if (bodyStream) {
|
|
481
|
+
return bodyStream;
|
|
482
|
+
}
|
|
483
|
+
const _hasRawBody = RawBodySymbol in event.node.req || "rawBody" in event.node.req || "body" in event.node.req || "__unenv__" in event.node.req;
|
|
484
|
+
if (_hasRawBody) {
|
|
485
|
+
return new ReadableStream({
|
|
486
|
+
async start(controller) {
|
|
487
|
+
const _rawBody = await readRawBody(event, false);
|
|
488
|
+
if (_rawBody) {
|
|
489
|
+
controller.enqueue(_rawBody);
|
|
490
|
+
}
|
|
491
|
+
controller.close();
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
return new ReadableStream({
|
|
479
496
|
start: (controller) => {
|
|
480
497
|
event.node.req.on("data", (chunk) => {
|
|
481
498
|
controller.enqueue(chunk);
|
|
@@ -580,16 +597,15 @@ function getCookie(event, name) {
|
|
|
580
597
|
return parseCookies(event)[name];
|
|
581
598
|
}
|
|
582
599
|
function setCookie(event, name, value, serializeOptions) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
...serializeOptions
|
|
586
|
-
});
|
|
600
|
+
serializeOptions = { path: "/", ...serializeOptions };
|
|
601
|
+
const cookieStr = serialize(name, value, serializeOptions);
|
|
587
602
|
let setCookies = event.node.res.getHeader("set-cookie");
|
|
588
603
|
if (!Array.isArray(setCookies)) {
|
|
589
604
|
setCookies = [setCookies];
|
|
590
605
|
}
|
|
606
|
+
const _optionsHash = objectHash(serializeOptions);
|
|
591
607
|
setCookies = setCookies.filter((cookieValue) => {
|
|
592
|
-
return cookieValue &&
|
|
608
|
+
return cookieValue && _optionsHash !== objectHash(parse$1(cookieValue));
|
|
593
609
|
});
|
|
594
610
|
event.node.res.setHeader("set-cookie", [...setCookies, cookieStr]);
|
|
595
611
|
}
|
|
@@ -701,7 +717,7 @@ function getResponseStatusText(event) {
|
|
|
701
717
|
return event.node.res.statusMessage;
|
|
702
718
|
}
|
|
703
719
|
function defaultContentType(event, type) {
|
|
704
|
-
if (type && !event.node.res.getHeader("content-type")) {
|
|
720
|
+
if (type && event.node.res.statusCode !== 304 && !event.node.res.getHeader("content-type")) {
|
|
705
721
|
event.node.res.setHeader("content-type", type);
|
|
706
722
|
}
|
|
707
723
|
}
|
|
@@ -1046,7 +1062,8 @@ const ignoredHeaders = /* @__PURE__ */ new Set([
|
|
|
1046
1062
|
"keep-alive",
|
|
1047
1063
|
"upgrade",
|
|
1048
1064
|
"expect",
|
|
1049
|
-
"host"
|
|
1065
|
+
"host",
|
|
1066
|
+
"accept"
|
|
1050
1067
|
]);
|
|
1051
1068
|
async function proxyRequest(event, target, opts = {}) {
|
|
1052
1069
|
let body;
|
|
@@ -1208,6 +1225,7 @@ function mergeHeaders(defaults, ...inputs) {
|
|
|
1208
1225
|
return merged;
|
|
1209
1226
|
}
|
|
1210
1227
|
|
|
1228
|
+
const getSessionPromise = Symbol("getSession");
|
|
1211
1229
|
const DEFAULT_NAME = "h3";
|
|
1212
1230
|
const DEFAULT_COOKIE = {
|
|
1213
1231
|
path: "/",
|
|
@@ -1240,8 +1258,9 @@ async function getSession(event, config) {
|
|
|
1240
1258
|
if (!event.context.sessions) {
|
|
1241
1259
|
event.context.sessions = /* @__PURE__ */ Object.create(null);
|
|
1242
1260
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1261
|
+
const existingSession = event.context.sessions[sessionName];
|
|
1262
|
+
if (existingSession) {
|
|
1263
|
+
return existingSession[getSessionPromise] || existingSession;
|
|
1245
1264
|
}
|
|
1246
1265
|
const session = {
|
|
1247
1266
|
id: "",
|
|
@@ -1261,11 +1280,14 @@ async function getSession(event, config) {
|
|
|
1261
1280
|
sealedSession = getCookie(event, sessionName);
|
|
1262
1281
|
}
|
|
1263
1282
|
if (sealedSession) {
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1283
|
+
const promise = unsealSession(event, config, sealedSession).catch(() => {
|
|
1284
|
+
}).then((unsealed) => {
|
|
1285
|
+
Object.assign(session, unsealed);
|
|
1286
|
+
delete event.context.sessions[sessionName][getSessionPromise];
|
|
1287
|
+
return session;
|
|
1288
|
+
});
|
|
1289
|
+
event.context.sessions[sessionName][getSessionPromise] = promise;
|
|
1290
|
+
await promise;
|
|
1269
1291
|
}
|
|
1270
1292
|
if (!session.id) {
|
|
1271
1293
|
session.id = config.generateId?.() ?? (config.crypto || crypto).randomUUID();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "h3",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
4
4
|
"description": "Minimal H(TTP) framework built for high performance and portability.",
|
|
5
5
|
"repository": "unjs/h3",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,40 +21,41 @@
|
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"cookie-es": "^1.0.0",
|
|
24
|
-
"defu": "^6.1.
|
|
24
|
+
"defu": "^6.1.4",
|
|
25
25
|
"destr": "^2.0.2",
|
|
26
26
|
"iron-webcrypto": "^1.0.0",
|
|
27
|
+
"ohash": "^1.1.3",
|
|
27
28
|
"radix3": "^1.1.0",
|
|
28
29
|
"ufo": "^1.3.2",
|
|
29
30
|
"uncrypto": "^0.1.3",
|
|
30
|
-
"unenv": "^1.
|
|
31
|
+
"unenv": "^1.9.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"0x": "^5.7.0",
|
|
34
35
|
"@types/express": "^4.17.21",
|
|
35
|
-
"@types/node": "^20.
|
|
36
|
+
"@types/node": "^20.11.6",
|
|
36
37
|
"@types/supertest": "^6.0.2",
|
|
37
|
-
"@vitest/coverage-v8": "^1.
|
|
38
|
+
"@vitest/coverage-v8": "^1.2.1",
|
|
38
39
|
"autocannon": "^7.14.0",
|
|
39
40
|
"changelogen": "^0.5.5",
|
|
40
41
|
"connect": "^3.7.0",
|
|
41
|
-
"eslint": "^8.
|
|
42
|
+
"eslint": "^8.56.0",
|
|
42
43
|
"eslint-config-unjs": "^0.2.1",
|
|
43
44
|
"express": "^4.18.2",
|
|
44
45
|
"get-port": "^7.0.0",
|
|
45
46
|
"jiti": "^1.21.0",
|
|
46
|
-
"listhen": "^1.5.
|
|
47
|
-
"node-fetch-native": "^1.
|
|
48
|
-
"prettier": "^3.
|
|
47
|
+
"listhen": "^1.5.6",
|
|
48
|
+
"node-fetch-native": "^1.6.1",
|
|
49
|
+
"prettier": "^3.2.4",
|
|
49
50
|
"react": "^18.2.0",
|
|
50
51
|
"react-dom": "^18.2.0",
|
|
51
|
-
"supertest": "^6.3.
|
|
52
|
+
"supertest": "^6.3.4",
|
|
52
53
|
"typescript": "^5.3.3",
|
|
53
54
|
"unbuild": "^2.0.0",
|
|
54
|
-
"vitest": "^1.
|
|
55
|
+
"vitest": "^1.2.1",
|
|
55
56
|
"zod": "^3.22.4"
|
|
56
57
|
},
|
|
57
|
-
"packageManager": "pnpm@8.
|
|
58
|
+
"packageManager": "pnpm@8.14.3",
|
|
58
59
|
"scripts": {
|
|
59
60
|
"build": "unbuild",
|
|
60
61
|
"dev": "vitest",
|