@takaro/http 0.0.14 → 0.0.18

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 (42) hide show
  1. package/dist/app.d.ts +1 -0
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +1 -2
  4. package/dist/app.js.map +1 -1
  5. package/dist/controllers/meta.d.ts +3 -0
  6. package/dist/controllers/meta.d.ts.map +1 -0
  7. package/dist/controllers/meta.js +87 -2
  8. package/dist/controllers/meta.js.map +1 -1
  9. package/dist/main.d.ts +2 -0
  10. package/dist/main.d.ts.map +1 -0
  11. package/dist/main.js +1 -0
  12. package/dist/main.js.map +1 -1
  13. package/dist/middleware/basicAuth.d.ts +3 -0
  14. package/dist/middleware/basicAuth.d.ts.map +1 -0
  15. package/dist/middleware/basicAuth.js +27 -0
  16. package/dist/middleware/basicAuth.js.map +1 -0
  17. package/dist/middleware/errorHandler.d.ts +2 -1
  18. package/dist/middleware/errorHandler.d.ts.map +1 -0
  19. package/dist/middleware/errorHandler.js +4 -2
  20. package/dist/middleware/errorHandler.js.map +1 -1
  21. package/dist/middleware/logger.d.ts +5 -1
  22. package/dist/middleware/logger.d.ts.map +1 -0
  23. package/dist/middleware/logger.js.map +1 -1
  24. package/dist/middleware/metrics.d.ts +1 -0
  25. package/dist/middleware/metrics.d.ts.map +1 -0
  26. package/dist/middleware/paginationMiddleware.d.ts +1 -0
  27. package/dist/middleware/paginationMiddleware.d.ts.map +1 -0
  28. package/dist/middleware/rateLimit.d.ts +1 -0
  29. package/dist/middleware/rateLimit.d.ts.map +1 -0
  30. package/dist/util/apiResponse.d.ts +1 -0
  31. package/dist/util/apiResponse.d.ts.map +1 -0
  32. package/package.json +3 -6
  33. package/src/app.ts +1 -3
  34. package/src/controllers/__tests__/meta.integration.test.ts +3 -9
  35. package/src/controllers/meta.ts +87 -2
  36. package/src/main.ts +1 -0
  37. package/src/middleware/__tests__/paginationMiddleware.unit.test.ts +1 -0
  38. package/src/middleware/__tests__/rateLimit.integration.test.ts +14 -12
  39. package/src/middleware/basicAuth.ts +34 -0
  40. package/src/middleware/errorHandler.ts +4 -2
  41. package/src/middleware/logger.ts +1 -1
  42. package/tsconfig.json +1 -1
package/dist/app.d.ts CHANGED
@@ -18,3 +18,4 @@ export declare class HTTP {
18
18
  stop(): Promise<void>;
19
19
  }
20
20
  export {};
21
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,OAAwB,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAgB,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAoB,MAAM,qBAAqB,CAAC;AAUlF,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,qBAAa,IAAI;IAOb,OAAO,CAAC,WAAW;IANrB,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAC;gBAGb,OAAO,GAAE,yBAA8B,EAC/B,WAAW,GAAE,YAAiB;IA0DxC,IAAI,eAAe,wBAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEK,KAAK;IAML,IAAI;CAMX"}
package/dist/app.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import express from 'express';
3
3
  import { logger, errors, Sentry } from '@takaro/util';
4
- import { getBullBoard } from '@takaro/queues';
5
4
  import { createServer } from 'node:http';
6
5
  import { useExpressServer } from 'routing-controllers';
7
6
  import { Meta } from './controllers/meta.js';
