@rpcbase/api 0.149.0 → 0.151.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/index.js CHANGED
@@ -27497,6 +27497,28 @@ var createApiErrorMiddleware = (options = {}) => (error, req, res, next) => {
27497
27497
  };
27498
27498
  var apiErrorMiddleware = createApiErrorMiddleware();
27499
27499
  //#endregion
27500
+ //#region src/requestValidation.ts
27501
+ var getErrorFields = (issues) => {
27502
+ const fields = {};
27503
+ for (const issue of issues) {
27504
+ const path = issue.path.map(String).join(".");
27505
+ if (!path) continue;
27506
+ const messages = fields[path] ?? [];
27507
+ messages.push(issue.message);
27508
+ fields[path] = messages;
27509
+ }
27510
+ return Object.keys(fields).length > 0 ? fields : void 0;
27511
+ };
27512
+ var parseApiRequest = (schema, input) => {
27513
+ const result = schema.safeParse(input);
27514
+ if (result.success) return result.data;
27515
+ throw new ApiHttpError(400, "invalid_request", {
27516
+ message: "Invalid request payload.",
27517
+ fields: getErrorFields(result.error.issues),
27518
+ cause: result.error
27519
+ });
27520
+ };
27521
+ //#endregion
27500
27522
  //#region src/initApi.ts
27501
27523
  var loadInitApiClient = async () => {
27502
27524
  return (await import("@rpcbase/client")).initApiClient;
@@ -27517,12 +27539,12 @@ var withApiRequestIdExposed = (options) => {
27517
27539
  };
27518
27540
  var initApi = async ({ app, routes, cors: corsOptions, errors }) => {
27519
27541
  await (await loadInitApiClient())({ app });
27520
- const registerHandler = (method, path, handler) => {
27521
- assert(path.startsWith("/api"), "API routes must start with /api");
27542
+ const registerHandler = (method, path, requestSchema, handler) => {
27543
+ assert(typeof path === "string" && path.startsWith("/api"), "API routes must be explicit string paths starting with /api");
27522
27544
  app[method](path, async (req, res, next) => {
27523
- const payload = method === "get" ? req.query : req.body ?? {};
27545
+ const requestPayload = method === "get" ? req.query : req.body ?? {};
27524
27546
  try {
27525
- const result = await handler(payload, {
27547
+ const result = await handler(requestSchema ? parseApiRequest(requestSchema, requestPayload) : requestPayload, {
27526
27548
  req,
27527
27549
  res
27528
27550
  });
@@ -27534,22 +27556,21 @@ var initApi = async ({ app, routes, cors: corsOptions, errors }) => {
27534
27556
  }
27535
27557
  });
27536
27558
  };
27559
+ const createApiMethod = (method) => ((path, requestSchemaOrHandler, validatedHandler) => {
27560
+ if (validatedHandler === void 0) {
27561
+ registerHandler(method, path, void 0, requestSchemaOrHandler);
27562
+ return;
27563
+ }
27564
+ registerHandler(method, path, requestSchemaOrHandler, validatedHandler);
27565
+ });
27537
27566
  const api = {
27538
27567
  use: (path, middleware) => {
27539
27568
  app.use(path, middleware);
27540
27569
  },
27541
- get: (path, handler) => {
27542
- registerHandler("get", path, handler);
27543
- },
27544
- post: (path, handler) => {
27545
- registerHandler("post", path, handler);
27546
- },
27547
- put: (path, handler) => {
27548
- registerHandler("put", path, handler);
27549
- },
27550
- delete: (path, handler) => {
27551
- registerHandler("delete", path, handler);
27552
- }
27570
+ get: createApiMethod("get"),
27571
+ post: createApiMethod("post"),
27572
+ put: createApiMethod("put"),
27573
+ delete: createApiMethod("delete")
27553
27574
  };
27554
27575
  app.use("/api", (0, import_lib.default)(withApiRequestIdExposed(corsOptions)));
27555
27576
  app.use("/api", (0, import_express.json)({ limit: "8mb" }));