@faapi/faapi 6.11.0 → 6.12.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/testing.js CHANGED
@@ -1,3 +1,71 @@
1
+ // src/utils/isPlainObject.ts
2
+ function isPlainObject(value) {
3
+ if (value === null || typeof value !== "object") {
4
+ return false;
5
+ }
6
+ if (Array.isArray(value)) {
7
+ return false;
8
+ }
9
+ const proto = Object.getPrototypeOf(value);
10
+ return proto === null || proto === Object.prototype;
11
+ }
12
+
13
+ // src/utils/stringifyJson.ts
14
+ function stringifyJson(value) {
15
+ return JSON.stringify(convertValue(value, /* @__PURE__ */ new Set()));
16
+ }
17
+ function convertValue(value, ancestors) {
18
+ if (value === null) return value;
19
+ const type = typeof value;
20
+ if (type === "bigint") return value.toString();
21
+ if (type === "number") return Number.isFinite(value) ? value : String(value);
22
+ if (type !== "object") return value;
23
+ const obj = value;
24
+ if (ancestors.has(obj)) {
25
+ throw new TypeError("[faapi] Converting circular structure to JSON");
26
+ }
27
+ if (obj instanceof Date) return obj.getTime();
28
+ if (obj instanceof Map) {
29
+ ancestors.add(obj);
30
+ const entries = Array.from(obj, ([k, v]) => [
31
+ convertValue(k, ancestors),
32
+ convertValue(v, ancestors)
33
+ ]);
34
+ ancestors.delete(obj);
35
+ return entries;
36
+ }
37
+ if (obj instanceof Set) {
38
+ ancestors.add(obj);
39
+ const values = Array.from(obj, (v) => convertValue(v, ancestors));
40
+ ancestors.delete(obj);
41
+ return values;
42
+ }
43
+ if (obj instanceof RegExp) return obj.toString();
44
+ const toJSON = obj.toJSON;
45
+ if (typeof toJSON === "function") {
46
+ ancestors.add(obj);
47
+ const result = convertValue(toJSON.call(obj), ancestors);
48
+ ancestors.delete(obj);
49
+ return result;
50
+ }
51
+ if (Array.isArray(obj)) {
52
+ ancestors.add(obj);
53
+ const arr = obj.map((item) => convertValue(item, ancestors));
54
+ ancestors.delete(obj);
55
+ return arr;
56
+ }
57
+ if (isPlainObject(obj)) {
58
+ ancestors.add(obj);
59
+ const out = {};
60
+ for (const [key, val] of Object.entries(obj)) {
61
+ out[key] = convertValue(val, ancestors);
62
+ }
63
+ ancestors.delete(obj);
64
+ return out;
65
+ }
66
+ return obj;
67
+ }
68
+
1
69
  // src/runtime/sse.ts
