@terreno/api 0.11.7 → 0.11.9

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.
Files changed (44) hide show
  1. package/dist/betterAuthSetup.js +10 -3
  2. package/dist/configurationPlugin.d.ts +2 -1
  3. package/dist/configurationPlugin.js +16 -9
  4. package/dist/errors.d.ts +6 -6
  5. package/dist/errors.js +22 -22
  6. package/dist/errors.test.d.ts +1 -0
  7. package/dist/errors.test.js +280 -0
  8. package/dist/githubAuth.d.ts +3 -3
  9. package/dist/githubAuth.js +16 -16
  10. package/dist/middleware.d.ts +1 -1
  11. package/dist/middleware.js +4 -3
  12. package/dist/middleware.test.d.ts +1 -0
  13. package/dist/middleware.test.js +82 -0
  14. package/dist/notifiers/googleChatNotifier.js +4 -3
  15. package/dist/notifiers/zoomNotifier.js +12 -11
  16. package/dist/openApiCompat.js +2 -1
  17. package/dist/openApiEtag.d.ts +1 -1
  18. package/dist/openApiEtag.js +4 -3
  19. package/dist/openApiValidator.d.ts +12 -12
  20. package/dist/openApiValidator.js +59 -58
  21. package/dist/plugins.d.ts +12 -1
  22. package/dist/plugins.js +34 -1
  23. package/dist/plugins.test.js +212 -8
  24. package/dist/scriptRunner.d.ts +8 -7
  25. package/dist/secretProviders.js +17 -7
  26. package/dist/types/consentForm.d.ts +4 -2
  27. package/package.json +1 -1
  28. package/src/betterAuthSetup.ts +10 -3
  29. package/src/configurationPlugin.ts +18 -9
  30. package/src/errors.test.ts +302 -0
  31. package/src/errors.ts +18 -13
  32. package/src/githubAuth.ts +11 -10
  33. package/src/middleware.test.ts +71 -0
  34. package/src/middleware.ts +6 -2
  35. package/src/notifiers/googleChatNotifier.ts +4 -3
  36. package/src/notifiers/zoomNotifier.ts +4 -3
  37. package/src/openApiCompat.ts +2 -1
  38. package/src/openApiEtag.ts +2 -2
  39. package/src/openApiValidator.ts +46 -46
  40. package/src/plugins.test.ts +130 -0
  41. package/src/plugins.ts +35 -0
  42. package/src/scriptRunner.ts +23 -27
  43. package/src/secretProviders.ts +27 -9
  44. package/src/types/consentForm.ts +6 -4
package/src/githubAuth.ts CHANGED
@@ -5,6 +5,7 @@ import {generateTokens, type UserModel} from "./auth";
5
5
  import {APIError} from "./errors";
6
6
  import type {AuthOptions} from "./expressServer";
7
7
  import {logger} from "./logger";
8
+ import {findOneOrNoneFor} from "./plugins";
8
9
 
9
10
  /** Options for configuring GitHub OAuth authentication */
