@internetderdinge/api 1.224.2 → 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.
- package/dist/src/accounts/accounts.controller.js +89 -0
- package/dist/src/accounts/accounts.route.js +101 -0
- package/dist/src/accounts/accounts.schemas.js +12 -0
- package/dist/src/accounts/accounts.service.js +65 -0
- package/dist/src/accounts/accounts.validation.js +99 -0
- package/dist/src/accounts/auth0.service.js +188 -0
- package/dist/src/config/config.js +48 -0
- package/dist/src/config/logger.js +27 -0
- package/dist/src/config/morgan.js +16 -0
- package/dist/src/config/passport.cjs +28 -0
- package/dist/src/config/roles.js +11 -0
- package/dist/src/config/tokens.cjs +10 -0
- package/dist/src/devices/devices.controller.js +172 -0
- package/dist/src/devices/devices.model.js +94 -0
- package/dist/src/devices/devices.route.js +153 -0
- package/dist/src/devices/devices.schemas.js +84 -0
- package/dist/src/devices/devices.service.js +198 -0
- package/dist/src/devices/devices.types.js +1 -0
- package/dist/src/devices/devices.validation.js +257 -0
- package/dist/src/devicesNotifications/devicesNotifications.controller.js +69 -0
- package/dist/src/devicesNotifications/devicesNotifications.model.js +39 -0
- package/dist/src/devicesNotifications/devicesNotifications.route.js +124 -0
- package/dist/src/devicesNotifications/devicesNotifications.schemas.js +10 -0
- package/dist/src/devicesNotifications/devicesNotifications.service.js +181 -0
- package/dist/src/devicesNotifications/devicesNotifications.validation.js +46 -0
- package/dist/src/email/email.service.js +580 -0
- package/dist/src/files/upload.service.js +124 -0
- package/dist/src/i18n/i18n.js +38 -0
- package/dist/src/i18n/saveMissingLocalJsonBackend.js +53 -0
- package/dist/src/i18n/types.js +1 -0
- package/dist/src/index.js +48 -0
- package/dist/src/iotdevice/iotdevice.controller.js +96 -0
- package/dist/src/iotdevice/iotdevice.model.js +17 -0
- package/dist/src/iotdevice/iotdevice.route.js +143 -0
- package/dist/src/iotdevice/iotdevice.schemas.js +60 -0
- package/dist/src/iotdevice/iotdevice.service.js +579 -0
- package/dist/src/iotdevice/iotdevice.types.js +1 -0
- package/dist/src/iotdevice/iotdevice.validation.js +54 -0
- package/dist/src/middlewares/auth.js +75 -0
- package/dist/src/middlewares/checkJwt.cjs +17 -0
- package/dist/src/middlewares/error.js +36 -0
- package/dist/src/middlewares/mongooseValidations/ensureSameOrganization.js +13 -0
- package/dist/src/middlewares/rateLimiter.js +7 -0
- package/dist/src/middlewares/validate.js +18 -0
- package/dist/src/middlewares/validateAction.js +35 -0
- package/dist/src/middlewares/validateAdmin.js +18 -0
- package/dist/src/middlewares/validateAi.js +16 -0
- package/dist/src/middlewares/validateCurrentAuthUser.js +17 -0
- package/dist/src/middlewares/validateCurrentUser.js +20 -0
- package/dist/src/middlewares/validateDevice.js +98 -0
- package/dist/src/middlewares/validateDeviceUserOrganization.js +26 -0
- package/dist/src/middlewares/validateOrganization.js +63 -0
- package/dist/src/middlewares/validateQuerySearchUserAndOrganization.js +44 -0
- package/dist/src/middlewares/validateTokens.js +23 -0
- package/dist/src/middlewares/validateUser.js +38 -0
- package/dist/src/middlewares/validateZod.js +33 -0
- package/dist/src/models/plugins/index.js +4 -0
- package/dist/src/models/plugins/paginate.plugin.js +117 -0
- package/dist/src/models/plugins/paginateNew.plugin.js +185 -0
- package/dist/src/models/plugins/simplePopulate.js +16 -0
- package/dist/src/models/plugins/toJSON.plugin.js +35 -0
- package/dist/src/organizations/organizations.controller.js +64 -0
- package/dist/src/organizations/organizations.model.js +41 -0
- package/dist/src/organizations/organizations.route.js +98 -0
- package/dist/src/organizations/organizations.schemas.js +7 -0
- package/dist/src/organizations/organizations.service.js +59 -0
- package/dist/src/organizations/organizations.validation.js +62 -0
- package/dist/src/pdf/pdf.controller.js +24 -0
- package/dist/src/pdf/pdf.route.js +22 -0
- package/dist/src/pdf/pdf.schemas.js +6 -0
- package/dist/src/pdf/pdf.service.js +65 -0
- package/dist/src/pdf/pdf.validation.js +27 -0
- package/dist/src/tokens/tokens.controller.js +60 -0
- package/dist/src/tokens/tokens.model.js +18 -0
- package/dist/src/tokens/tokens.route.js +52 -0
- package/dist/src/tokens/tokens.schemas.js +14 -0
- package/dist/src/tokens/tokens.service.js +30 -0
- package/dist/src/tokens/tokens.validation.js +9 -0
- package/dist/src/types/routeSpec.js +1 -0
- package/dist/src/users/users.controller.js +147 -0
- package/dist/src/users/users.model.js +50 -0
- package/dist/src/users/users.route.js +137 -0
- package/dist/src/users/users.schemas.js +69 -0
- package/dist/src/users/users.service.js +295 -0
- package/dist/src/users/users.types.js +1 -0
- package/dist/src/users/users.validation.js +144 -0
- package/dist/src/utils/ApiError.js +16 -0
- package/dist/src/utils/buildRouterAndDocs.js +72 -0
- package/dist/src/utils/catchAsync.js +4 -0
- package/dist/src/utils/comparePapers.service.js +32 -0
- package/dist/src/utils/deviceUtils.js +63 -0
- package/dist/src/utils/filterOptions.js +24 -0
- package/dist/src/utils/medicationName.js +10 -0
- package/dist/src/utils/pick.js +16 -0
- package/dist/src/utils/registerOpenApi.js +28 -0
- package/dist/src/utils/urlUtils.js +15 -0
- package/dist/src/utils/userName.js +22 -0
- package/dist/src/utils/zValidations.js +124 -0
- package/dist/src/validations/auth.validation.cjs +53 -0
- package/dist/src/validations/custom.validation.js +19 -0
- package/dist/src/validations/index.cjs +3 -0
- package/package.json +15 -6
- package/scripts/release-and-sync-paperless.mjs +135 -0
- package/scripts/release-version.mjs +145 -0
- package/src/accounts/accounts.controller.ts +1 -0
- package/src/accounts/accounts.service.ts +1 -0
- package/src/accounts/accounts.validation.ts +6 -3
- package/src/accounts/auth0.service.ts +55 -28
- package/src/config/config.ts +6 -0
- package/src/config/logger.ts +15 -9
- package/src/devices/devices.controller.ts +7 -1
- package/src/devices/devices.model.ts +4 -1
- package/src/devices/devices.schemas.ts +10 -8
- package/src/devices/devices.service.ts +2 -1
- package/src/devices/devices.types.ts +1 -0
- package/src/devices/devices.validation.ts +85 -23
- package/src/devicesNotifications/devicesNotifications.controller.ts +57 -28
- package/src/devicesNotifications/devicesNotifications.model.ts +20 -12
- package/src/devicesNotifications/devicesNotifications.service.ts +35 -17
- package/src/files/upload.service.ts +52 -28
- package/src/i18n/i18n.ts +2 -2
- package/src/i18n/types.ts +1 -0
- package/src/index.ts +47 -0
- package/src/iotdevice/iotdevice.controller.ts +1 -0
- package/src/iotdevice/iotdevice.model.ts +6 -3
- package/src/iotdevice/iotdevice.route.ts +85 -76
- package/src/iotdevice/iotdevice.service.ts +5 -4
- package/src/iotdevice/iotdevice.types.ts +6 -0
- package/src/middlewares/auth.ts +2 -8
- package/src/middlewares/error.ts +26 -12
- package/src/middlewares/mongooseValidations/ensureSameOrganization.ts +4 -3
- package/src/middlewares/validateAi.ts +17 -9
- package/src/middlewares/validateDevice.ts +1 -0
- package/src/middlewares/validateDeviceUserOrganization.ts +1 -0
- package/src/middlewares/validateOrganization.ts +1 -1
- package/src/middlewares/validateQuerySearchUserAndOrganization.ts +1 -0
- package/src/middlewares/validateTokens.ts +2 -1
- package/src/middlewares/validateUser.ts +1 -0
- package/src/models/plugins/index.ts +5 -4
- package/src/models/plugins/paginate.plugin.ts +26 -16
- package/src/models/plugins/paginateNew.plugin.ts +33 -21
- package/src/models/plugins/simplePopulate.ts +8 -3
- package/src/models/plugins/toJSON.plugin.ts +12 -5
- package/src/organizations/organizations.controller.ts +1 -2
- package/src/organizations/organizations.model.ts +4 -4
- package/src/organizations/organizations.route.ts +1 -1
- package/src/organizations/organizations.service.ts +15 -6
- package/src/pdf/pdf.controller.ts +18 -1
- package/src/pdf/pdf.service.ts +25 -16
- package/src/tokens/tokens.controller.ts +6 -8
- package/src/tokens/tokens.model.ts +3 -1
- package/src/tokens/tokens.service.ts +3 -2
- package/src/types/express.d.ts +17 -0
- package/src/types/mongoose.d.ts +22 -0
- package/src/users/users.controller.ts +8 -9
- package/src/users/users.model.ts +6 -5
- package/src/users/users.route.ts +0 -1
- package/src/users/users.service.ts +16 -0
- package/src/users/users.types.ts +1 -0
- package/src/users/users.validation.ts +6 -2
- package/src/utils/ApiError.ts +8 -1
- package/src/utils/buildRouterAndDocs.ts +56 -21
- package/src/utils/catchAsync.ts +27 -3
- package/src/utils/deviceUtils.ts +109 -0
- package/src/utils/medicationName.ts +5 -4
- package/src/utils/pick.ts +5 -1
- package/src/utils/userName.ts +1 -0
- package/src/utils/zValidations.ts +78 -26
- package/tsconfig.json +13 -4
package/src/utils/ApiError.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
export class ApiError extends Error {
|
|
2
3
|
statusCode: number;
|
|
3
4
|
isOperational: boolean;
|
|
4
5
|
|
|
5
|
-
constructor(
|
|
6
|
+
constructor(
|
|
7
|
+
statusCode: number,
|
|
8
|
+
message: string,
|
|
9
|
+
isOperational = true,
|
|
10
|
+
stack = "",
|
|
11
|
+
raw: any = null,
|
|
12
|
+
) {
|
|
6
13
|
super(message);
|
|
7
14
|
this.statusCode = statusCode;
|
|
8
15
|
this.isOperational = isOperational;
|
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RequestHandler, Router } from "express";
|
|
2
|
+
import { registry } from "../utils/registerOpenApi";
|
|
2
3
|
|
|
3
|
-
import { validateZod } from
|
|
4
|
-
import { bearerAuth, xApiKey } from
|
|
4
|
+
import { validateZod } from "../middlewares/validateZod";
|
|
5
|
+
import { bearerAuth, xApiKey } from "../utils/registerOpenApi";
|
|
5
6
|
|
|
6
|
-
import { extendZodWithOpenApi } from
|
|
7
|
-
import { z } from
|
|
7
|
+
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import type { ZodTypeAny } from "zod";
|
|
8
10
|
|
|
9
11
|
extendZodWithOpenApi(z);
|
|
10
12
|
|
|
11
|
-
const roleValidatorNames = [
|
|
13
|
+
const roleValidatorNames = ["validateAiRole", "validateAdmin"];
|
|
12
14
|
function hasRoleValidation(validators: Function[] = []): boolean {
|
|
13
15
|
return validators.some((fn) => roleValidatorNames.includes(fn.name));
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export type RouteSpec = {
|
|
17
|
-
method:
|
|
19
|
+
method: "get" | "post" | "put" | "patch" | "delete" | "options" | "head";
|
|
18
20
|
path: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
validate?: RequestHandler<any, any, any, any, any>[];
|
|
22
|
+
validateWithRequestSchema?: RequestHandler<any, any, any, any, any>[];
|
|
23
|
+
requestSchema?: Partial<Record<string, ZodTypeAny>>;
|
|
24
|
+
responseSchema?: ZodTypeAny;
|
|
25
|
+
handler: RequestHandler<any, any, any, any, any>;
|
|
22
26
|
summary: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
privateDocs?: boolean;
|
|
29
|
+
memoOnly?: boolean;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
|
-
export default function buildAiRouterAndDocs(
|
|
32
|
+
export default function buildAiRouterAndDocs(
|
|
33
|
+
router: Router,
|
|
34
|
+
routeSpecs: any,
|
|
35
|
+
basePath = "/",
|
|
36
|
+
tags: string[] = [],
|
|
37
|
+
) {
|
|
26
38
|
routeSpecs.forEach((spec) => {
|
|
27
39
|
// mount Express
|
|
28
40
|
|
|
@@ -31,11 +43,18 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
if (spec.requestSchema) {
|
|
34
|
-
spec.validateWithRequestSchema = [
|
|
46
|
+
spec.validateWithRequestSchema = [
|
|
47
|
+
validateZod(spec.requestSchema),
|
|
48
|
+
...spec.validate,
|
|
49
|
+
];
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
if (spec.validateWithRequestSchema) {
|
|
38
|
-
router[spec.method](
|
|
53
|
+
router[spec.method](
|
|
54
|
+
spec.path,
|
|
55
|
+
...spec.validateWithRequestSchema,
|
|
56
|
+
spec.handler,
|
|
57
|
+
);
|
|
39
58
|
}
|
|
40
59
|
|
|
41
60
|
var { body, ...rest } = spec.requestSchema || {};
|
|
@@ -43,7 +62,7 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
43
62
|
if (body) {
|
|
44
63
|
rest.body = {
|
|
45
64
|
content: {
|
|
46
|
-
|
|
65
|
+
"application/json": {
|
|
47
66
|
schema: body,
|
|
48
67
|
},
|
|
49
68
|
},
|
|
@@ -52,28 +71,44 @@ export default function buildAiRouterAndDocs(router: Router, routeSpecs: any, ba
|
|
|
52
71
|
|
|
53
72
|
// console.log('spec.requestSchema', body);
|
|
54
73
|
|
|
55
|
-
if (
|
|
74
|
+
if (
|
|
75
|
+
spec.responseSchema &&
|
|
76
|
+
!hasRoleValidation(spec.validate) &&
|
|
77
|
+
spec.privateDocs !== true &&
|
|
78
|
+
spec.memoOnly !== true
|
|
79
|
+
) {
|
|
56
80
|
// collect all middleware fn names (falls back to '<anonymous>' if unnamed)
|
|
57
|
-
const middlewareNames = (spec.validate || []).map(
|
|
81
|
+
const middlewareNames = (spec.validate || []).map(
|
|
82
|
+
(fn) => `\`${fn.name}\`` || "<anonymous>",
|
|
83
|
+
);
|
|
84
|
+
const openApiPath = (basePath + spec.path).replace(
|
|
85
|
+
/:([A-Za-z0-9_]+)/g,
|
|
86
|
+
"{$1}",
|
|
87
|
+
);
|
|
58
88
|
|
|
59
89
|
registry.registerPath({
|
|
60
90
|
method: spec.method,
|
|
61
|
-
path:
|
|
91
|
+
path: openApiPath,
|
|
62
92
|
summary: spec.summary,
|
|
63
93
|
request: rest,
|
|
64
94
|
|
|
65
95
|
// append middleware names to the description
|
|
66
|
-
description: [
|
|
96
|
+
description: [
|
|
97
|
+
spec.description,
|
|
98
|
+
`\n\nMiddlewares: ${middlewareNames.join(", ")}`,
|
|
99
|
+
]
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
.join("\n"),
|
|
67
102
|
|
|
68
103
|
// (optionally) expose them as a custom extension instead:
|
|
69
|
-
|
|
104
|
+
"x-middlewares": middlewareNames,
|
|
70
105
|
|
|
71
106
|
security: [{ [bearerAuth.name]: [] }, { [xApiKey.name]: [] }],
|
|
72
107
|
responses: {
|
|
73
108
|
200: {
|
|
74
|
-
description:
|
|
109
|
+
description: "Object with user data.",
|
|
75
110
|
content: {
|
|
76
|
-
|
|
111
|
+
"application/json": { schema: spec.responseSchema },
|
|
77
112
|
},
|
|
78
113
|
},
|
|
79
114
|
},
|
package/src/utils/catchAsync.ts
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
|
-
import type { Request, Response, NextFunction } from
|
|
1
|
+
import type { Request, Response, NextFunction } from "express";
|
|
2
|
+
|
|
3
|
+
type AsyncRequestHandler<
|
|
4
|
+
P = any,
|
|
5
|
+
ResBody = any,
|
|
6
|
+
ReqBody = any,
|
|
7
|
+
ReqQuery = any,
|
|
8
|
+
Locals extends Record<string, any> = Record<string, any>,
|
|
9
|
+
> = (
|
|
10
|
+
req: Request<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
11
|
+
res: Response<ResBody, Locals>,
|
|
12
|
+
next: NextFunction,
|
|
13
|
+
) => Promise<any>;
|
|
2
14
|
|
|
3
15
|
const catchAsync =
|
|
4
|
-
|
|
5
|
-
|
|
16
|
+
<
|
|
17
|
+
P = any,
|
|
18
|
+
ResBody = any,
|
|
19
|
+
ReqBody = any,
|
|
20
|
+
ReqQuery = any,
|
|
21
|
+
Locals extends Record<string, any> = Record<string, any>,
|
|
22
|
+
>(
|
|
23
|
+
fn: AsyncRequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
24
|
+
) =>
|
|
25
|
+
(
|
|
26
|
+
req: Request<P, ResBody, ReqBody, ReqQuery, Locals>,
|
|
27
|
+
res: Response<ResBody, Locals>,
|
|
28
|
+
next: NextFunction,
|
|
29
|
+
): void => {
|
|
6
30
|
Promise.resolve(fn(req, res, next)).catch((err) => next(err));
|
|
7
31
|
};
|
|
8
32
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export type DeviceListEntry = {
|
|
5
|
+
id: string;
|
|
6
|
+
features: string[];
|
|
7
|
+
deviceNameDetection?: string;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface InitDeviceListOptions {
|
|
12
|
+
list?: DeviceListEntry[];
|
|
13
|
+
listPath?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let deviceList: DeviceListEntry[] | null = null;
|
|
17
|
+
|
|
18
|
+
const parseDeviceList = (value: unknown): DeviceListEntry[] => {
|
|
19
|
+
if (!Array.isArray(value)) {
|
|
20
|
+
throw new Error("Device list must be an array.");
|
|
21
|
+
}
|
|
22
|
+
return value as DeviceListEntry[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const loadDeviceListFromFile = (listPath: string): DeviceListEntry[] => {
|
|
26
|
+
const absolutePath = path.resolve(listPath);
|
|
27
|
+
const raw = readFileSync(absolutePath, "utf8");
|
|
28
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
29
|
+
return parseDeviceList(parsed);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const initDeviceList = (
|
|
33
|
+
options: InitDeviceListOptions = {},
|
|
34
|
+
): DeviceListEntry[] => {
|
|
35
|
+
if (options.list) {
|
|
36
|
+
deviceList = options.list;
|
|
37
|
+
return deviceList;
|
|
38
|
+
}
|
|
39
|
+
if (options.listPath) {
|
|
40
|
+
deviceList = loadDeviceListFromFile(options.listPath);
|
|
41
|
+
return deviceList;
|
|
42
|
+
}
|
|
43
|
+
throw new Error("initDeviceList requires list or listPath.");
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const ensureDeviceList = (): DeviceListEntry[] => {
|
|
47
|
+
if (!deviceList) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
"deviceList is not initialized. Call initDeviceList(...) before using device utilities.",
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return deviceList;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { deviceList as default };
|
|
56
|
+
|
|
57
|
+
export function deviceByKind(device): any {
|
|
58
|
+
const list = ensureDeviceList();
|
|
59
|
+
const result = list.find((e) => e.id === device);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function deviceByDeviceName(deviceName): any {
|
|
64
|
+
if (!deviceName) return false;
|
|
65
|
+
const list = ensureDeviceList();
|
|
66
|
+
const result = list.find((e) => {
|
|
67
|
+
if (!e.deviceNameDetection) return false;
|
|
68
|
+
|
|
69
|
+
return deviceName.startsWith(e.deviceNameDetection);
|
|
70
|
+
});
|
|
71
|
+
if (!result) return false;
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns true if the device kind has the given feature
|
|
77
|
+
*/
|
|
78
|
+
export function deviceKindHasFeature(
|
|
79
|
+
feature:
|
|
80
|
+
| "analog"
|
|
81
|
+
| "wifi"
|
|
82
|
+
| "epaper"
|
|
83
|
+
| "nbiot"
|
|
84
|
+
| "nouser"
|
|
85
|
+
| "battery-offline"
|
|
86
|
+
| "code7"
|
|
87
|
+
| "sensor"
|
|
88
|
+
| "payment"
|
|
89
|
+
| "anabox-smart"
|
|
90
|
+
| "intakes1"
|
|
91
|
+
| "intakes3"
|
|
92
|
+
| "intakes4"
|
|
93
|
+
| "intakes5"
|
|
94
|
+
| "intakes7"
|
|
95
|
+
| "stationaer"
|
|
96
|
+
| "tray-colors"
|
|
97
|
+
| "nuechtern-bedarf"
|
|
98
|
+
| "week-colors"
|
|
99
|
+
| "day-colors"
|
|
100
|
+
| "alt-device"
|
|
101
|
+
| "battery-level",
|
|
102
|
+
kind?: DeviceListEntry["id"],
|
|
103
|
+
): boolean {
|
|
104
|
+
if (!kind) return false;
|
|
105
|
+
const list = ensureDeviceList();
|
|
106
|
+
const result = list.find((e) => e.id === kind);
|
|
107
|
+
if (!result) return false;
|
|
108
|
+
return result.features.includes(feature);
|
|
109
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import i18n from "../i18n/i18n";
|
|
3
|
+
import type { MedicationEntry } from "../types/MedicationEntry";
|
|
3
4
|
|
|
4
5
|
export const medicationName = (entry: MedicationEntry, lng: string): string => {
|
|
5
6
|
const name = entry.medicationData?.Kurzname
|
|
6
7
|
? entry.medicationData.Kurzname
|
|
7
8
|
: entry.localMedicationData?.meta?.name
|
|
8
|
-
? entry.localMedicationData.meta.name.replace(/ .*/,
|
|
9
|
-
: i18n.t(
|
|
9
|
+
? entry.localMedicationData.meta.name.replace(/ .*/, "")
|
|
10
|
+
: i18n.t("A medication", { lng });
|
|
10
11
|
|
|
11
12
|
return name;
|
|
12
13
|
};
|
package/src/utils/pick.ts
CHANGED
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* @param {string[]} keys - The keys to pick
|
|
5
5
|
* @returns {Partial<Record<string, any>>} - The new object with picked properties
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
// @ts-nocheck
|
|
8
|
+
const pick = <T extends Record<string, any>>(
|
|
9
|
+
object: T,
|
|
10
|
+
keys: string[],
|
|
11
|
+
): Partial<T> => {
|
|
8
12
|
return keys.reduce((obj, key) => {
|
|
9
13
|
if (object && Object.prototype.hasOwnProperty.call(object, key)) {
|
|
10
14
|
obj[key] = object[key];
|
package/src/utils/userName.ts
CHANGED
|
@@ -1,45 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { objectId } from "../validations/custom.validation";
|
|
4
|
+
import mongoose from "mongoose";
|
|
4
5
|
|
|
5
6
|
export const zPagination = {
|
|
6
7
|
query: z.object({
|
|
7
8
|
name: z.string().optional(),
|
|
8
|
-
role: z
|
|
9
|
-
|
|
9
|
+
role: z
|
|
10
|
+
.string()
|
|
11
|
+
.openapi({ example: "admin", description: "Role to filter by" })
|
|
12
|
+
.optional(),
|
|
13
|
+
sortBy: z
|
|
14
|
+
.string()
|
|
15
|
+
.openapi({ example: "createdAt", description: "Field to sort by" })
|
|
16
|
+
.optional(),
|
|
10
17
|
search: z
|
|
11
18
|
.string()
|
|
12
19
|
.openapi({
|
|
13
|
-
example:
|
|
14
|
-
description:
|
|
20
|
+
example: process.env.SCHEMA_EXAMPLE_SEARCH || "",
|
|
21
|
+
description: "Search term to filter results",
|
|
15
22
|
})
|
|
16
23
|
.optional(),
|
|
17
24
|
limit: z.coerce
|
|
18
25
|
.number()
|
|
19
26
|
.openapi({
|
|
20
27
|
example: 10,
|
|
21
|
-
description:
|
|
28
|
+
description: "Number of items per page",
|
|
22
29
|
})
|
|
23
30
|
.int()
|
|
24
31
|
.min(1)
|
|
25
32
|
.max(100000)
|
|
26
33
|
.optional(),
|
|
27
|
-
offset: z
|
|
34
|
+
offset: z.coerce
|
|
28
35
|
.number() // was z.int()
|
|
29
36
|
.openapi({
|
|
30
37
|
example: 0,
|
|
31
|
-
description:
|
|
38
|
+
description: "Offset for pagination, used to skip a number of items",
|
|
32
39
|
})
|
|
33
40
|
.int()
|
|
34
41
|
.min(0)
|
|
35
42
|
.max(100000)
|
|
36
43
|
.optional(),
|
|
37
|
-
page: z
|
|
44
|
+
page: z.coerce
|
|
38
45
|
.number()
|
|
39
46
|
.int()
|
|
40
47
|
.openapi({
|
|
41
48
|
example: 1,
|
|
42
|
-
description:
|
|
49
|
+
description: "Page number for pagination",
|
|
43
50
|
})
|
|
44
51
|
.min(1)
|
|
45
52
|
.max(100000)
|
|
@@ -50,40 +57,85 @@ export const zPagination = {
|
|
|
50
57
|
export const zPaginationResponse = () =>
|
|
51
58
|
z.object({
|
|
52
59
|
results: z.array(z.unknown()), // Replace with your specific item schema
|
|
53
|
-
totalResults: z
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
totalResults: z
|
|
61
|
+
.number()
|
|
62
|
+
.openapi({ example: 100, description: "Total number of items" }),
|
|
63
|
+
totalPages: z
|
|
64
|
+
.number()
|
|
65
|
+
.openapi({ example: 10, description: "Total number of pages" }),
|
|
66
|
+
page: z
|
|
67
|
+
.number()
|
|
68
|
+
.openapi({ example: 1, description: "Current page number" }),
|
|
69
|
+
limit: z
|
|
70
|
+
.number()
|
|
71
|
+
.openapi({ example: 10, description: "Number of items per page" }),
|
|
57
72
|
});
|
|
58
73
|
|
|
74
|
+
const defaultObjectIdExample = "682fd0d7d4a6325d9d45b86d";
|
|
75
|
+
const exampleDefaults = {
|
|
76
|
+
organization: "682fd0d7d4a6325d9d45b86e",
|
|
77
|
+
user: defaultObjectIdExample,
|
|
78
|
+
device: "682fd0d7d4a6325d9d45b86f",
|
|
79
|
+
paper: "682fd0d7d4a6325d9d45b870",
|
|
80
|
+
};
|
|
81
|
+
const objectIdExampleOverrides: Record<string, string | undefined> = {
|
|
82
|
+
organizationId:
|
|
83
|
+
process.env.SCHEMA_EXAMPLE_ORGANIZATION_ID || exampleDefaults.organization,
|
|
84
|
+
organization:
|
|
85
|
+
process.env.SCHEMA_EXAMPLE_ORGANIZATION_ID || exampleDefaults.organization,
|
|
86
|
+
userId: process.env.SCHEMA_EXAMPLE_USER_ID || exampleDefaults.user,
|
|
87
|
+
deviceId: process.env.SCHEMA_EXAMPLE_DEVICE_ID || exampleDefaults.device,
|
|
88
|
+
device: process.env.SCHEMA_EXAMPLE_DEVICE_ID || exampleDefaults.device,
|
|
89
|
+
paperId: process.env.SCHEMA_EXAMPLE_PAPER_ID || exampleDefaults.paper,
|
|
90
|
+
paper: process.env.SCHEMA_EXAMPLE_PAPER_ID || exampleDefaults.paper,
|
|
91
|
+
patient: process.env.SCHEMA_EXAMPLE_USER_ID || exampleDefaults.user,
|
|
92
|
+
accountId: process.env.SCHEMA_EXAMPLE_ACCOUNT_ID,
|
|
93
|
+
tokenId: process.env.SCHEMA_EXAMPLE_TOKEN_ID,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const zObjectIdFor = (paramName?: string) => {
|
|
97
|
+
const example = paramName ? objectIdExampleOverrides[paramName] : undefined;
|
|
98
|
+
const exampleValue = example || defaultObjectIdExample;
|
|
99
|
+
return z
|
|
100
|
+
.string()
|
|
101
|
+
.refine((val) => {
|
|
102
|
+
if (process.env.SCHEMA_STRICT_EXAMPLES === "true" && example) {
|
|
103
|
+
return val === example;
|
|
104
|
+
}
|
|
105
|
+
return mongoose.Types.ObjectId.isValid(val);
|
|
106
|
+
})
|
|
107
|
+
.openapi({
|
|
108
|
+
example: exampleValue,
|
|
109
|
+
description: "A valid MongoDB ObjectId",
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
59
113
|
export const zGet = (id: string) => ({
|
|
60
114
|
params: z.object({
|
|
61
|
-
[id]:
|
|
115
|
+
[id]: zObjectIdFor(id),
|
|
62
116
|
}),
|
|
63
117
|
});
|
|
64
118
|
|
|
65
|
-
export function zPatchBody<T extends ZodRawShape>(
|
|
119
|
+
export function zPatchBody<T extends ZodRawShape>(
|
|
120
|
+
shape: T,
|
|
121
|
+
message = "At least one field must be provided for update",
|
|
122
|
+
) {
|
|
66
123
|
// assume user passed in already-optional vals
|
|
67
124
|
return z.object(shape); // .refine((o) => Object.keys(o).length > 0, { message });
|
|
68
125
|
}
|
|
69
126
|
|
|
70
127
|
export const zUpdate = (id: string) => ({
|
|
71
128
|
params: z.object({
|
|
72
|
-
[id]:
|
|
129
|
+
[id]: zObjectIdFor(id),
|
|
73
130
|
}),
|
|
74
131
|
});
|
|
75
132
|
|
|
76
133
|
export const zDelete = (id: string) => ({
|
|
77
134
|
params: z.object({
|
|
78
|
-
[id]:
|
|
135
|
+
[id]: zObjectIdFor(id),
|
|
79
136
|
}),
|
|
80
137
|
});
|
|
81
138
|
|
|
82
|
-
export const zObjectId =
|
|
83
|
-
.string()
|
|
84
|
-
.refine((val) => {
|
|
85
|
-
return mongoose.Types.ObjectId.isValid(val);
|
|
86
|
-
})
|
|
87
|
-
.openapi({ example: '682fd0d7d4a6325d9d45b86d', description: 'A valid MongoDB ObjectId' });
|
|
139
|
+
export const zObjectId = zObjectIdFor();
|
|
88
140
|
|
|
89
141
|
export const zDate = () => z.string().pipe(z.coerce.date());
|
package/tsconfig.json
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
|
-
"module": "
|
|
4
|
+
"module": "ES2020",
|
|
5
5
|
"baseUrl": ".",
|
|
6
6
|
"rootDir": ".",
|
|
7
7
|
"outDir": "./dist",
|
|
8
8
|
"esModuleInterop": true,
|
|
9
|
-
"strict":
|
|
10
|
-
"
|
|
9
|
+
"strict": false,
|
|
10
|
+
"noImplicitAny": false,
|
|
11
|
+
"noImplicitThis": false,
|
|
12
|
+
"useUnknownInCatchVariables": false,
|
|
13
|
+
"noUncheckedIndexedAccess": false,
|
|
14
|
+
"exactOptionalPropertyTypes": false,
|
|
15
|
+
"moduleResolution": "Bundler",
|
|
11
16
|
"resolveJsonModule": true,
|
|
12
17
|
"forceConsistentCasingInFileNames": true,
|
|
13
18
|
"skipLibCheck": true,
|
|
@@ -17,6 +22,10 @@
|
|
|
17
22
|
"esm": true,
|
|
18
23
|
"experimentalSpecifierResolution": "node"
|
|
19
24
|
},
|
|
20
|
-
"include": [
|
|
25
|
+
"include": [
|
|
26
|
+
"src/**/*",
|
|
27
|
+
"common.legacy/**/*",
|
|
28
|
+
"../memo-api/src/middlewares/validateMessage.ts"
|
|
29
|
+
],
|
|
21
30
|
"exclude": ["node_modules", "dist"]
|
|
22
31
|
}
|