@faapi/faapi 6.11.0 → 6.13.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/cli/index.js CHANGED
@@ -2511,7 +2511,7 @@ function baseExpression(type, ctx) {
2511
2511
  case "union":
2512
2512
  return generateUnionExpression(type.members, ctx);
2513
2513
  case "date":
2514
- return 'z.preprocess((v) => (typeof v === "string" ? new Date(v) : v), z.date())';
2514
+ return 'z.preprocess((v) => (typeof v === "string" || typeof v === "number" ? new Date(v) : v), z.date())';
2515
2515
  case "record":
2516
2516
  return `z.record(${runtimeTypeToZodExpression(type.key, ctx)}, ${runtimeTypeToZodExpression(type.value, ctx)})`;
2517
2517
  case "map":
@@ -6116,6 +6116,85 @@ var init_loadRouteModule = __esm({
6116
6116
  }
6117
6117
  });
6118
6118
 
6119
+ // src/utils/isPlainObject.ts
6120
+ function isPlainObject(value) {
6121
+ if (value === null || typeof value !== "object") {
6122
+ return false;
6123
+ }
6124
+ if (Array.isArray(value)) {
6125
+ return false;
6126
+ }
6127
+ const proto = Object.getPrototypeOf(value);
6128
+ return proto === null || proto === Object.prototype;
6129
+ }
6130
+ var init_isPlainObject = __esm({
6131
+ "src/utils/isPlainObject.ts"() {
6132
+ "use strict";
6133
+ }
6134
+ });
6135
+
6136
+ // src/utils/stringifyJson.ts
6137
+ function stringifyJson(value) {
6138
+ return JSON.stringify(convertValue(value, /* @__PURE__ */ new Set()));
6139
+ }
6140
+ function convertValue(value, ancestors) {
6141
+ if (value === null) return value;
6142
+ const type = typeof value;
6143
+ if (type === "bigint") return value.toString();
6144
+ if (type === "number") return Number.isFinite(value) ? value : String(value);
6145
+ if (type !== "object") return value;
6146
+ const obj = value;
6147
+ if (ancestors.has(obj)) {
6148
+ throw new TypeError("[faapi] Converting circular structure to JSON");
6149
+ }
6150
+ if (obj instanceof Date) return obj.getTime();
6151
+ if (obj instanceof Map) {
6152
+ ancestors.add(obj);
6153
+ const entries = Array.from(obj, ([k, v]) => [
6154
+ convertValue(k, ancestors),
6155
+ convertValue(v, ancestors)
6156
+ ]);
6157
+ ancestors.delete(obj);
6158
+ return entries;
6159
+ }
6160
+ if (obj instanceof Set) {
6161
+ ancestors.add(obj);
6162
+ const values = Array.from(obj, (v) => convertValue(v, ancestors));
6163
+ ancestors.delete(obj);
6164
+ return values;
6165
+ }
6166
+ if (obj instanceof RegExp) return obj.toString();
6167
+ const toJSON = obj.toJSON;
6168
+ if (typeof toJSON === "function") {
6169
+ ancestors.add(obj);
6170
+ const result = convertValue(toJSON.call(obj), ancestors);
6171
+ ancestors.delete(obj);
6172
+ return result;
6173
+ }
6174
+ if (Array.isArray(obj)) {
6175
+ ancestors.add(obj);
6176
+ const arr = obj.map((item) => convertValue(item, ancestors));
6177
+ ancestors.delete(obj);
6178
+ return arr;
6179
+ }
6180
+ if (isPlainObject(obj)) {
6181
+ ancestors.add(obj);
6182
+ const out = {};
6183
+ for (const [key, val] of Object.entries(obj)) {
6184
+ out[key] = convertValue(val, ancestors);
6185
+ }
6186
+ ancestors.delete(obj);
6187
+ return out;
6188
+ }
6189
+ return obj;
6190
+ }
6191
+ var init_stringifyJson = __esm({
6192
+ "src/utils/stringifyJson.ts"() {
6193
+ "use strict";
6194
+ init_isPlainObject();
6195
+ }
6196
+ });
6197
+
6119
6198
  // src/runtime/sse.ts