@@ -20,6 +19,7 @@ export class HTTP {
20
19
  this.httpServer = createServer(this.app);
21
20
  this.app.use(Sentry.Handlers.requestHandler());
22
21
  this.app.use(bodyParser.json({
22
+ limit: '1mb',
23
23
  verify: (req, res, buf) => {
24
24
  req.rawBody = buf.toString();
25
25
  },
@@ -62,7 +62,6 @@ export class HTTP {
62
62
  validation: { whitelist: true, forbidNonWhitelisted: true },
63
63
  });
64
64
  }
65
- this.app.use('/queues', getBullBoard());
66
65
  this.app.use(Sentry.Handlers.errorHandler());
67
66
  this.app.use(ErrorHandler);
68
67
  }
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { Response } from 'express';
1
2
  import { OpenAPIObject } from 'openapi3-ts';
2
3
  export declare class HealthOutputDTO {
3
4
  healthy: boolean;
@@ -10,6 +11,8 @@ export declare class Meta {
10
11
  healthy: boolean;
11
12
  }>;
12
13
  getOpenApi(): Promise<OpenAPIObject>;
14
+ getRoot(res: Response): void;
13
15
  getOpenApiHtml(): string;
14
16
  getMetrics(): Promise<string>;
15
17
  }
18
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/controllers/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKnC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,qBAAa,eAAe;IAE1B,OAAO,EAAG,OAAO,CAAC;CACnB;AA+DD,qBACa,IAAI;IAGT,SAAS;;;IAMT,YAAY;;;IAMZ,UAAU;IAsHhB,OAAO,CAAQ,GAAG,EAAE,QAAQ;IAK5B,cAAc;IAwCd,UAAU;CAGX"}
@@ -7,13 +7,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- import { Controller, Get, getMetadataArgsStorage } from 'routing-controllers';
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Controller, Get, getMetadataArgsStorage, Res } from 'routing-controllers';
11
14
  import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
12
15
  import { routingControllersToSpec, ResponseSchema } from 'routing-controllers-openapi';
13
16
  import { IsBoolean } from 'class-validator';
14
17
  import { getMetrics, health } from '@takaro/util';
15
18
  import { PERMISSIONS } from '@takaro/auth';
16
19
  import { EventMapping } from '@takaro/modules';
20
+ import { randomUUID } from 'crypto';
21
+ import dedent from 'dedent';
17
22
  let spec;
18
23
  export class HealthOutputDTO {
19
24
  }
@@ -21,6 +26,62 @@ __decorate([
21
26
  IsBoolean(),
22
27
  __metadata("design:type", Boolean)
23
28
  ], HealthOutputDTO.prototype, "healthy", void 0);
29
+ function addSearchExamples(original) {
30
+ // Copy the spec so we don't mutate the original
31
+ const spec = JSON.parse(JSON.stringify(original));
32
+ // Add some examples and info to all the POST /search endpoints
33
+ Object.keys(spec.paths).forEach((pathKey) => {
34
+ const pathItem = spec?.paths[pathKey];
35
+ Object.keys(pathItem).forEach((method) => {
36
+ const operation = pathItem[method];
37
+ if (method === 'post' && pathKey.endsWith('/search')) {
38
+ const standardExamples = {
39
+ list: {
40
+ summary: 'List all',
41
+ value: {},
42
+ },
43
+ advanced: {
44
+ summary: 'Advanced search',
45
+ description: dedent `All /search endpoints allow you to combine different filters, search terms and ranges.
46
+ Filters are exact matches, search terms are partial matches and ranges are greater than or less than comparisons.
47
+ Ranges allow you to make queries like "all records created in the last 7 days" or "all records with an age greater than 18".
48
+
49
+ In search and filter sections, you pass an array of values for each property
50
+ These values are OR'ed together. So we'll get 2 records back in this case, if the IDs exist.
51
+
52
+ Eg: \`{"filters": {"id": ["${randomUUID()}", "${randomUUID()}"]}}\`
53
+
54
+ Different filters will be AND'ed together.
55
+ This will return all records where the name is John and the age is 19.
56
+
57
+ Eg: \`{"filters": {"name": "John", "age": 19}}\`
58
+ `,
59
+ value: {
60
+ filters: {
61
+ id: ['ea85ddf4-2885-482f-adc6-548fbe3fd8af'],
62
+ },
63
+ greaterThan: { createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() },
64
+ },
65
+ },
66
+ };
67
+ if (!operation.requestBody) {
68
+ operation.requestBody = {
69
+ content: {
70
+ 'application/json': {
71
+ examples: standardExamples,
72
+ },
73
+ },
74
+ };
75
+ }
76
+ operation.requestBody.content['application/json'].examples = {
77
+ ...standardExamples,
78
+ ...operation.requestBody.content['application/json'].examples,
79
+ };
80
+ }
81
+ });
82
+ });
83
+ return spec;
84
+ }
24
85
  let Meta = class Meta {
25
86
  async getHealth() {
26
87
  return { healthy: true };
@@ -92,11 +153,24 @@ let Meta = class Meta {
92
153
  const operation = pathItem[method];
93
154
  if (operation.operationId === operationId) {
94
155
  // Update the description with required permissions
95
- operation.description = (operation.description || '') + ` Required permissions: ${requiredPerms}`;
156
+ operation.description = (operation.description || '') + `\n\n Required permissions: ${requiredPerms}`;
96
157
  }
97
158
  });
98
159
  });