10
11
  export interface GitHubAuthOptions {
@@ -57,24 +58,24 @@ export interface GitHubUserFields {
57
58
  * userSchema.plugin(githubUserPlugin);
58
59
  * ```
59
60
  */
60
- export function githubUserPlugin(schema: any) {
61
+ export const githubUserPlugin = (schema: any): void => {
61
62
  schema.add({
62
63
  githubAvatarUrl: {type: String},
63
64
  githubId: {index: true, sparse: true, type: String, unique: true},
64
65
  githubProfileUrl: {type: String},
65
66
  githubUsername: {type: String},
66
67
  });
67
- }
68
+ };
68
69
 
69
70
  /**
70
71
  * Sets up GitHub OAuth authentication strategy.
71
72
  * Call this after setupAuth() in your server initialization.
72
73
  */
73
- export function setupGitHubAuth(
74
+ export const setupGitHubAuth = (
74
75
  _app: express.Application,
75
76
  userModel: UserModel,
76
77
  githubOptions: GitHubAuthOptions
77
- ) {
78
+ ): void => {
78
79
  const scope = githubOptions.scope ?? ["user:email"];
79
80
 
80
81
  passport.use(
@@ -112,7 +113,7 @@ export function setupGitHubAuth(
112
113
  const githubId = profile.id;
113
114
 
114
115
  // Check if user with this GitHub ID already exists
115
- const existingGitHubUser = await userModel.findOne({githubId} as any);
116
+ const existingGitHubUser = await findOneOrNoneFor(userModel, {githubId});
116
117
 
117
118
  // Case 1: User is authenticated and wants to link GitHub account
118
119
  if (existingUser) {
@@ -155,7 +156,7 @@ export function setupGitHubAuth(
155
156
 
156
157
  // Check if user with this email already exists
157
158
  if (email) {
158
- const existingEmailUser = await userModel.findOne({email} as any);
159
+ const existingEmailUser = await findOneOrNoneFor(userModel, {email});
159
160
  if (existingEmailUser) {
160
161
  // If account linking is allowed, link GitHub to existing email account
161
162
  if (githubOptions.allowAccountLinking !== false) {
@@ -195,7 +196,7 @@ export function setupGitHubAuth(
195
196
  }) as any
196
197
  ) as passport.Strategy
197
198
  );
198
- }
199
+ };
199
200
 
200
201
  /**
201
202
  * Adds GitHub OAuth routes to the Express application.
@@ -206,12 +207,12 @@ export function setupGitHubAuth(
206
207
  * - POST /auth/github/link - Links GitHub account to authenticated user (requires JWT auth)
207
208
  * - DELETE /auth/github/unlink - Unlinks GitHub account from authenticated user (requires JWT auth)
208
209
  */
209
- export function addGitHubAuthRoutes(
210
+ export const addGitHubAuthRoutes = (
210
211
  app: express.Application,
211
212
  userModel: UserModel,
212
213
  githubOptions: GitHubAuthOptions,
213
214
  authOptions?: AuthOptions
214
- ): void {
215
+ ): void => {
215
216
  const router = require("express").Router();
216
217
 
217
218
  // Initiate GitHub OAuth flow
@@ -332,4 +333,4 @@ export function addGitHubAuthRoutes(
332
333
  }
333
334
 
334
335
  app.use("/auth", router);
335
- }
336
+ };
@@ -0,0 +1,71 @@
1
+ import {beforeEach, describe, expect, it, type Mock, mock} from "bun:test";
2
+ import * as Sentry from "@sentry/bun";
3
+ import type {NextFunction, Request, Response} from "express";
4
+
5
+ import {sentryAppVersionMiddleware} from "./middleware";
6
+
7
+ const buildReq = (headers: Record<string, string | undefined>): Request => {
8
+ return {
9
+ get: (name: string) => headers[name],
10
+ } as unknown as Request;
11
+ };
12
+
13
+ const buildNext = (): Mock<() => void> => mock(() => {});
14
+
15
+ describe("sentryAppVersionMiddleware", () => {
16
+ let setTagMock: Mock<(key: string, value: string) => void>;
17
+
18
+ beforeEach(() => {
19
+ // bunSetup.ts mocks @sentry/bun so that getCurrentScope() returns a scope
20
+ // with a Bun mock setTag. Clear that mock between tests so each assertion
21
+ // sees only its own calls.
22
+ setTagMock = Sentry.getCurrentScope().setTag as unknown as Mock<
23
+ (key: string, value: string) => void
24
+ >;
25
+ setTagMock.mockClear();
26
+ });
27
+
28
+ it("sets the app_version tag when the App-Version header is present", () => {
29
+ const next = buildNext();
30
+ const req = buildReq({"App-Version": "1.2.3"});
31
+
32
+ sentryAppVersionMiddleware(req, {} as Response, next as unknown as NextFunction);
33
+
34
+ expect(setTagMock).toHaveBeenCalledTimes(1);
35
+ expect(setTagMock.mock.calls[0]).toEqual(["app_version", "1.2.3"]);
36
+ expect(next).toHaveBeenCalledTimes(1);
37
+ });
38
+
39
+ it("does not set a tag when the App-Version header is missing", () => {
40
+ const next = buildNext();
41
+ const req = buildReq({});
42
+
43
+ sentryAppVersionMiddleware(req, {} as Response, next as unknown as NextFunction);
44
+
45
+ expect(setTagMock).not.toHaveBeenCalled();
46
+ expect(next).toHaveBeenCalledTimes(1);
47
+ });
48
+
49
+ it("does not set a tag when the App-Version header is an empty string", () => {
50
+ const next = buildNext();
51
+ const req = buildReq({"App-Version": ""});
52
+
53
+ sentryAppVersionMiddleware(req, {} as Response, next as unknown as NextFunction);
54
+
55
+ expect(setTagMock).not.toHaveBeenCalled();
56
+ expect(next).toHaveBeenCalledTimes(1);
57
+ });
58
+
59
+ it("calls next exactly once with no arguments when the header is present", () => {
60
+ const next = buildNext();
61
+
62
+ sentryAppVersionMiddleware(
63
+ buildReq({"App-Version": "9.9.9"}),
64
+ {} as Response,
65
+ next as unknown as NextFunction
66
+ );
67
+
68
+ expect(next).toHaveBeenCalledTimes(1);
69
+ expect(next.mock.calls[0]).toHaveLength(0);
70
+ });
71
+ });
package/src/middleware.ts CHANGED
@@ -9,10 +9,14 @@ import type {NextFunction, Request, Response} from "express";
9
9
  *
10
10
  * Expected header: `App-Version`
11
11
  */
12
- export function sentryAppVersionMiddleware(req: Request, _res: Response, next: NextFunction): void {
12
+ export const sentryAppVersionMiddleware = (
13
+ req: Request,
14
+ _res: Response,
15
+ next: NextFunction
16
+ ): void => {
13
17
  const appVersion = req.get("App-Version");
14
18
  if (appVersion) {
15
19
  Sentry.getCurrentScope().setTag("app_version", appVersion);
16
20
  }
17
21
  next();
18
- }
22
+ };
@@ -34,13 +34,14 @@ export const sendToGoogleChat = async (
34
34
 
35
35
  try {
36
36
  await axios.post(chatWebhookUrl, {text: formattedMessageText});
37
- } catch (error: any) {
38
- logger.error(`Error posting to Google Chat: ${error.text ?? error.message}`);
37
+ } catch (error: unknown) {
38
+ const errorObj = error as {text?: string; message?: string};
39
+ logger.error(`Error posting to Google Chat: ${errorObj.text ?? errorObj.message}`);
39
40
  Sentry.captureException(error);
40
41
  if (shouldThrow) {
41
42
  throw new APIError({
42
43
  status: 500,
43
- title: `Error posting to Google Chat: ${error.text ?? error.message}`,
44
+ title: `Error posting to Google Chat: ${errorObj.text ?? errorObj.message}`,
44
45
  });
45
46
  }
46
47
  }
@@ -95,13 +95,14 @@ export const sendToZoom = async (
95
95
  },
96
96
  }
97
97
  );
98
- } catch (error: any) {
99
- logger.error(`Error posting to Zoom: ${error.text ?? error.message}`);
98
+ } catch (error: unknown) {
99
+ const errorMessage = error instanceof Error ? error.message : String(error);
100
+ logger.error(`Error posting to Zoom: ${errorMessage}`);
100
101
  Sentry.captureException(error);
101
102
  if (shouldThrow) {
102
103
  throw new APIError({
103
104
  status: 500,
104
- title: `Error posting to Zoom: ${error.text ?? error.message}`,
105
+ title: `Error posting to Zoom: ${errorMessage}`,
105
106
  });
106
107
  }
107
108
  }
@@ -110,7 +110,7 @@ const patchRouterStack = (stack: any[]): void => {
110
110
  */
111
111
  export const patchAppUse = (app: any): void => {
112
112
  const originalUse = app.use.bind(app);
113
- app.use = function patchedUse(...args: any[]) {
113
+ const patchedUse = (...args: any[]): unknown => {
114
114
  // Track stack length before the call
115
115
  const router = app._router || app.router;
116
116
  const stackBefore = router?.stack?.length ?? 0;
@@ -132,6 +132,7 @@ export const patchAppUse = (app: any): void => {
132
132
 
133
133
  return result;
134
134
  };
135
+ app.use = patchedUse;
135
136
  };
136
137
 
137
138
  /**
@@ -6,7 +6,7 @@ import type {NextFunction, Request, Response} from "express";
6
6
  * This middleware should be added before the @wesleytodd/openapi middleware
7
7
  * to intercept requests to /openapi.json and add conditional request support.
8
8
  */
9
- export function openApiEtagMiddleware(req: Request, res: Response, next: NextFunction): void {
9
+ export const openApiEtagMiddleware = (req: Request, res: Response, next: NextFunction): void => {
10
10
  // Only handle GET requests to /openapi.json
11
11
  if (req.method !== "GET" || req.path !== "/openapi.json") {
12
12
  next();
@@ -37,4 +37,4 @@ export function openApiEtagMiddleware(req: Request, res: Response, next: NextFun
37
37
  };
38
38
 
39
39
  next();
40
- }
40
+ };
@@ -110,9 +110,9 @@ let globalConfig: OpenApiValidatorConfig = {
110
110
  * Check whether `configureOpenApiValidator()` has been called.
111
111
  * Validation middleware is a no-op when this returns false.
112
112
  */
113
- export function isOpenApiValidatorConfigured(): boolean {
113
+ export const isOpenApiValidatorConfigured = (): boolean => {
114
114
  return isConfigured;
115
- }
115
+ };
116
116
 
117
117
  /**
118
118
  * Configure the global OpenAPI validator settings.
@@ -131,28 +131,28 @@ export function isOpenApiValidatorConfigured(): boolean {
131
131
  * });
132
132
  * ```
133
133
  */
134
- export function configureOpenApiValidator(config: Partial<OpenApiValidatorConfig> = {}): void {
134
+ export const configureOpenApiValidator = (config: Partial<OpenApiValidatorConfig> = {}): void => {
135
135
  isConfigured = true;
136
136
  globalConfig = {...globalConfig, ...config};
137
137
  // Clear cached AJV instances so new config takes effect
138
138
  ajvCache.clear();
139
139
  validatorCache.clear();
140
140
  logger.debug(`OpenAPI validator configured: ${JSON.stringify(globalConfig)}`);
141
- }
141
+ };
142
142
 
143
143
  /**
144
144
  * Get the current global validator configuration.
145
145
  */
146
- export function getOpenApiValidatorConfig(): OpenApiValidatorConfig {
146
+ export const getOpenApiValidatorConfig = (): OpenApiValidatorConfig => {
147
147
  return {...globalConfig};
148
- }
148
+ };
149
149
 
150
150
  /**
151
151
  * Reset the global validator configuration to defaults.
152
152
  * Also resets `isConfigured` to false.
153
153
  * Useful for testing.
154
154
  */
155
- export function resetOpenApiValidatorConfig(): void {
155
+ export const resetOpenApiValidatorConfig = (): void => {
156
156
  isConfigured = false;
157
157
  globalConfig = {
158
158
  coerceTypes: true,
@@ -163,7 +163,7 @@ export function resetOpenApiValidatorConfig(): void {
163
163
  };
164
164
  ajvCache.clear();
165
165
  validatorCache.clear();
166
- }
166
+ };
167
167
 
168
168
  // Lazy AJV instance cache keyed by coerceTypes + removeAdditional
169
169
  const ajvCache = new Map<string, Ajv>();
@@ -171,7 +171,7 @@ const ajvCache = new Map<string, Ajv>();
171
171
  /**
172
172
  * Get or create an AJV instance with the current config settings.
173
173
  */
174
- function getAjvInstance(): Ajv {
174
+ const getAjvInstance = (): Ajv => {
175
175
  const key = `coerce:${globalConfig.coerceTypes ?? true},remove:${globalConfig.removeAdditional ?? true}`;
176
176
  let instance = ajvCache.get(key);
177
177
 
@@ -189,7 +189,7 @@ function getAjvInstance(): Ajv {
189
189
  }
190
190
 
191
191
  return instance;
192
- }
192
+ };
193
193
 
194
194
  // Cache compiled validators by schema hash + config key
195
195
  const validatorCache = new Map<string, ValidateFunction>();
@@ -197,9 +197,9 @@ const validatorCache = new Map<string, ValidateFunction>();
197
197
  /**
198
198
  * Generate a simple hash for a schema to use as a cache key.
199
199
  */
200
- function hashSchema(schema: OpenApiSchema): string {
200
+ const hashSchema = (schema: OpenApiSchema): string => {
201
201
  return JSON.stringify(schema);
202
- }
202
+ };
203
203
 
204
204
  const VALID_JSON_SCHEMA_TYPES = new Set([
205
205
  "string",
@@ -221,7 +221,7 @@ const MONGOOSE_TYPE_MAP: Record<string, {type: string; format?: string}> = {
221
221
  * Recursively replace non-standard mongoose-to-swagger types with valid JSON Schema types
222
222
  * so AJV can compile the schema.
223
223
  */
224
- function sanitizeSchemaForAjv(schema: Record<string, unknown>): Record<string, unknown> {
224
+ const sanitizeSchemaForAjv = (schema: Record<string, unknown>): Record<string, unknown> => {
225
225
  if (!schema || typeof schema !== "object") {
226
226
  return schema;
227
227
  }
@@ -262,7 +262,7 @@ function sanitizeSchemaForAjv(schema: Record<string, unknown>): Record<string, u
262
262
  }
263
263
 
264
264
  return result;
265
- }
265
+ };
266
266
 
267
267
  /**
268
268
  * Get or create a compiled validator for a schema.
@@ -270,7 +270,7 @@ function sanitizeSchemaForAjv(schema: Record<string, unknown>): Record<string, u
270
270
  * Sanitizes non-standard mongoose-to-swagger types before compilation.
271
271
  * Returns null if the schema still cannot be compiled after sanitization.
272
272
  */
273
- function getValidator(schema: OpenApiSchema): ValidateFunction | null {
273
+ const getValidator = (schema: OpenApiSchema): ValidateFunction | null => {
274
274
  const ajv = getAjvInstance();
275
275
  const configKey = `coerce:${globalConfig.coerceTypes ?? true},remove:${globalConfig.removeAdditional ?? true}`;
276
276
  const hash = `${configKey}:${hashSchema(schema)}`;
@@ -293,12 +293,12 @@ function getValidator(schema: OpenApiSchema): ValidateFunction | null {
293
293
  validatorCache.set(hash, null as unknown as ValidateFunction);
294
294
  return null;
295
295
  }
296
- }
296
+ };
297
297
 
298
298
  /**
299
299
  * Format AJV errors into a human-readable string.
300
300
  */
301
- function formatValidationErrors(errors: ErrorObject[]): string {
301
+ const formatValidationErrors = (errors: ErrorObject[]): string => {
302
302
  return errors
303
303
  .map((err) => {
304
304
  const path = err.instancePath || "/";
@@ -306,17 +306,17 @@ function formatValidationErrors(errors: ErrorObject[]): string {
306
306
  return `${path}: ${message}`;
307
307
  })
308
308
  .join("; ");
309
- }
309
+ };
310
310
 
311
311
  /**
312
312
  * Convert OpenApiSchemaProperty to a full OpenApiSchema suitable for AJV.
313
313
  * Strips `required` from individual properties (OpenAPI-style) and moves it
314
314
  * to the schema-level `required` array (JSON Schema-style) for AJV compatibility.
315
315
  */
316
- function propertiesToSchema(
316
+ const propertiesToSchema = (
317
317
  properties: Record<string, OpenApiSchemaProperty>,
318
318
  requiredFields?: string[]
319
- ): OpenApiSchema {
319
+ ): OpenApiSchema => {
320
320
  // Extract required fields from properties that have required: true
321
321
  const autoRequired = Object.entries(properties)
322
322
  .filter(([_, prop]) => prop.required)
@@ -344,7 +344,7 @@ function propertiesToSchema(
344
344
  }
345
345
 
346
346
  return schema;
347
- }
347
+ };
348
348
 
349
349
  /**
350
350
  * Options for the request body validator middleware.
@@ -388,10 +388,10 @@ export interface RequestBodyValidatorOptions {
388
388
  * @param options - Optional configuration for this validator
389
389
  * @returns Express middleware function
390
390
  */
391
- export function validateRequestBody(
391
+ export const validateRequestBody = (
392
392
  schema: Record<string, OpenApiSchemaProperty>,
393
393
  options?: RequestBodyValidatorOptions
394
- ): (req: Request, res: Response, next: NextFunction) => void {
394
+ ): ((req: Request, res: Response, next: NextFunction) => void) => {
395
395
  const fullSchema = propertiesToSchema(schema, options?.required);
396
396
 
397
397
  return (req: Request, _res: Response, next: NextFunction): void => {
@@ -491,7 +491,7 @@ export function validateRequestBody(
491
491
 
492
492
  next();
493
493
  };
494
- }
494
+ };
495
495
 
496
496
  /**
497
497
  * Options for the query parameter validator middleware.
@@ -515,10 +515,10 @@ export interface QueryValidatorOptions {
515
515
  * @param options - Optional configuration for this validator
516
516
  * @returns Express middleware function
517
517
  */
518
- export function validateQueryParams(
518
+ export const validateQueryParams = (
519
519
  schema: Record<string, OpenApiSchemaProperty>,
520
520
  options?: QueryValidatorOptions
521
- ): (req: Request, res: Response, next: NextFunction) => void {
521
+ ): ((req: Request, res: Response, next: NextFunction) => void) => {
522
522
  const fullSchema = propertiesToSchema(schema);
523
523
 
524
524
  return (req: Request, _res: Response, next: NextFunction): void => {
@@ -591,7 +591,7 @@ export function validateQueryParams(
591
591
 
592
592
  next();
593
593
  };
594
- }
594
+ };
595
595
 
596
596
  /**
597
597
  * Options for creating a combined validation middleware.
@@ -630,9 +630,9 @@ export interface CreateValidatorOptions {
630
630
  * ], handler);
631
631
  * ```
632
632
  */
633
- export function createValidator(
633
+ export const createValidator = (
634
634
  options: CreateValidatorOptions
635
- ): (req: Request, res: Response, next: NextFunction) => void {
635
+ ): ((req: Request, res: Response, next: NextFunction) => void) => {
636
636
  const bodyValidator = options.body
637
637
  ? validateRequestBody(options.body, {enabled: options.enabled})
638
638
  : null;
@@ -663,7 +663,7 @@ export function createValidator(
663
663
  next();
664
664
  }
665
665
  };
666
- }
666
+ };
667
667
 
668
668
  /**
669
669
  * Validates response data against a schema.
@@ -673,10 +673,10 @@ export function createValidator(
673
673
  * @param schema - The expected schema
674
674
  * @returns Object with valid flag and any errors
675
675
  */
676
- export function validateResponseData(
676
+ export const validateResponseData = (
677
677
  data: unknown,
678
678
  schema: Record<string, OpenApiSchemaProperty>
679
- ): {valid: boolean; errors?: ErrorObject[]} {
679
+ ): {valid: boolean; errors?: ErrorObject[]} => {
680
680
  if (!globalConfig.validateResponses) {
681
681
  return {valid: true};
682
682
  }
@@ -698,7 +698,7 @@ export function validateResponseData(
698
698
  }
699
699
 
700
700
  return {valid: true};
701
- }
701
+ };
702
702
 
703
703
  const m2sOptions = {
704
704
  props: ["readOnly", "required", "enum", "default"],
@@ -712,19 +712,19 @@ const m2sOptions = {
712
712
  * @param model - A Mongoose model
713
713
  * @returns Schema properties suitable for validation
714
714
  */
715
- export function getSchemaFromModel<T>(model: Model<T>): Record<string, OpenApiSchemaProperty> {
715
+ export const getSchemaFromModel = <T>(model: Model<T>): Record<string, OpenApiSchemaProperty> => {
716
716
  const modelSwagger = m2s(model, m2sOptions);
717
717
  fixMixedFields((model as any).schema, modelSwagger.properties);
718
718
  return modelSwagger.properties as Record<string, OpenApiSchemaProperty>;
719
- }
719
+ };
720
720
 
721
721
  /**
722
722
  * Extract required field names from a Mongoose model's swagger schema.
723
723
  */
724
- function getRequiredFieldsFromModel<T>(model: Model<T>): string[] {
724
+ const getRequiredFieldsFromModel = <T>(model: Model<T>): string[] => {
725
725
  const modelSwagger = m2s(model, m2sOptions);
726
726
  return (modelSwagger.required as string[]) ?? [];
727
- }
727
+ };
728
728
 
729
729
  /**
730
730
  * Creates a request body validator middleware from a Mongoose model.
@@ -734,10 +734,10 @@ function getRequiredFieldsFromModel<T>(model: Model<T>): string[] {
734
734
  * @param options - Optional configuration for the validator
735
735
  * @returns Express middleware function
736
736
  */
737
- export function validateModelRequestBody<T>(
737
+ export const validateModelRequestBody = <T>(
738
738
  model: Model<T>,
739
739
  options?: RequestBodyValidatorOptions
740
- ): (req: Request, res: Response, next: NextFunction) => void {
740
+ ): ((req: Request, res: Response, next: NextFunction) => void) => {
741
741
  let schema = getSchemaFromModel(model);
742
742
  let requiredFields = getRequiredFieldsFromModel(model);
743
743
 
@@ -751,7 +751,7 @@ export function validateModelRequestBody<T>(
751
751
  ...options,
752
752
  required: [...(options?.required ?? []), ...requiredFields],
753
753
  });
754
- }
754
+ };
755
755
 
756
756
  /**
757
757
  * Options for creating validation middleware for a modelRouter.
@@ -805,13 +805,13 @@ export interface ModelRouterValidationOptions {
805
805
  * @param options - Configuration options
806
806
  * @returns Object with create and update validation middleware
807
807
  */
808
- export function createModelValidators<T>(
808
+ export const createModelValidators = <T>(
809
809
  model: Model<T>,
810
810
  options?: ModelRouterValidationOptions
811
811
  ): {
812
812
  create: (req: Request, res: Response, next: NextFunction) => void;
813
813
  update: (req: Request, res: Response, next: NextFunction) => void;
814
- } {
814
+ } => {
815
815
  const schema = getSchemaFromModel(model);
816
816
 
817
817
  return {
@@ -826,7 +826,7 @@ export function createModelValidators<T>(
826
826
  onError: options?.onError,
827
827
  }),
828
828
  };
829
- }
829
+ };
830
830
 
831
831
  /**
832
832
  * Build a query parameter schema from a model's Mongoose schema and queryFields array.
@@ -836,10 +836,10 @@ export function createModelValidators<T>(
836
836
  * @param queryFields - Array of field names allowed for querying
837
837
  * @returns Schema properties suitable for query validation
838
838
  */
839
- export function buildQuerySchemaFromFields<T>(
839
+ export const buildQuerySchemaFromFields = <T>(
840
840
  model: Model<T>,
841
841
  queryFields: string[] = []
842
- ): Record<string, OpenApiSchemaProperty> {
842
+ ): Record<string, OpenApiSchemaProperty> => {
843
843
  const modelSchema = getSchemaFromModel(model);
844
844
  const querySchema: Record<string, OpenApiSchemaProperty> = {
845
845
  limit: {type: "number"},
@@ -859,4 +859,4 @@ export function buildQuerySchemaFromFields<T>(
859
859
  }
860
860
 
861
861
  return querySchema;
862
- }
862
+ };