6120
6199
  function encodeSseEvent(event) {
6121
6200
  let out = "";
@@ -6142,7 +6221,7 @@ function encodeSseEvent(event) {
6142
6221
  } else if (event.data === null) {
6143
6222
  dataStr = "null";
6144
6223
  } else {
6145
- dataStr = JSON.stringify(event.data);
6224
+ dataStr = stringifyJson(event.data);
6146
6225
  }
6147
6226
  const lines = dataStr.split("\n");
6148
6227
  for (const line of lines) {
@@ -6173,7 +6252,9 @@ function createSseWriter() {
6173
6252
  headers: {
6174
6253
  "Content-Type": "text/event-stream",
6175
6254
  "Cache-Control": "no-cache",
6176
- Connection: "keep-alive"
6255
+ Connection: "keep-alive",
6256
+ // nginx 认到该头后按响应跳过 proxy_buffering;其他反代/客户端忽略,无副作用
6257
+ "X-Accel-Buffering": "no"
6177
6258
  }
6178
6259
  });
6179
6260
  const writer = {
@@ -6223,6 +6304,7 @@ function createSseWriter() {
6223
6304
  var init_sse = __esm({
6224
6305
  "src/runtime/sse.ts"() {
6225
6306
  "use strict";
6307
+ init_stringifyJson();
6226
6308
  }
6227
6309
  });
6228
6310
 
@@ -6318,7 +6400,7 @@ function jsonRaw(body, status, extraHeaders) {
6318
6400
  const extra = new Headers(extraHeaders);
6319
6401
  extra.forEach((value, key) => headers.set(key, value));
6320
6402
  }
6321
- return new Response(JSON.stringify(body), { status, headers });
6403
+ return new Response(stringifyJson(body), { status, headers });
6322
6404
  }
6323
6405
  function wrapOkResult(result, config) {
6324
6406
  if (result instanceof Response) return result;
@@ -6385,6 +6467,7 @@ var init_responseFormatter = __esm({
6385
6467
  "use strict";
6386
6468
  init_FaapiError();
6387
6469
  init_httpErrors();
6470
+ init_stringifyJson();
6388
6471
  }
6389
6472
  });
6390
6473
 
@@ -6931,23 +7014,6 @@ var init_resolveInput = __esm({
6931
7014
  }
6932
7015
  });
6933
7016
 
6934
- // src/utils/isPlainObject.ts
6935
- function isPlainObject(value) {
6936
- if (value === null || typeof value !== "object") {
6937
- return false;
6938
- }
6939
- if (Array.isArray(value)) {
6940
- return false;
6941
- }
6942
- const proto = Object.getPrototypeOf(value);
6943
- return proto === null || proto === Object.prototype;
6944
- }
6945
- var init_isPlainObject = __esm({
6946
- "src/utils/isPlainObject.ts"() {
6947
- "use strict";
6948
- }
6949
- });
6950
-
6951
7017
  // src/response/pendingMeta.ts
6952
7018
  function deferMetaHeaders(response, headers) {
6953
7019
  const existing = pending.get(response);
@@ -7033,7 +7099,7 @@ async function toResponse(value, meta) {
7033
7099
  });
7034
7100
  }
