@internetderdinge/api 1.229.0 → 1.229.1

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 (167) hide show
  1. package/dist/src/accounts/accounts.controller.js +89 -0
  2. package/dist/src/accounts/accounts.route.js +101 -0
  3. package/dist/src/accounts/accounts.schemas.js +12 -0
  4. package/dist/src/accounts/accounts.service.js +65 -0
  5. package/dist/src/accounts/accounts.validation.js +99 -0
  6. package/dist/src/accounts/auth0.service.js +188 -0
  7. package/dist/src/config/config.js +48 -0
  8. package/dist/src/config/logger.js +27 -0
  9. package/dist/src/config/morgan.js +16 -0
  10. package/dist/src/config/passport.cjs +28 -0
  11. package/dist/src/config/roles.js +11 -0
  12. package/dist/src/config/tokens.cjs +10 -0
  13. package/dist/src/devices/devices.controller.js +172 -0
  14. package/dist/src/devices/devices.model.js +94 -0
  15. package/dist/src/devices/devices.route.js +153 -0
  16. package/dist/src/devices/devices.schemas.js +84 -0
  17. package/dist/src/devices/devices.service.js +198 -0
  18. package/dist/src/devices/devices.types.js +1 -0
  19. package/dist/src/devices/devices.validation.js +257 -0
  20. package/dist/src/devicesNotifications/devicesNotifications.controller.js +69 -0
  21. package/dist/src/devicesNotifications/devicesNotifications.model.js +39 -0
  22. package/dist/src/devicesNotifications/devicesNotifications.route.js +124 -0
  23. package/dist/src/devicesNotifications/devicesNotifications.schemas.js +10 -0
  24. package/dist/src/devicesNotifications/devicesNotifications.service.js +181 -0
  25. package/dist/src/devicesNotifications/devicesNotifications.validation.js +46 -0
  26. package/dist/src/email/email.service.js +580 -0
  27. package/dist/src/files/upload.service.js +124 -0
  28. package/dist/src/i18n/i18n.js +38 -0
  29. package/dist/src/i18n/saveMissingLocalJsonBackend.js +53 -0
  30. package/dist/src/i18n/types.js +1 -0
  31. package/dist/src/index.js +48 -0
  32. package/dist/src/iotdevice/iotdevice.controller.js +96 -0
  33. package/dist/src/iotdevice/iotdevice.model.js +17 -0
  34. package/dist/src/iotdevice/iotdevice.route.js +143 -0
  35. package/dist/src/iotdevice/iotdevice.schemas.js +60 -0
  36. package/dist/src/iotdevice/iotdevice.service.js +579 -0
  37. package/dist/src/iotdevice/iotdevice.types.js +1 -0
  38. package/dist/src/iotdevice/iotdevice.validation.js +54 -0
  39. package/dist/src/middlewares/auth.js +75 -0
  40. package/dist/src/middlewares/checkJwt.cjs +17 -0
  41. package/dist/src/middlewares/error.js +36 -0
  42. package/dist/src/middlewares/mongooseValidations/ensureSameOrganization.js +13 -0
  43. package/dist/src/middlewares/rateLimiter.js +7 -0
  44. package/dist/src/middlewares/validate.js +18 -0
  45. package/dist/src/middlewares/validateAction.js +35 -0
  46. package/dist/src/middlewares/validateAdmin.js +18 -0
  47. package/dist/src/middlewares/validateAi.js +16 -0
  48. package/dist/src/middlewares/validateCurrentAuthUser.js +17 -0
  49. package/dist/src/middlewares/validateCurrentUser.js +20 -0
  50. package/dist/src/middlewares/validateDevice.js +98 -0
  51. package/dist/src/middlewares/validateDeviceUserOrganization.js +26 -0
  52. package/dist/src/middlewares/validateOrganization.js +63 -0
  53. package/dist/src/middlewares/validateQuerySearchUserAndOrganization.js +44 -0
  54. package/dist/src/middlewares/validateTokens.js +23 -0
  55. package/dist/src/middlewares/validateUser.js +38 -0
  56. package/dist/src/middlewares/validateZod.js +33 -0
  57. package/dist/src/models/plugins/index.js +4 -0
  58. package/dist/src/models/plugins/paginate.plugin.js +117 -0
  59. package/dist/src/models/plugins/paginateNew.plugin.js +185 -0
  60. package/dist/src/models/plugins/simplePopulate.js +16 -0
  61. package/dist/src/models/plugins/toJSON.plugin.js +35 -0
  62. package/dist/src/organizations/organizations.controller.js +64 -0
  63. package/dist/src/organizations/organizations.model.js +41 -0
  64. package/dist/src/organizations/organizations.route.js +98 -0
  65. package/dist/src/organizations/organizations.schemas.js +7 -0
  66. package/dist/src/organizations/organizations.service.js +59 -0
  67. package/dist/src/organizations/organizations.validation.js +62 -0
  68. package/dist/src/pdf/pdf.controller.js +24 -0
  69. package/dist/src/pdf/pdf.route.js +22 -0
  70. package/dist/src/pdf/pdf.schemas.js +6 -0
  71. package/dist/src/pdf/pdf.service.js +65 -0
  72. package/dist/src/pdf/pdf.validation.js +27 -0
  73. package/dist/src/tokens/tokens.controller.js +60 -0
  74. package/dist/src/tokens/tokens.model.js +18 -0
  75. package/dist/src/tokens/tokens.route.js +52 -0
  76. package/dist/src/tokens/tokens.schemas.js +14 -0
  77. package/dist/src/tokens/tokens.service.js +30 -0
  78. package/dist/src/tokens/tokens.validation.js +9 -0
  79. package/dist/src/types/routeSpec.js +1 -0
  80. package/dist/src/users/users.controller.js +147 -0
  81. package/dist/src/users/users.model.js +50 -0
  82. package/dist/src/users/users.route.js +137 -0
  83. package/dist/src/users/users.schemas.js +69 -0
  84. package/dist/src/users/users.service.js +295 -0
  85. package/dist/src/users/users.types.js +1 -0
  86. package/dist/src/users/users.validation.js +144 -0
  87. package/dist/src/utils/ApiError.js +16 -0
  88. package/dist/src/utils/buildRouterAndDocs.js +72 -0
  89. package/dist/src/utils/catchAsync.js +4 -0
  90. package/dist/src/utils/comparePapers.service.js +32 -0
  91. package/dist/src/utils/deviceUtils.js +63 -0
  92. package/dist/src/utils/filterOptions.js +24 -0
  93. package/dist/src/utils/medicationName.js +10 -0
  94. package/dist/src/utils/pick.js +16 -0
  95. package/dist/src/utils/registerOpenApi.js +28 -0
  96. package/dist/src/utils/urlUtils.js +15 -0
  97. package/dist/src/utils/userName.js +22 -0
  98. package/dist/src/utils/zValidations.js +124 -0
  99. package/dist/src/validations/auth.validation.cjs +53 -0
  100. package/dist/src/validations/custom.validation.js +19 -0
  101. package/dist/src/validations/index.cjs +3 -0
  102. package/package.json +13 -3
  103. package/scripts/release-and-sync-paperless.mjs +135 -0
  104. package/src/accounts/accounts.controller.ts +1 -0
  105. package/src/accounts/accounts.service.ts +1 -0
  106. package/src/accounts/accounts.validation.ts +6 -3
  107. package/src/accounts/auth0.service.ts +55 -28
  108. package/src/config/config.ts +6 -0
  109. package/src/config/logger.ts +15 -9
  110. package/src/devices/devices.controller.ts +7 -1
  111. package/src/devices/devices.model.ts +4 -1
  112. package/src/devices/devices.schemas.ts +10 -8
  113. package/src/devices/devices.service.ts +1 -0
  114. package/src/devices/devices.types.ts +1 -0
  115. package/src/devices/devices.validation.ts +85 -23
  116. package/src/devicesNotifications/devicesNotifications.controller.ts +57 -28
  117. package/src/devicesNotifications/devicesNotifications.model.ts +20 -12
  118. package/src/devicesNotifications/devicesNotifications.service.ts +35 -17
  119. package/src/files/upload.service.ts +52 -28
  120. package/src/i18n/i18n.ts +1 -1
  121. package/src/i18n/types.ts +1 -0
  122. package/src/index.ts +47 -0
  123. package/src/iotdevice/iotdevice.controller.ts +1 -0
  124. package/src/iotdevice/iotdevice.model.ts +6 -3
  125. package/src/iotdevice/iotdevice.route.ts +85 -76
  126. package/src/iotdevice/iotdevice.service.ts +4 -3
  127. package/src/iotdevice/iotdevice.types.ts +6 -0
  128. package/src/middlewares/auth.ts +2 -8
  129. package/src/middlewares/error.ts +26 -12
  130. package/src/middlewares/mongooseValidations/ensureSameOrganization.ts +4 -3
  131. package/src/middlewares/validateAi.ts +17 -9
  132. package/src/middlewares/validateDevice.ts +1 -0
  133. package/src/middlewares/validateDeviceUserOrganization.ts +1 -0
  134. package/src/middlewares/validateOrganization.ts +1 -1
  135. package/src/middlewares/validateQuerySearchUserAndOrganization.ts +1 -0
  136. package/src/middlewares/validateTokens.ts +2 -1
  137. package/src/middlewares/validateUser.ts +1 -0
  138. package/src/models/plugins/index.ts +5 -4
  139. package/src/models/plugins/paginate.plugin.ts +26 -16
  140. package/src/models/plugins/paginateNew.plugin.ts +33 -21
  141. package/src/models/plugins/simplePopulate.ts +8 -3
  142. package/src/models/plugins/toJSON.plugin.ts +12 -5
  143. package/src/organizations/organizations.controller.ts +1 -2
  144. package/src/organizations/organizations.model.ts +4 -4
  145. package/src/organizations/organizations.route.ts +1 -1
  146. package/src/organizations/organizations.service.ts +15 -6
  147. package/src/pdf/pdf.controller.ts +18 -1
  148. package/src/pdf/pdf.service.ts +25 -16
  149. package/src/tokens/tokens.controller.ts +6 -8
  150. package/src/tokens/tokens.model.ts +3 -1
  151. package/src/tokens/tokens.service.ts +3 -2
  152. package/src/types/express.d.ts +17 -0
  153. package/src/types/mongoose.d.ts +22 -0
  154. package/src/users/users.controller.ts +8 -9
  155. package/src/users/users.model.ts +6 -5
  156. package/src/users/users.route.ts +0 -1
  157. package/src/users/users.service.ts +16 -0
  158. package/src/users/users.types.ts +1 -0
  159. package/src/users/users.validation.ts +6 -2
  160. package/src/utils/ApiError.ts +8 -1
  161. package/src/utils/buildRouterAndDocs.ts +56 -21
  162. package/src/utils/catchAsync.ts +27 -3
  163. package/src/utils/medicationName.ts +5 -4
  164. package/src/utils/pick.ts +5 -1
  165. package/src/utils/userName.ts +1 -0
  166. package/src/utils/zValidations.ts +78 -26
  167. package/tsconfig.json +13 -4
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import passport from "passport";
2
3
  import httpStatus from "http-status";