99
160
  });
161
+ // Add the operationId to the description, this helps users find the corresponding function call in the API client.
162
+ Object.keys(spec.paths).forEach((pathKey) => {
163
+ const pathItem = spec?.paths[pathKey];
164
+ Object.keys(pathItem).forEach((method) => {
165
+ const operation = pathItem[method];
166
+ // Api client exposes it as roleControllerSearch
167
+ // Current value is RoleController.search so lets adjust
168
+ // Capitalize the part after . and remove the .
169
+ const split = operation.operationId.split('.');
170
+ const cleanOperationId = split[0] + split[1].charAt(0).toUpperCase() + split[1].slice(1);
171
+ operation.description = (operation.description || '') + `<br> OperationId: \`${cleanOperationId}\``;
172
+ });
173
+ });
100
174
  if (spec.components?.schemas) {
101
175
  spec.components.schemas.PERMISSIONS = {
102
176
  enum: Object.values(PERMISSIONS),
@@ -111,8 +185,12 @@ let Meta = class Meta {
111
185
  oneOf: [...allEvents.map((e) => ({ $ref: `#/components/schemas/${e}` }))],
112
186
  };
113
187
  }
188
+ spec = addSearchExamples(spec);
114
189
  return spec;
115
190
  }
191
+ getRoot(res) {
192
+ return res.redirect('/api.html');
193
+ }
116
194
  getOpenApiHtml() {
117
195
  return `<!DOCTYPE html>
118
196
  <html>
@@ -175,6 +253,13 @@ __decorate([
175
253
  __metadata("design:paramtypes", []),
176
254
  __metadata("design:returntype", Promise)
177
255
  ], Meta.prototype, "getOpenApi", null);
256
+ __decorate([
257
+ Get('/'),
258
+ __param(0, Res()),
259
+ __metadata("design:type", Function),
260
+ __metadata("design:paramtypes", [Object]),
261
+ __metadata("design:returntype", void 0)
262
+ ], Meta.prototype, "getRoot", null);
178
263
  __decorate([
179
264
  Get('/api.html'),
180
265
  __metadata("design:type", Function),
@@ -1 +1 @@
1
- {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/controllers/meta.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/controllers/meta.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { HTTP } from './app.js';
2
2
  export * from './middleware/metrics.js';
3
3
  export { createRateLimitMiddleware } from './middleware/rateLimit.js';
4
+ export { getAdminBasicAuth } from './middleware/basicAuth.js';
4
5
  export { paginationMiddleware } from './middleware/paginationMiddleware.js';
5
6
  export { apiResponse, APIOutput } from './util/apiResponse.js';
6
7
  export { ErrorHandler } from './middleware/errorHandler.js';
8
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
package/dist/main.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { HTTP } from './app.js';
2
2
  export * from './middleware/metrics.js';
3
3
  export { createRateLimitMiddleware } from './middleware/rateLimit.js';
4
+ export { getAdminBasicAuth } from './middleware/basicAuth.js';
4
5
  export { paginationMiddleware } from './middleware/paginationMiddleware.js';
5
6
  export { apiResponse, APIOutput } from './util/apiResponse.js';
6
7
  export { ErrorHandler } from './middleware/errorHandler.js';
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export declare function getAdminBasicAuth(secret: string): (req: Request, res: Response, next: NextFunction) => void;
3
+ //# sourceMappingURL=basicAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basicAuth.d.ts","sourceRoot":"","sources":["../../src/middleware/basicAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,SACV,OAAO,OAAO,QAAQ,QAAQ,YAAY,UA8B/E"}
@@ -0,0 +1,27 @@
1
+ export function getAdminBasicAuth(secret) {
2
+ return function adminBasicAuth(req, res, next) {
3
+ const auth = req.headers.authorization;
4
+ // If no auth header is present, prompt for credentials
5
+ if (!auth) {
6
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
7
+ res.status(401).send('Authentication required');
8
+ return;
9
+ }
10
+ const [type, credentials] = auth.split(' ');
11
+ // Verify auth type is Basic
12
+ if (type !== 'Basic') {
13
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
14
+ res.status(401).send('Invalid authentication type');
15
+ return;
16
+ }
17
+ // Decode and verify credentials
18
+ const [username, password] = Buffer.from(credentials, 'base64').toString().split(':');
19
+ if (username !== 'admin' || password !== secret) {
20
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
21
+ res.status(401).send('Invalid credentials');
22
+ return;
23
+ }
24
+ next();
25
+ };
26
+ }
27
+ //# sourceMappingURL=basicAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basicAuth.js","sourceRoot":"","sources":["../../src/middleware/basicAuth.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,SAAS,cAAc,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAEvC,uDAAuD;QACvD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;YAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE5C,4BAA4B;QAC5B,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;YAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,gCAAgC;QAChC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEtF,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAChD,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;YAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -1,2 +1,3 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
- export declare function ErrorHandler(originalError: Error, req: Request, res: Response, _next: NextFunction): Promise<Response<any, Record<string, any>>>;
2
+ export declare function ErrorHandler(originalError: Error, req: Request, res: Response, _next: NextFunction): Promise<void>;
3
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAS1D,wBAAsB,YAAY,CAChC,aAAa,EAAE,KAAK,EACpB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EAEb,KAAK,EAAE,YAAY,iBA0EpB"}
@@ -11,7 +11,9 @@ export async function ErrorHandler(originalError, req, res, _next) {
11
11
  // @ts-expect-error Error typing is weird in ts... but we validate during runtime so should be OK
12
12
  const validationErrors = originalError['errors'];
13
13
  parsedError = new errors.ValidationError('Validation error', validationErrors);
14
- log.warn('⚠️ Validation errror', { details: validationErrors.map((e) => JSON.stringify(e.target, null, 2)) });
14
+ log.warn('⚠️ Validation errror', {
15
+ details: validationErrors.map((e) => JSON.stringify(e.constraints, null, 2)),
16
+ });
15
17
  }
16
18
  }
17
19
  if (originalError instanceof MulterError) {
@@ -61,6 +63,6 @@ export async function ErrorHandler(originalError, req, res, _next) {
61
63
  log.warn(`⚠️ FAIL ${req.method} ${req.originalUrl}`, parsedError);
62
64
  }
63
65
  res.status(status).json(apiResponse({}, { error: parsedError, req, res }));
64
- return res.end();
66
+ res.end();
65
67
  }
66
68
  //# sourceMappingURL=errorHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
+ import { NextFunction, Request, Response } from 'express';
1
2
  /**
2
3
  * This middleware is called very early in the request lifecycle, so it's
3
4
  * we leverage this fact to inject the context tracking at this stage
4
5
  */
5
- export declare const LoggingMiddleware: (...args: any[]) => unknown;
6
+ export declare const LoggingMiddleware: typeof loggingMiddleware;
7
+ declare function loggingMiddleware(req: Request, res: Response, next: NextFunction): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/middleware/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ1D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAA0C,OAAO,iBAAiB,CAAC;AAEjG,iBAAe,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,iBA+C/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/middleware/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,sBAAsB,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAC3D,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACrG,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAErE,KAAK,UAAU,iBAAiB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC9E,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAE9G,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE;QAC/C,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,WAAW;QACrB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI;KACxD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7C,IAAI,IAAI,EAAE,CAAC;QACT,2DAA2D;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC;QAC3C,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,6CAA6C;IAC7C,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC;QAEjD,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE;YAC9C,YAAY;YACZ,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC1C,MAAM,EAAE,GAAG,CAAC,UAAU;YACtB,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC;YAC7C,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;YAChC,QAAQ,EAAE,GAAG,CAAC,EAAE;YAChB,QAAQ,EAAE,WAAW;YACrB,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC;YAC3B,WAAW,EAAE,KAAK;YAClB,QAAQ,EAAE,KAAK;YACf,8BAA8B,EAAE,KAAK;YACrC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/middleware/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,sBAAsB,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAC3D,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACrG,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE3B;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAA6B,CAAC;AAEjG,KAAK,UAAU,iBAAiB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC9E,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAE9G,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE;QAC/C,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,WAAW;QACrB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI;KACxD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7C,IAAI,IAAI,EAAE,CAAC;QACT,2DAA2D;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC;QAC3C,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,6CAA6C;IAC7C,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC;QAEjD,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE;YAC9C,YAAY;YACZ,aAAa,EAAE,GAAG,CAAC,MAAM;YACzB,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC1C,MAAM,EAAE,GAAG,CAAC,UAAU;YACtB,YAAY,EAAE,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC;YAC7C,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;YAChC,QAAQ,EAAE,GAAG,CAAC,EAAE;YAChB,QAAQ,EAAE,WAAW;YACrB,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC;YAC3B,WAAW,EAAE,KAAK;YAClB,QAAQ,EAAE,KAAK;YACf,8BAA8B,EAAE,KAAK;YACrC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -1,2 +1,3 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
2
  export declare function metricsMiddleware(req: Request, res: Response, next: NextFunction): Promise<void>;
3
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/middleware/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgB1D,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,iBAyBtF"}
@@ -1,2 +1,3 @@
1
1
  import { NextFunction, Request, Response } from 'express';
2
2
  export declare function paginationMiddleware(req: Request, res: Response, next: NextFunction): Promise<void>;
3
+ //# sourceMappingURL=paginationMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paginationMiddleware.d.ts","sourceRoot":"","sources":["../../src/middleware/paginationMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAW1D,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzG"}
@@ -6,3 +6,4 @@ export interface IRateLimitMiddlewareOptions {
6
6
  useInMemory?: boolean;
7
7
  }
8
8
  export declare function createRateLimitMiddleware(opts: IRateLimitMiddlewareOptions): Promise<(req: Request, res: Response, next: NextFunction) => Promise<void>>;
9
+ //# sourceMappingURL=rateLimit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,2BAA2B,iBAyB5D,OAAO,OAAO,QAAQ,QAAQ,YAAY,oBAmC9D"}
@@ -34,3 +34,4 @@ interface IApiResponseOptions {
34
34
  }
35
35
  export declare function apiResponse(data?: unknown, opts?: IApiResponseOptions): APIOutput<unknown>;
36
36
  export {};
37
+ //# sourceMappingURL=apiResponse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiResponse.d.ts","sourceRoot":"","sources":["../../src/util/apiResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,EAML,eAAe,IAAI,mBAAmB,EACvC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,cAAM,WAAW;IAEf,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,CAAC,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAAC;CAC1C;AAED,cAAM,cAAc;IAGlB,UAAU,EAAG,MAAM,CAAC;IAIpB,KAAK,CAAC,EAAE,WAAW,CAAC;IAEpB;;OAEG;IAGH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IAGH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IAGH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAGvD,IAAI,EAAG,cAAc,CAAC;IAEtB,IAAI,EAAG,CAAC,CAAC;CACV;AAED,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACvC,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,OAAY,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,CA2C9F"}
package/package.json CHANGED
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "@takaro/http",
3
- "version": "0.0.14",
3
+ "version": "0.0.18",
4
4
  "description": "An opinionated http server",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "start:dev": "tsc --watch --preserveWatchOutput -p ./tsconfig.build.json",
10
- "build": "tsc -p ./tsconfig.build.json",
11
- "test": "npm run test:unit --if-present && npm run test:integration --if-present",
12
- "test:unit": "mocha --config ../../.mocharc.js src/**/*.unit.test.ts --exit",
13
- "test:integration": "mocha --config ../../.mocharc.js src/**/*.integration.test.ts --exit"
10
+ "build": "tsc -p ./tsconfig.build.json"
14
11
  },
15
12
  "keywords": [],
16
13
  "author": "",
@@ -27,7 +24,7 @@
27
24
  "devDependencies": {
28
25
  "@types/cookie-parser": "1.4.7",
29
26
  "@types/cors": "2.8.17",
30
- "@types/express": "4.17.21",
27
+ "@types/express": "5.0.0",
31
28
  "supertest": "6.3.4"
32
29
  }
33
30
  }
package/src/app.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import express, { Application } from 'express';
3
3
  import { logger, errors, Sentry } from '@takaro/util';
4
- import { getBullBoard } from '@takaro/queues';
5
4
  import { Server, createServer } from 'node:http';
6
5
  import { RoutingControllersOptions, useExpressServer } from 'routing-controllers';
7
6
  import { Meta } from './controllers/meta.js';
@@ -33,6 +32,7 @@ export class HTTP {
33
32
  this.app.use(Sentry.Handlers.requestHandler());
34
33
  this.app.use(
35
34
  bodyParser.json({
35
+ limit: '1mb',
36
36
  verify: (req, res, buf) => {
37
37
  (req as any).rawBody = buf.toString();
38
38
  },
@@ -77,8 +77,6 @@ export class HTTP {
77
77
  });
78
78
  }
79
79
 
80
- this.app.use('/queues', getBullBoard());
81
-
82
80
  this.app.use(Sentry.Handlers.errorHandler());
83
81
 
84
82
  this.app.use(ErrorHandler);
@@ -1,6 +1,6 @@
1
1
  import { HTTP } from '../../app.js';
2
2
  import supertest from 'supertest';
3
- import { expect } from '@takaro/test';
3
+ import { describe, it, before, after } from 'node:test';
4
4
 
5
5
  describe('app', () => {
6
6
  let http: HTTP;
@@ -14,16 +14,10 @@ describe('app', () => {
14
14
  });
15
15
 
16
16
  it('Serves a health status', async () => {
17
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
18
- // @ts-ignore
19
- const response = await supertest(http.expressInstance).get('/healthz');
20
- expect(response.status).to.be.equal(200);
17
+ await supertest(http.expressInstance).get('/healthz').expect(200);
21
18
  });
22
19
 
23
20
  it('Serves a open api spec', async () => {
24
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
25
- // @ts-ignore
26
- const response = await supertest(http.expressInstance).get('/openapi.json');
27
- expect(response.status).to.be.equal(200);
21
+ await supertest(http.expressInstance).get('/openapi.json').expect(200);
28
22
  });
29
23
  });
@@ -1,4 +1,5 @@
1
- import { Controller, Get, getMetadataArgsStorage } from 'routing-controllers';
1
+ import { Controller, Get, getMetadataArgsStorage, Res } from 'routing-controllers';
2
+ import { Response } from 'express';
2
3
  import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
3
4
  import { routingControllersToSpec, ResponseSchema } from 'routing-controllers-openapi';
4
5
  import { IsBoolean } from 'class-validator';
@@ -6,6 +7,8 @@ import { getMetrics, health } from '@takaro/util';
6
7
  import { OpenAPIObject } from 'openapi3-ts';
7
8
  import { PERMISSIONS } from '@takaro/auth';
8
9
  import { EventMapping } from '@takaro/modules';
10
+ import { randomUUID } from 'crypto';
11
+ import dedent from 'dedent';
9
12
 
10
13
  let spec: OpenAPIObject | undefined;
11
14
 
@@ -13,6 +16,68 @@ export class HealthOutputDTO {
13
16
  @IsBoolean()
14
17
  healthy!: boolean;
15
18
  }
19
+
20
+ function addSearchExamples(original: OpenAPIObject): OpenAPIObject {
21
+ // Copy the spec so we don't mutate the original
22
+ const spec = JSON.parse(JSON.stringify(original));
23
+
24
+ // Add some examples and info to all the POST /search endpoints
25
+ Object.keys(spec.paths).forEach((pathKey) => {
26
+ const pathItem = spec?.paths[pathKey];
27
+ Object.keys(pathItem).forEach((method) => {
28
+ const operation = pathItem[method];
29
+ if (method === 'post' && pathKey.endsWith('/search')) {
30
+ const standardExamples = {
31
+ list: {
32
+ summary: 'List all',
33
+ value: {},
34
+ },
35
+ advanced: {
36
+ summary: 'Advanced search',
37
+ description: dedent`All /search endpoints allow you to combine different filters, search terms and ranges.
38
+ Filters are exact matches, search terms are partial matches and ranges are greater than or less than comparisons.
39
+ Ranges allow you to make queries like "all records created in the last 7 days" or "all records with an age greater than 18".
40
+
41
+ In search and filter sections, you pass an array of values for each property
42
+ These values are OR'ed together. So we'll get 2 records back in this case, if the IDs exist.
43
+
44
+ Eg: \`{"filters": {"id": ["${randomUUID()}", "${randomUUID()}"]}}\`
45
+
46
+ Different filters will be AND'ed together.
47
+ This will return all records where the name is John and the age is 19.
48
+
49
+ Eg: \`{"filters": {"name": "John", "age": 19}}\`
50
+ `,
51
+ value: {
52
+ filters: {
53
+ id: ['ea85ddf4-2885-482f-adc6-548fbe3fd8af'],
54
+ },
55
+ greaterThan: { createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() },
56
+ },
57
+ },
58
+ };
59
+
60
+ if (!operation.requestBody) {
61
+ operation.requestBody = {
62
+ content: {
63
+ 'application/json': {
64
+ examples: standardExamples,
65
+ },
66
+ },
67
+ };
68
+ }
69
+
70
+ operation.requestBody.content['application/json'].examples = {
71
+ ...standardExamples,
72
+ ...operation.requestBody.content['application/json'].examples,
73
+ };
74
+ }
75
+ });
76
+ });
77
+
78
+ return spec;
79
+ }
80
+
16
81
  @Controller()