7035
7101
  if (isPlainObject(value) || Array.isArray(value)) {
7036
- const body2 = JSON.stringify(value);
7102
+ const body2 = stringifyJson(value);
7037
7103
  const headers2 = new Headers({ "Content-Type": "application/json" });
7038
7104
  applyMeta(headers2);
7039
7105
  return new Response(body2, {
@@ -7057,7 +7123,7 @@ async function toResponse(value, meta) {
7057
7123
  headers: headers2
7058
7124
  });
7059
7125
  }
7060
- const body = JSON.stringify(value);
7126
+ const body = stringifyJson(value);
7061
7127
  const headers = new Headers({ "Content-Type": "application/json" });
7062
7128
  applyMeta(headers);
7063
7129
  return new Response(body, {
@@ -7069,6 +7135,7 @@ var init_toResponse = __esm({
7069
7135
  "src/response/toResponse.ts"() {
7070
7136
  "use strict";
7071
7137
  init_isPlainObject();
7138
+ init_stringifyJson();
7072
7139
  init_pendingMeta();
7073
7140
  }
7074
7141
  });
@@ -7394,9 +7461,6 @@ var init_injectParams = __esm({
7394
7461
  function wrapResult(result, ctx) {
7395
7462
  return wrapOkResult(result, ctx.config);
7396
7463
  }
7397
- function stashHandlerResult(ctx, result) {
7398
- ctx.__faapiHandlerResult = result;
7399
- }
7400
7464
  function mergeMeta(response, meta) {
7401
7465
  const hasMeta = meta.status !== void 0 || Object.keys(meta.headers).length > 0 || meta.setCookies.length > 0;
7402
7466
  if (!hasMeta) return response;
@@ -7465,9 +7529,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
7465
7529
  const result = await injectParamsAsync(handler, ctx, body, injectors);
7466
7530
  const sseResponse = pickSseAndAutoClose();
7467
7531
  if (sseResponse) return sseResponse;
7468
- const response = await toResponse(wrapResult(result, ctx), meta);
7469
- if (!(result instanceof Response)) stashHandlerResult(ctx, result);
7470
- return response;
7532
+ return toResponse(wrapResult(result, ctx), meta);
7471
7533
  } catch (err) {
7472
7534
  autoCloseSseOnError();
7473
7535
  throw err;
@@ -7478,9 +7540,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
7478
7540
  const result = await injectParamsAsync(handler, ctx, body, injectors);
7479
7541
  const sseResponse = pickSseAndAutoClose();
7480
7542
  if (sseResponse) return sseResponse;
7481
- const response = await toResponse(wrapResult(result, ctx), meta);
7482
- if (!(result instanceof Response)) stashHandlerResult(ctx, result);
7483
- return response;
7543
+ return toResponse(wrapResult(result, ctx), meta);
7484
7544
  } catch (err) {
7485
7545
  autoCloseSseOnError();
7486
7546
  throw err;
@@ -8081,7 +8141,7 @@ var init_serverUtils = __esm({
8081
8141
  function wrapWsSocket(rawSocket) {
8082
8142
  return {
8083
8143
  send(data) {
8084
- const payload = typeof data === "string" || Buffer.isBuffer(data) ? data : JSON.stringify(data);
8144
+ const payload = typeof data === "string" || Buffer.isBuffer(data) ? data : stringifyJson(data);
8085
8145
  rawSocket.send(payload);
8086
8146
  },
8087
8147
  close(code, reason) {
@@ -8095,6 +8155,7 @@ function wrapWsSocket(rawSocket) {
8095
8155
  var init_wsHandler = __esm({
8096
8156
  "src/runtime/wsHandler.ts"() {
8097
8157
  "use strict";
8158
+ init_stringifyJson();
8098
8159
  }
8099
8160
  });
8100
8161
 
@@ -8582,7 +8643,6 @@ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares,
8582
8643
  globalInjectors
8583
8644
  });
8584
8645
  const response = outerMiddlewares.length > 0 ? await compose(outerMiddlewares, ctx, routePipeline) : await routePipeline();
8585
- res.__faapiHandlerResult = ctx.__faapiHandlerResult;
8586
8646
  await sendSuccessResponse(response, res);
8587
8647
  } catch (err) {
8588
8648
  if (res.destroyed || res.writableEnded) return;
@@ -9799,10 +9859,7 @@ async function createAppBase(options) {
9799
9859
  resolve3({
9800
9860
  status: mockRes.statusCode,
9801
9861
  headers: new Headers(mockRes._headers),
9802
- body: parsed,
9803
- // inject raw 捕获桥(第三跳):handler 原始返回值(handleRequest 从 ctx
9804
- // 桥接到 res;未捕获时 undefined——语义见 InjectResponse.raw 注释)
9805
- raw: mockRes.__faapiHandlerResult
9862
+ body: parsed
9806
9863
  });
9807
9864
  });
9808
9865
  const listeners = server.listeners("request");