2
70
  function encodeSseEvent(event) {
3
71
  let out = "";
@@ -24,7 +92,7 @@ function encodeSseEvent(event) {
24
92
  } else if (event.data === null) {
25
93
  dataStr = "null";
26
94
  } else {
27
- dataStr = JSON.stringify(event.data);
95
+ dataStr = stringifyJson(event.data);
28
96
  }
29
97
  const lines = dataStr.split("\n");
30
98
  for (const line of lines) {
@@ -182,7 +250,7 @@ function jsonRaw(body, status, extraHeaders) {
182
250
  const extra = new Headers(extraHeaders);
183
251
  extra.forEach((value, key) => headers.set(key, value));
184
252
  }
185
- return new Response(JSON.stringify(body), { status, headers });
253
+ return new Response(stringifyJson(body), { status, headers });
186
254
  }
187
255
  function wrapOkResult(result, config) {
188
256
  if (result instanceof Response) return result;
@@ -541,18 +609,6 @@ function createTestContext(options) {
541
609
  return createContext(request, params, config, ip, registries);
542
610
  }
543
611
 
544
- // src/utils/isPlainObject.ts
545
- function isPlainObject(value) {
546
- if (value === null || typeof value !== "object") {
547
- return false;
548
- }
549
- if (Array.isArray(value)) {
550
- return false;
551
- }
552
- const proto = Object.getPrototypeOf(value);
553
- return proto === null || proto === Object.prototype;
554
- }
555
-
556
612
  // src/response/pendingMeta.ts
557
613
  var pending = /* @__PURE__ */ new WeakMap();
558
614
  function deferMetaHeaders(response, headers) {
@@ -632,7 +688,7 @@ async function toResponse(value, meta) {
632
688
  });
633
689
  }
634
690
  if (isPlainObject(value) || Array.isArray(value)) {
635
- const body2 = JSON.stringify(value);
691
+ const body2 = stringifyJson(value);
636
692
  const headers2 = new Headers({ "Content-Type": "application/json" });
637
693
  applyMeta(headers2);
638
694
  return new Response(body2, {
@@ -656,7 +712,7 @@ async function toResponse(value, meta) {
656
712
  headers: headers2
657
713
  });
658
714
  }
659
- const body = JSON.stringify(value);
715
+ const body = stringifyJson(value);
660
716
  const headers = new Headers({ "Content-Type": "application/json" });
661
717
  applyMeta(headers);
662
718
  return new Response(body, {
@@ -1036,9 +1092,6 @@ async function injectParamsAsync(handler, ctx, body, injectors) {
1036
1092
  function wrapResult(result, ctx) {
1037
1093
  return wrapOkResult(result, ctx.config);
1038
1094
  }
1039
- function stashHandlerResult(ctx, result) {
1040
- ctx.__faapiHandlerResult = result;
1041
- }
1042
1095
  function mergeMeta(response, meta) {
1043
1096
  const hasMeta = meta.status !== void 0 || Object.keys(meta.headers).length > 0 || meta.setCookies.length > 0;
1044
1097
  if (!hasMeta) return response;
@@ -1107,9 +1160,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
1107
1160
  const result = await injectParamsAsync(handler, ctx, body, injectors);
1108
1161
  const sseResponse = pickSseAndAutoClose();
1109
1162
  if (sseResponse) return sseResponse;
1110
- const response = await toResponse(wrapResult(result, ctx), meta);
1111
- if (!(result instanceof Response)) stashHandlerResult(ctx, result);
1112
- return response;
1163
+ return toResponse(wrapResult(result, ctx), meta);
1113
1164
  } catch (err) {
1114
1165
  autoCloseSseOnError();
1115
1166
  throw err;
@@ -1120,9 +1171,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
1120
1171
  const result = await injectParamsAsync(handler, ctx, body, injectors);
1121
1172
  const sseResponse = pickSseAndAutoClose();
1122
1173
  if (sseResponse) return sseResponse;
1123
- const response = await toResponse(wrapResult(result, ctx), meta);
1124
- if (!(result instanceof Response)) stashHandlerResult(ctx, result);
1125
- return response;
1174
+ return toResponse(wrapResult(result, ctx), meta);
1126
1175
  } catch (err) {
1127
1176
  autoCloseSseOnError();
1128
1177
  throw err;
@@ -2695,7 +2744,7 @@ function baseExpression(type, ctx) {
2695
2744
  case "union":
2696
2745
  return generateUnionExpression(type.members, ctx);
2697
2746
  case "date":
2698
- return 'z.preprocess((v) => (typeof v === "string" ? new Date(v) : v), z.date())';
2747
+ return 'z.preprocess((v) => (typeof v === "string" || typeof v === "number" ? new Date(v) : v), z.date())';
2699
2748
  case "record":
2700
2749
  return `z.record(${runtimeTypeToZodExpression(type.key, ctx)}, ${runtimeTypeToZodExpression(type.value, ctx)})`;
2701
2750
  case "map":
@@ -4322,7 +4371,7 @@ function buildErrorResponse(err, config) {
4322
4371
  function wrapWsSocket(rawSocket) {
4323
4372
  return {
4324
4373
  send(data) {
4325
- const payload = typeof data === "string" || Buffer.isBuffer(data) ? data : JSON.stringify(data);
4374
+ const payload = typeof data === "string" || Buffer.isBuffer(data) ? data : stringifyJson(data);
4326
4375
  rawSocket.send(payload);
4327
4376
  },
4328
4377
  close(code, reason) {
@@ -4795,7 +4844,6 @@ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares,
4795
4844
  globalInjectors
4796
4845
  });
4797
4846
  const response = outerMiddlewares.length > 0 ? await compose(outerMiddlewares, ctx, routePipeline) : await routePipeline();
4798
- res.__faapiHandlerResult = ctx.__faapiHandlerResult;
4799
4847
  await sendSuccessResponse(response, res);
4800
4848
  } catch (err) {
4801
4849
  if (res.destroyed || res.writableEnded) return;