17
82
  export class Meta {
18
83
  @Get('/healthz')
@@ -105,12 +170,26 @@ export class Meta {
105
170
  const operation = pathItem[method];
106
171
  if (operation.operationId === operationId) {
107
172
  // Update the description with required permissions
108
- operation.description = (operation.description || '') + ` Required permissions: ${requiredPerms}`;
173
+ operation.description = (operation.description || '') + `\n\n Required permissions: ${requiredPerms}`;
109
174
  }
110
175
  });
111
176
  });
112
177
  });
113
178
 
179
+ // Add the operationId to the description, this helps users find the corresponding function call in the API client.
180
+ Object.keys(spec.paths).forEach((pathKey) => {
181
+ const pathItem = spec?.paths[pathKey];
182
+ Object.keys(pathItem).forEach((method) => {
183
+ const operation = pathItem[method];
184
+ // Api client exposes it as roleControllerSearch
185
+ // Current value is RoleController.search so lets adjust
186
+ // Capitalize the part after . and remove the .
187
+ const split = operation.operationId.split('.');
188
+ const cleanOperationId = split[0] + split[1].charAt(0).toUpperCase() + split[1].slice(1);
189
+ operation.description = (operation.description || '') + `<br> OperationId: \`${cleanOperationId}\``;
190
+ });
191
+ });
192
+
114
193
  if (spec.components?.schemas) {
115
194
  spec.components.schemas.PERMISSIONS = {
116
195
  enum: Object.values(PERMISSIONS),
@@ -128,9 +207,15 @@ export class Meta {
128
207
  };
129
208
  }
130
209
 
210
+ spec = addSearchExamples(spec);
131
211
  return spec;
132
212
  }