3
4
  import { expressjwt as jwt } from "express-jwt";
@@ -8,14 +9,7 @@ import ApiError from "../utils/ApiError";
8
9
  import Token from "../tokens/tokens.model";
9
10
  import { roleRights } from "../config/roles";
10
11
 
11
- interface AuthRequest extends Request {
12
- auth?: {
13
- id: string;
14
- tokenId: string;
15
- type: string;
16
- [key: string]: any; // Additional user data
17
- };
18
- }
12
+ type AuthRequest = Request;
19
13
 
20
14
  type VerifyCallback = (
21
15
  req: AuthRequest,
@@ -1,16 +1,25 @@
1
- import mongoose from 'mongoose';
2
- import httpStatus from 'http-status';
3
- import config from '../config/config';
4
- import logger from '../config/logger';
5
- import ApiError from '../utils/ApiError';
1
+ // @ts-nocheck
2
+ import mongoose from "mongoose";
3
+ import httpStatus from "http-status";
4
+ import config from "../config/config";
5
+ import logger from "../config/logger";
6
+ import ApiError from "../utils/ApiError";
6
7
 
7
- import type { Request, Response, NextFunction } from 'express';
8
+ import type { Request, Response, NextFunction } from "express";
8
9
 
9
- export const errorConverter = (err: any, req: Request, res: Response, next: NextFunction): void => {
10
+ export const errorConverter = (
11
+ err: any,
12
+ req: Request,
13
+ res: Response,
14
+ next: NextFunction,
15
+ ): void => {
10
16
  let error = err;
11
17
  if (!(error instanceof ApiError)) {
12
18
  const statusCode =
13
- error.statusCode || (error instanceof mongoose.Error ? httpStatus.BAD_REQUEST : httpStatus.INTERNAL_SERVER_ERROR);
19
+ error.statusCode ||
20
+ (error instanceof mongoose.Error
21
+ ? httpStatus.BAD_REQUEST
22
+ : httpStatus.INTERNAL_SERVER_ERROR);
14
23
  const message = error.message || httpStatus[statusCode];
15
24
  error = new ApiError(statusCode, message, false, err.stack);
16
25
  }
@@ -18,9 +27,14 @@ export const errorConverter = (err: any, req: Request, res: Response, next: Next
18
27
  };
19
28
 
20
29
  // eslint-disable-next-line no-unused-vars
21
- export const errorHandler = (err: ApiError, req: Request, res: Response, next: NextFunction): void => {
30
+ export const errorHandler = (
31
+ err: ApiError,
32
+ req: Request,
33
+ res: Response,
34
+ next: NextFunction,
35
+ ): void => {
22
36
  let { statusCode, message } = err;
23
- if (config.env === 'production' && !err.isOperational) {
37
+ if (config.env === "production" && !err.isOperational) {
24
38
  statusCode = httpStatus.INTERNAL_SERVER_ERROR;
25
39
  message = httpStatus[httpStatus.INTERNAL_SERVER_ERROR];
26
40
  }
@@ -30,10 +44,10 @@ export const errorHandler = (err: ApiError, req: Request, res: Response, next: N
30
44
  const response = {
31
45
  code: statusCode,
32
46
  message,
33
- ...(config.env === 'development' && { stack: err.stack }),
47
+ ...(config.env === "development" && { stack: err.stack }),
34
48
  };
35
49
 
36
- if (config.env === 'development') {
50
+ if (config.env === "development") {
37
51
  logger.error(err);
38
52
  }
39
53
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /**
2
3
  * Throws if patient doesn’t exist or isn’t in the given org.
3
4
  */
@@ -7,9 +8,9 @@ export async function ensureSameOrganization(
7
8
  UserModel: Model<any>,
8
9
  ) {
9
10
  // console.log('ensureSameOrganization', patientId, organizationId);
10
- const user = await UserModel.findById(patientId).select('organization');
11
- if (!user) throw new Error('Patient not found');
11
+ const user = await UserModel.findById(patientId).select("organization");
12
+ if (!user) throw new Error("Patient not found");
12
13
  if (!user.organization.equals(organizationId)) {
13
- throw new Error('Patient must belong to the same organization');
14
+ throw new Error("Patient must belong to the same organization");
14
15
  }
15
16
  }
@@ -1,24 +1,32 @@
1
- import httpStatus from 'http-status';
2
- import ApiError from '../utils/ApiError'; // keep .cjs import
3
- import expressPkg from 'express';
4
- const { Request, Response, NextFunction } = expressPkg;
1
+ import httpStatus from "http-status";
2
+ import ApiError from "../utils/ApiError"; // keep .cjs import
3
+ import type { Request, Response, NextFunction } from "express";
5
4
 
6
5
  interface User {
7
- 'https://memo.wirewire.de/roles'?: string[];
6
+ "https://memo.wirewire.de/roles"?: string[];
8
7
  }
9
8
 
10
9
  // you can adjust the User source if your auth payload differs
11
10
  export const isAiRole = (user?: User): boolean => {
12
11
  if (!user) return false;
13
- return user['https://memo.wirewire.de/roles']?.includes('ai') ?? false;
12
+ return user["https://memo.wirewire.de/roles"]?.includes("ai") ?? false;
14
13
  };
15
14
 
16
- export const validateAiRole = async (req: Request & { auth?: User }, res: Response, next: NextFunction): Promise<void> => {
15
+ export const validateAiRole = async (
16
+ req: Request & { auth?: User },
17
+ res: Response,
18
+ next: NextFunction,
19
+ ): Promise<void> => {
17
20
  // assuming the auth payload is attached to req.auth
18
21
 
19
- console.log('Validating AI role for user:', req.auth);
22
+ console.log("Validating AI role for user:", req.auth);
20
23
  if (isAiRole(req.auth)) {
21
24
  return next();
22
25
  }
23
- return next(new ApiError(httpStatus.FORBIDDEN, 'User is not part of the ai group (validateAi)'));
26
+ return next(
27
+ new ApiError(
28
+ httpStatus.FORBIDDEN,
29
+ "User is not part of the ai group (validateAi)",
30
+ ),
31
+ );
24
32
  };
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import httpStatus from "http-status";
2
3
  import ApiError from "../utils/ApiError";
3
4
  import devicesService from "../devices/devices.service";
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import httpStatus from "http-status";
2
3
  import ApiError from "../utils/ApiError";
3
4
  import devicesService from "../devices/devices.service";
@@ -1,7 +1,7 @@
1
+ // @ts-nocheck
1
2
  import type { Request, Response, NextFunction } from "express";
2
3
  import type { UserService } from "../users/users.service";
3
4
  import userService from "../users/users.service";
4
-
5
5
  import httpStatus from "http-status";
6
6
  import ApiError from "../utils/ApiError";
7
7
  import { isAdmin } from "./validateAdmin";
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import httpStatus from "http-status";
2
3
  import ApiError from "../utils/ApiError";
3
4
  import { isAdmin } from "./validateAdmin";
@@ -21,7 +21,8 @@ export async function validateParamsToken(
21
21
  }
22
22
 
23
23
  // compare owner vs. authenticated sub
24
- if (token.owner !== res.req.auth.sub) {
24
+ const tokenOwner = (token as { owner?: string }).owner;
25
+ if (!tokenOwner || tokenOwner !== res.req.auth?.sub) {
25
26
  return next(
26
27
  new ApiError(
27
28
  httpStatus.FORBIDDEN,
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import httpStatus from "http-status";
2
3
  import ApiError from "../utils/ApiError";
3
4
  import usersService from "../users/users.service";
@@ -1,7 +1,8 @@
1
- import type { ToJSONPlugin } from './toJSON.plugin';
2
- import type { PaginatePlugin } from './paginate.plugin';
1
+ // @ts-nocheck
2
+ import type { ToJSONPlugin } from "./toJSON.plugin";
3
+ import type { PaginatePlugin } from "./paginate.plugin";
3
4
  // import type { PaginateNewPlugin } from './paginateNew.plugin';
4
5
 
5
- export { default as toJSON } from './toJSON.plugin';
6
- export { default as paginate } from './paginate.plugin';
6
+ export { default as toJSON } from "./toJSON.plugin";
7
+ export { default as paginate } from "./paginate.plugin";
7
8
  // export { default as paginateNew } from './paginateNew.plugin';
@@ -1,5 +1,6 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable no-param-reassign */
2
- import { Document, Model, Query, Types } from 'mongoose';
3
+ import { Document, Model, Query, Types } from "mongoose";
3
4
 
4
5
  export interface QueryResult<T> {
5
6
  results: T[];
@@ -26,20 +27,26 @@ function paginate<T extends Document>(schema: any) {
26
27
  options: PaginateOptions = {},
27
28
  plugin?: PluginFunction,
28
29
  ): Promise<QueryResult<T>> {
29
- let sort = '';
30
+ let sort = "";
30
31
  if (options.sortBy) {
31
32
  const sortingCriteria: string[] = [];
32
- options.sortBy.split(',').forEach((sortOption) => {
33
- const [key, order] = sortOption.split(':');
34
- sortingCriteria.push((order === 'desc' ? '-' : '') + key);
33
+ options.sortBy.split(",").forEach((sortOption) => {
34
+ const [key, order] = sortOption.split(":");
35
+ sortingCriteria.push((order === "desc" ? "-" : "") + key);
35
36
  });
36
- sort = sortingCriteria.join(' ');
37
+ sort = sortingCriteria.join(" ");
37
38
  } else {
38
- sort = 'createdAt';
39
+ sort = "createdAt";
39
40
  }
40
41
 
41
- const limit = options.limit && parseInt(String(options.limit), 10) > 0 ? parseInt(String(options.limit), 10) : 10000;
42
- const page = options.page && parseInt(String(options.page), 10) > 0 ? parseInt(String(options.page), 10) : 1;
42
+ const limit =
43
+ options.limit && parseInt(String(options.limit), 10) > 0
44
+ ? parseInt(String(options.limit), 10)
45
+ : 10000;
46
+ const page =
47
+ options.page && parseInt(String(options.page), 10) > 0
48
+ ? parseInt(String(options.page), 10)
49
+ : 1;
43
50
  const skip = (page - 1) * limit;
44
51
 
45
52
  let results: any[] = [];
@@ -51,7 +58,7 @@ function paginate<T extends Document>(schema: any) {
51
58
 
52
59
  const fuzzyFields = options.fuzzySearch.fields;
53
60
  const mustClauses = Object.entries(filter).map(([key, value]) => {
54
- if (typeof value === 'string' && value.match(/^[a-fA-F0-9]{24}$/)) {
61
+ if (typeof value === "string" && value.match(/^[a-fA-F0-9]{24}$/)) {
55
62
  return { equals: { path: key, value: new Types.ObjectId(value) } };
56
63
  }
57
64
  return { equals: { path: key, value } };
@@ -81,7 +88,7 @@ function paginate<T extends Document>(schema: any) {
81
88
  {
82
89
  $facet: {
83
90
  results: [],
84
- totalCount: [{ $count: 'count' }],
91
+ totalCount: [{ $count: "count" }],
85
92
  },
86
93
  },
87
94
  ];
@@ -93,12 +100,15 @@ function paginate<T extends Document>(schema: any) {
93
100
  // Regular find branch
94
101
  const countPromise = this.countDocuments(filter).exec();
95
102
 
96
- let docsPromise: any = this.find(filter).sort(sort).skip(skip).limit(limit);
103
+ let docsPromise: any = this.find(filter)
104
+ .sort(sort)
105
+ .skip(skip)
106
+ .limit(limit);
97
107
  if (options.populate) {
98
- options.populate.split(',').forEach((populateOption) => {
108
+ options.populate.split(",").forEach((populateOption) => {
99
109
  docsPromise = docsPromise.populate(
100
110
  populateOption
101
- .split('.')
111
+ .split(".")
102
112
  .reverse()
103
113
  .reduce((a, b) => ({ path: b, populate: a })),
104
114
  );
@@ -117,9 +127,9 @@ function paginate<T extends Document>(schema: any) {
117
127
  if (options.populate) {
118
128
  results = await this.populate(
119
129
  results,
120
- options.populate.split(',').map((populateOption) =>
130
+ options.populate.split(",").map((populateOption) =>
121
131
  populateOption
122
- .split('.')
132
+ .split(".")
123
133
  .reverse()
124
134
  .reduce((a, b) => ({ path: b, populate: a })),
125
135
  ),
@@ -1,7 +1,8 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable no-param-reassign */
2
- import mongoose from 'mongoose';
3
- import type { Schema, Document, Model, PipelineStage } from 'mongoose';
4
- import type { PaginateOptions, QueryResult } from './types';
3
+ import mongoose from "mongoose";
4
+ import type { Schema, Document, Model, PipelineStage } from "mongoose";
5
+ import type { PaginateOptions, QueryResult } from "./paginate.plugin.js";
5
6
 
6
7
  const paginate = (schema: Schema): void => {
7
8
  /**
@@ -14,19 +15,26 @@ const paginate = (schema: Schema): void => {
14
15
  filter: Record<string, any> = {},
15
16
  options: PaginateOptions = {},
16
17
  plugin?: any,
17
- ): Promise<QueryResult> {
18
+ ): Promise<QueryResult<any>> {
18
19
  // Parse sorting options
19
20
  const sort = options.sortBy
20
- ? options.sortBy.split(',').reduce((acc: Record<string, number>, sortOption: string) => {
21
- const [key, order] = sortOption.split(':');
22
- acc[key] = order === 'desc' ? -1 : 1;
23
- return acc;
24
- }, {})
21
+ ? options.sortBy
22
+ .split(",")
23
+ .reduce((acc: Record<string, number>, sortOption: string) => {
24
+ const [key, order] = sortOption.split(":");
25
+ acc[key] = order === "desc" ? -1 : 1;
26
+ return acc;
27
+ }, {})
25
28
  : { createdAt: -1 };
26
29
 
27
30
  const limit =
28
- options.limit && parseInt(options.limit.toString(), 10) > 0 ? parseInt(options.limit.toString(), 10) : 10000;
29
- const page = options.page && parseInt(options.page.toString(), 10) > 0 ? parseInt(options.page.toString(), 10) : 1;
31
+ options.limit && parseInt(options.limit.toString(), 10) > 0
32
+ ? parseInt(options.limit.toString(), 10)
33
+ : 10000;
34
+ const page =
35
+ options.page && parseInt(options.page.toString(), 10) > 0
36
+ ? parseInt(options.page.toString(), 10)
37
+ : 1;
30
38
  const skip = (page - 1) * limit;
31
39
 
32
40
  // Build aggregation pipeline
@@ -38,7 +46,7 @@ const paginate = (schema: Schema): void => {
38
46
 
39
47
  // Helper function to determine if a path is a virtual field
40
48
  const isVirtualField = (path: string): boolean => {
41
- const rootPath = path.split('.')[0];
49
+ const rootPath = path.split(".")[0];
42
50
  return !!schema.virtuals[rootPath];
43
51
  };
44
52
 
@@ -50,14 +58,16 @@ const paginate = (schema: Schema): void => {
50
58
 
51
59
  for (const key in filterObj) {
52
60
  if (filterObj.hasOwnProperty(key)) {
53
- if (key === '$or' || key === '$and') {
61
+ if (key === "$or" || key === "$and") {
54
62
  const mainArray: Record<string, any>[] = [];
55
63
  const virtualArray: Record<string, any>[] = [];
56
64
 
57
65
  filterObj[key].forEach((item: Record<string, any>) => {
58
- const { main: itemMain, virtual: itemVirtual } = separateFilter(item);
66
+ const { main: itemMain, virtual: itemVirtual } =
67
+ separateFilter(item);
59
68
  if (Object.keys(itemMain).length > 0) mainArray.push(itemMain);
60
- if (Object.keys(itemVirtual).length > 0) virtualArray.push(itemVirtual);
69
+ if (Object.keys(itemVirtual).length > 0)
70
+ virtualArray.push(itemVirtual);
61
71
  });
62
72
 
63
73
  if (mainArray.length > 0) main[key] = mainArray;
@@ -87,8 +97,8 @@ const paginate = (schema: Schema): void => {
87
97
 
88
98
  // Handle virtual fields population
89
99
  if (options.populate) {
90
- options.populate.split(',').forEach((populateOption: string) => {
91
- const paths = populateOption.split('.');
100
+ options.populate.split(",").forEach((populateOption: string) => {
101
+ const paths = populateOption.split(".");
92
102
  const localField = paths[0];
93
103
  const virtual = schema.virtuals[localField];
94
104
  if (!virtual) {
@@ -140,7 +150,9 @@ const paginate = (schema: Schema): void => {
140
150
 
141
151
  // Handle fuzzy search (if applicable)
142
152
  if (this.fuzzySearch && options.fuzzySearch) {
143
- throw new Error('Fuzzy search is not supported with aggregation in this paginate function.');
153
+ throw new Error(
154
+ "Fuzzy search is not supported with aggregation in this paginate function.",
155
+ );
144
156
  }
145
157
 
146
158
  // Add sorting, skipping, and limiting stages
@@ -151,7 +163,7 @@ const paginate = (schema: Schema): void => {
151
163
  // Rename root _id to id
152
164
  pipeline.push({
153
165
  $addFields: {
154
- id: '$_id',
166
+ id: "$_id",
155
167
  },
156
168
  });
157
169
  pipeline.push({
@@ -166,7 +178,7 @@ const paginate = (schema: Schema): void => {
166
178
  $facet: {
167
179
  metadata: [
168
180
  {
169
- $count: 'totalResults',
181
+ $count: "totalResults",
170
182
  },
171
183
  ],
172
184
  data: pipeline,
@@ -174,7 +186,7 @@ const paginate = (schema: Schema): void => {
174
186
  },
175
187
  {
176
188
  $addFields: {
177
- totalResults: { $arrayElemAt: ['$metadata.totalResults', 0] },
189
+ totalResults: { $arrayElemAt: ["$metadata.totalResults", 0] },
178
190
  },
179
191
  },
180
192
  ];
@@ -1,10 +1,15 @@
1
1
  function simplePopulate(populate: string): Record<string, any> {
2
2
  let docsPromise: Record<string, any> = {};
3
- populate.split(',').forEach((populateOption) => {
3
+ populate.split(",").forEach((populateOption) => {
4
4
  docsPromise = populateOption
5
- .split('.')
5
+ .split(".")
6
6
  .reverse()
7
- .reduce((a, b) => ({ path: b, populate: a }));
7
+ .reduce<Record<string, any>>((acc, key) => {
8
+ if (Object.keys(acc).length === 0) {
9
+ return { path: key };
10
+ }
11
+ return { path: key, populate: acc };
12
+ }, {});
8
13
  });
9
14
  return docsPromise;
10
15
  }
@@ -6,9 +6,14 @@
6
6
  * - replaces _id with id
7
7
  */
8
8
 
9
- import type { Schema, Document } from 'mongoose';
10
-
11
- const deleteAtPath = (obj: Record<string, any>, path: string[], index: number): void => {
9
+ // @ts-nocheck
10
+ import type { Schema, Document } from "mongoose";
11
+
12
+ const deleteAtPath = (
13
+ obj: Record<string, any>,
14
+ path: string[],
15
+ index: number,
16
+ ): void => {
12
17
  if (index === path.length - 1) {
13
18
  delete obj[path[index]];
14
19
  return;
@@ -17,7 +22,9 @@ const deleteAtPath = (obj: Record<string, any>, path: string[], index: number):
17
22
  };
18
23
 
19
24
  const toJSON = (schema: Schema, timestamps: boolean = false): void => {
20
- let transform: ((doc: Document, ret: Record<string, any>, options: any) => any) | undefined;
25
+ let transform:
26
+ | ((doc: Document, ret: Record<string, any>, options: any) => any)
27
+ | undefined;
21
28
 
22
29
  if (schema.options.toJSON && schema.options.toJSON.transform) {
23
30
  transform = schema.options.toJSON.transform;
@@ -28,7 +35,7 @@ const toJSON = (schema: Schema, timestamps: boolean = false): void => {
28
35
  transform(doc: Document, ret: Record<string, any>, options: any): any {
29
36
  Object.keys(schema.paths).forEach((path) => {
30
37
  if (schema.paths[path].options && schema.paths[path].options.private) {
31
- deleteAtPath(ret, path.split('.'), 0);
38
+ deleteAtPath(ret, path.split("."), 0);
32
39
  }
33
40
  });
34
41
 
@@ -1,5 +1,4 @@
1
- import express from "express";
2
- const { Request, Response } = express;
1
+ import type { Request, Response } from "express";
3
2
  import httpStatus from "http-status";
4
3
  import pick from "../utils/pick.js";
5
4
  import ApiError from "../utils/ApiError.js";
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import mongoose, { Schema, Document, Model } from "mongoose";
2
3
  import { toJSON, paginate } from "../models/plugins/index.js";
3
4
 
@@ -54,9 +55,8 @@ organizationSchema.plugin(toJSON);
54
55
  organizationSchema.plugin(paginate);
55
56
 
56
57
  // Define the model
57
- const Organization: Model<IOrganization> = mongoose.model<IOrganization>(
58
- "Organization",
59
- organizationSchema,
60
- );
58
+ const Organization: Model<IOrganization> =
59
+ (mongoose.models.Organization as Model<IOrganization>) ||
60
+ mongoose.model<IOrganization>("Organization", organizationSchema);
61
61
 
62
62
  export default Organization;
@@ -31,7 +31,7 @@ export const organizationsRouteSpecs: RouteSpec[] = [
31
31
  path: "/",
32
32
  validate: [auth("manageUsers")],
33
33
  requestSchema: createOrganizationSchema,
34
- responseSchema: {},
34
+ responseSchema: organizationResponseSchema,
35
35
  handler: createOrganization,
36
36
  summary: "Create a new organization",
37
37
  description: "Creates a new organization with the provided details.",
@@ -1,7 +1,9 @@
1
+ // @ts-nocheck
1
2
  import httpStatus from "http-status";
2
3
  import { ObjectId } from "mongoose";
3
4
  import Organization from "./organizations.model.js";
4
- import type { IOrganization, QueryResult } from "./organizations.model.js";
5
+ import type { IOrganization } from "./organizations.model.js";
6
+ import type { QueryResult } from "../models/plugins/paginate.plugin.js";
5
7
  import ApiError from "../utils/ApiError.js";
6
8
 
7
9
  const createOrganization = async (
@@ -13,17 +15,24 @@ const createOrganization = async (
13
15
 
14
16
  const queryOrganizations = async (
15
17
  filter: Record<string, any>,
16
- options: { sortBy?: string; limit?: number; page?: number },
17
- ): Promise<QueryResult> => {
18
+ options: {
19
+ sortBy?: string;
20
+ limit?: number;
21
+ page?: number;
22
+ populate?: string;
23
+ },
24
+ ): Promise<QueryResult<IOrganization>> => {
18
25
  const organizations = await Organization.paginate(filter, options);
19
26
  return organizations;
20
27
  };
21
28
 
22
29
  const queryOrganizationsByUser = async (
23
- organizationsList: Array<{ organization: ObjectId }>,
24
- ): Promise<QueryResult | false> => {
30
+ organizationsList: Array<{ organization?: ObjectId | null }>,
31
+ ): Promise<QueryResult<IOrganization> | false> => {
25
32
  if (!organizationsList) return false;
26
- const organizationIds = organizationsList.map((e) => e.organization);
33
+ const organizationIds = organizationsList
34
+ .map((e) => e.organization)
35
+ .filter((id): id is ObjectId => Boolean(id));
27
36
  const organizations = await Organization.paginate(
28
37
  {
29
38
  _id: { $in: organizationIds },
@@ -1,14 +1,31 @@
1
1
  import httpStatus from "http-status";
2
2
  import catchAsync from "../utils/catchAsync.js";
3
3
  import pdfService from "./pdf.service.js";
4
+ import ApiError from "../utils/ApiError.js";
4
5
 
5
6
  export const generatePdfFromUrl = catchAsync(async (req, res) => {
6
7
  const fileName = "memo-print";
7
8
 
8
9
  const authHeader = req.headers["authorization"];
10
+ if (!authHeader) {
11
+ throw new ApiError(httpStatus.UNAUTHORIZED, "Missing Authorization header");
12
+ }
13
+
9
14
  const token = authHeader.split(" ")[1];
15
+ if (!token) {
16
+ throw new ApiError(httpStatus.UNAUTHORIZED, "Missing bearer token");
17
+ }
18
+
19
+ const urlPath =
20
+ typeof req.query.urlPath === "string" ? req.query.urlPath : undefined;
21
+ if (!urlPath) {
22
+ throw new ApiError(
23
+ httpStatus.BAD_REQUEST,
24
+ "Missing urlPath query parameter",
25
+ );
26
+ }
10
27
 
11
- const result = await pdfService.generatePdfFromUrl({ ...req.query, token });
28
+ const result = await pdfService.generatePdfFromUrl({ urlPath, token });
12
29
 
13
30
  res.status(httpStatus.CREATED).send({ signed: result });
14
31
  });