133
213
 
214
+ @Get('/')
215
+ getRoot(@Res() res: Response) {
216
+ return res.redirect('/api.html');
217
+ }
218
+
134
219
  @Get('/api.html')
135
220
  getOpenApiHtml() {
136
221
  return `<!DOCTYPE html>
package/src/main.ts CHANGED
@@ -2,6 +2,7 @@ export { HTTP } from './app.js';
2
2
 
3
3
  export * from './middleware/metrics.js';
4
4
  export { createRateLimitMiddleware } from './middleware/rateLimit.js';
5
+ export { getAdminBasicAuth } from './middleware/basicAuth.js';
5
6
  export { paginationMiddleware } from './middleware/paginationMiddleware.js';
6
7
  export { apiResponse, APIOutput } from './util/apiResponse.js';
7
8
  export { ErrorHandler } from './middleware/errorHandler.js';
@@ -2,6 +2,7 @@ import { sandbox, expect } from '@takaro/test';
2
2
  import { NextFunction, Request, Response } from 'express';
3
3
  import { errors } from '@takaro/util';
4
4
  import { paginationMiddleware } from '../paginationMiddleware.js';
5
+ import { describe, it } from 'node:test';
5
6
 
6
7
  async function runPagination(page?: number, limit?: number) {
7
8
  const req = { query: { page, limit } } as unknown as Request;
@@ -1,11 +1,11 @@
1
1
  import { Response, NextFunction, Request } from 'express';
2
2
  import { Redis } from '@takaro/db';
3
- import { expect } from '@takaro/test';
4
3
  import { Controller, UseBefore, Get } from 'routing-controllers';
5
4
  import { HTTP } from '../../main.js';
6
5
  import { createRateLimitMiddleware } from '../rateLimit.js';
7
6
  import { ctx } from '@takaro/util';
8
7
  import supertest from 'supertest';
8
+ import { describe, beforeEach, afterEach, after, it } from 'node:test';
9
9
 
10
10
  describe('rateLimit middleware', () => {
11
11
  let http: HTTP;
@@ -112,17 +112,19 @@ describe('rateLimit middleware', () => {
112
112
  const agent = supertest(http.expressInstance);
113
113
 
114
114
  for (let i = 1; i < 5; i++) {
115
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
116
- // @ts-ignore
117
- const res = await agent.get('/low-limit').expect(200);
118
- expect(res.header['x-ratelimit-remaining']).to.equal((5 - i).toString());
119
- expect(res.header['x-ratelimit-limit']).to.equal('5');
120
- expect(res.header['x-ratelimit-reset']).to.be.a('string');
115
+ await agent
116
+ .get('/low-limit')
117
+ .expect(200)
118
+ .expect('x-ratelimit-remaining', (5 - i).toString())
119
+ .expect('x-ratelimit-limit', '5')
120
+ .expect('x-ratelimit-reset', /\d+/);
121
121
  }
122
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
123
- // @ts-ignore
124
- const res = await agent.get('/low-limit').expect(429);
125
- expect(res.header['x-ratelimit-remaining']).to.equal('0');
126
- expect(res.header['x-ratelimit-limit']).to.equal('5');
122
+
123
+ agent
124
+ .get('/low-limit')
125
+ .expect(429)
126
+ .expect('x-ratelimit-remaining', '0')
127
+ .expect('x-ratelimit-limit', '5')
128
+ .expect('x-ratelimit-reset', /\d+/);
127
129
  });
128
130
  });
@@ -0,0 +1,34 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ export function getAdminBasicAuth(secret: string) {
4
+ return function adminBasicAuth(req: Request, res: Response, next: NextFunction) {
5
+ const auth = req.headers.authorization;
6
+
7
+ // If no auth header is present, prompt for credentials
8
+ if (!auth) {
9
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
10
+ res.status(401).send('Authentication required');
11
+ return;
12
+ }
13
+
14
+ const [type, credentials] = auth.split(' ');
15
+
16
+ // Verify auth type is Basic
17
+ if (type !== 'Basic') {
18
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
19
+ res.status(401).send('Invalid authentication type');
20
+ return;
21
+ }
22
+
23
+ // Decode and verify credentials
24
+ const [username, password] = Buffer.from(credentials, 'base64').toString().split(':');
25
+
26
+ if (username !== 'admin' || password !== secret) {
27
+ res.set('WWW-Authenticate', 'Basic realm="Admin Access"');
28
+ res.status(401).send('Invalid credentials');
29
+ return;
30
+ }
31
+
32
+ next();
33
+ };
34
+ }
@@ -22,7 +22,9 @@ export async function ErrorHandler(
22
22
  // @ts-expect-error Error typing is weird in ts... but we validate during runtime so should be OK
23
23
  const validationErrors = originalError['errors'] as ValidationError[];
24
24
  parsedError = new errors.ValidationError('Validation error', validationErrors);
25
- log.warn('⚠️ Validation errror', { details: validationErrors.map((e) => JSON.stringify(e.target, null, 2)) });
25
+ log.warn('⚠️ Validation errror', {
26
+ details: validationErrors.map((e) => JSON.stringify(e.constraints, null, 2)),
27
+ });
26
28
  }
27
29
  }
28
30
 
@@ -83,5 +85,5 @@ export async function ErrorHandler(
83
85
  }
84
86
 
85
87
  res.status(status).json(apiResponse({}, { error: parsedError, req, res }));
86
- return res.end();
88
+ res.end();
87
89
  }
@@ -10,7 +10,7 @@ const log = logger('http');
10
10
  * This middleware is called very early in the request lifecycle, so it's
11
11
  * we leverage this fact to inject the context tracking at this stage
12
12
  */
13
- export const LoggingMiddleware = ctx.wrap('HTTP', loggingMiddleware);
13
+ export const LoggingMiddleware = ctx.wrap('HTTP', loggingMiddleware) as typeof loggingMiddleware;
14
14
 
15
15
  async function loggingMiddleware(req: Request, res: Response, next: NextFunction) {
16
16
  if (HIDDEN_ROUTES.some((route) => req.originalUrl.startsWith(route))) {
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../../tsconfig.esm.json",
2
+ "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "rootDir": "src",
5
5
  "outDir": "dist"