@internetderdinge/api 1.224.2

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 (102) hide show
  1. package/.github/copilot-instructions.md +77 -0
  2. package/CHANGELOG.md +11 -0
  3. package/README.md +52 -0
  4. package/package.json +112 -0
  5. package/src/accounts/accounts.controller.ts +166 -0
  6. package/src/accounts/accounts.route.ts +107 -0
  7. package/src/accounts/accounts.schemas.ts +16 -0
  8. package/src/accounts/accounts.service.ts +85 -0
  9. package/src/accounts/accounts.validation.ts +118 -0
  10. package/src/accounts/auth0.service.ts +226 -0
  11. package/src/config/config.ts +49 -0
  12. package/src/config/logger.ts +33 -0
  13. package/src/config/morgan.ts +22 -0
  14. package/src/config/passport.cjs +30 -0
  15. package/src/config/roles.ts +13 -0
  16. package/src/config/tokens.cjs +10 -0
  17. package/src/devices/devices.controller.ts +276 -0
  18. package/src/devices/devices.model.ts +126 -0
  19. package/src/devices/devices.route.ts +198 -0
  20. package/src/devices/devices.schemas.ts +94 -0
  21. package/src/devices/devices.service.ts +320 -0
  22. package/src/devices/devices.validation.ts +221 -0
  23. package/src/devicesNotifications/devicesNotifications.controller.ts +72 -0
  24. package/src/devicesNotifications/devicesNotifications.model.ts +67 -0
  25. package/src/devicesNotifications/devicesNotifications.route.ts +150 -0
  26. package/src/devicesNotifications/devicesNotifications.schemas.ts +11 -0
  27. package/src/devicesNotifications/devicesNotifications.service.ts +222 -0
  28. package/src/devicesNotifications/devicesNotifications.validation.ts +56 -0
  29. package/src/email/email.service.ts +609 -0
  30. package/src/files/upload.service.ts +145 -0
  31. package/src/i18n/i18n.ts +51 -0
  32. package/src/i18n/saveMissingLocalJsonBackend.ts +92 -0
  33. package/src/index.ts +7 -0
  34. package/src/iotdevice/iotdevice.controller.ts +136 -0
  35. package/src/iotdevice/iotdevice.model.ts +32 -0
  36. package/src/iotdevice/iotdevice.route.ts +181 -0
  37. package/src/iotdevice/iotdevice.schemas.ts +79 -0
  38. package/src/iotdevice/iotdevice.service.ts +732 -0
  39. package/src/iotdevice/iotdevice.validation.ts +61 -0
  40. package/src/middlewares/auth.ts +110 -0
  41. package/src/middlewares/checkJwt.cjs +19 -0
  42. package/src/middlewares/error.js.legacy +44 -0
  43. package/src/middlewares/error.ts +41 -0
  44. package/src/middlewares/mongooseValidations/ensureSameOrganization.ts +15 -0
  45. package/src/middlewares/rateLimiter.ts +10 -0
  46. package/src/middlewares/validate.ts +25 -0
  47. package/src/middlewares/validateAction.ts +41 -0
  48. package/src/middlewares/validateAdmin.ts +21 -0
  49. package/src/middlewares/validateAi.ts +24 -0
  50. package/src/middlewares/validateCurrentAuthUser.ts +23 -0
  51. package/src/middlewares/validateCurrentUser.ts +35 -0
  52. package/src/middlewares/validateDevice.ts +191 -0
  53. package/src/middlewares/validateDeviceUserOrganization.ts +54 -0
  54. package/src/middlewares/validateOrganization.ts +109 -0
  55. package/src/middlewares/validateQuerySearchUserAndOrganization.ts +75 -0
  56. package/src/middlewares/validateTokens.ts +36 -0
  57. package/src/middlewares/validateUser.ts +75 -0
  58. package/src/middlewares/validateZod.ts +54 -0
  59. package/src/models/plugins/index.ts +7 -0
  60. package/src/models/plugins/paginate.plugin.ts +145 -0
  61. package/src/models/plugins/paginateNew.plugin.ts +206 -0
  62. package/src/models/plugins/simplePopulate.ts +12 -0
  63. package/src/models/plugins/toJSON.plugin.ts +51 -0
  64. package/src/organizations/organizations.controller.ts +101 -0
  65. package/src/organizations/organizations.model.ts +62 -0
  66. package/src/organizations/organizations.route.ts +119 -0
  67. package/src/organizations/organizations.schemas.ts +8 -0
  68. package/src/organizations/organizations.service.ts +85 -0
  69. package/src/organizations/organizations.validation.ts +76 -0
  70. package/src/pdf/pdf.controller.ts +18 -0
  71. package/src/pdf/pdf.route.ts +28 -0
  72. package/src/pdf/pdf.schemas.ts +7 -0
  73. package/src/pdf/pdf.service.ts +89 -0
  74. package/src/pdf/pdf.validation.ts +30 -0
  75. package/src/tokens/tokens.controller.ts +81 -0
  76. package/src/tokens/tokens.model.ts +24 -0
  77. package/src/tokens/tokens.route.ts +66 -0
  78. package/src/tokens/tokens.schemas.ts +15 -0
  79. package/src/tokens/tokens.service.ts +46 -0
  80. package/src/tokens/tokens.validation.ts +13 -0
  81. package/src/types/routeSpec.ts +1 -0
  82. package/src/users/users.controller.ts +234 -0
  83. package/src/users/users.model.ts +89 -0
  84. package/src/users/users.route.ts +171 -0
  85. package/src/users/users.schemas.ts +79 -0
  86. package/src/users/users.service.ts +393 -0
  87. package/src/users/users.validation.ts +166 -0
  88. package/src/utils/ApiError.ts +18 -0
  89. package/src/utils/buildRouterAndDocs.ts +85 -0
  90. package/src/utils/catchAsync.ts +9 -0
  91. package/src/utils/comparePapers.service.ts +48 -0
  92. package/src/utils/filterOptions.ts +37 -0
  93. package/src/utils/medicationName.ts +12 -0
  94. package/src/utils/pick.ts +16 -0
  95. package/src/utils/registerOpenApi.ts +32 -0
  96. package/src/utils/urlUtils.ts +14 -0
  97. package/src/utils/userName.ts +27 -0
  98. package/src/utils/zValidations.ts +89 -0
  99. package/src/validations/auth.validation.cjs +60 -0
  100. package/src/validations/custom.validation.ts +26 -0
  101. package/src/validations/index.cjs +2 -0
  102. package/tsconfig.json +22 -0
@@ -0,0 +1,145 @@
1
+ import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
2
+ import { Upload } from '@aws-sdk/lib-storage';
3
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
4
+ import multer from 'multer';
5
+ import multerS3 from 'multer-s3';
6
+ import fs from 'fs';
7
+ import request from 'request';
8
+
9
+ type GetSignedFileUrlParams = {
10
+ fileName: string;
11
+ bucket?: string;
12
+ expiresIn?: number;
13
+ };
14
+
15
+ type UploadImageParams = {
16
+ key: string;
17
+ blob: Buffer | Uint8Array | Blob | string | ReadableStream;
18
+ };
19
+
20
+ const s3 = new S3Client({
21
+ region: 'eu-central-1',
22
+ credentials: {
23
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
24
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
25
+ },
26
+ });
27
+
28
+ export const getSignedFileUrl = async ({
29
+ fileName,
30
+ bucket = process.env.AWS_S3_BUCKET_NAME!,
31
+ expiresIn = 7200,
32
+ }: GetSignedFileUrlParams): Promise<string> => {
33
+ const command = new GetObjectCommand({
34
+ Bucket: bucket,
35
+ Key: fileName,
36
+ });
37
+
38
+ const result = await getSignedUrl(s3, command, { expiresIn });
39
+ return result;
40
+ };
41
+
42
+ export const uploadImage = async ({ key, blob }: UploadImageParams): Promise<{ hello: string }> => {
43
+ const target = {
44
+ Bucket: process.env.AWS_S3_BUCKET_NAME!,
45
+ Key: key,
46
+ Body: blob,
47
+ };
48
+
49
+ try {
50
+ const parallelUploads3 = new Upload({
51
+ client: s3,
52
+ queueSize: 4,
53
+ leavePartsOnError: false,
54
+ params: target,
55
+ });
56
+
57
+ parallelUploads3.on('httpUploadProgress', (progress) => {
58
+ // console.log(progress);
59
+ });
60
+
61
+ await parallelUploads3.done();
62
+ } catch (e) {
63
+ console.error(e);
64
+ }
65
+
66
+ return { hello: 'xx' };
67
+ };
68
+
69
+ export const fileFilter = (req: Express.Request, file: Express.Multer.File, cb: multer.FileFilterCallback): void => {
70
+ if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
71
+ cb(null, true);
72
+ } else {
73
+ cb(new Error('Invalid file type, only JPEG and PNG is allowed!'), false);
74
+ }
75
+ };
76
+
77
+ export const uploadFile = multer({
78
+ storage: multerS3({
79
+ s3: s3,
80
+ bucket: process.env.AWS_S3_BUCKET_NAME!,
81
+ contentType: multerS3.AUTO_CONTENT_TYPE,
82
+ acl: 'public-read',
83
+ metadata(req, file, cb) {
84
+ cb(null, { fieldName: file.fieldname });
85
+ },
86
+ key(req, file, cb) {
87
+ cb(null, `${Date.now().toString()}-${file.originalname}`);
88
+ },
89
+ }),
90
+ });
91
+
92
+ const getPhoto = async (photoId: string, res: Express.Response): Promise<void> => {
93
+ try {
94
+ const params = {
95
+ Bucket: process.env.AWS_S3_BUCKET_NAME!,
96
+ Key: photoId,
97
+ };
98
+
99
+ await s3
100
+ .getObject(params)
101
+ .on('httpHeaders', function (statusCode, headers) {
102
+ res.set('Content-Length', headers['content-length']);
103
+ res.set('Content-Type', headers['content-type']);
104
+ this.response.httpResponse.createUnbufferedStream().pipe(res);
105
+ })
106
+ .send();
107
+ } catch (e) {
108
+ throw new Error(`Could not retrieve file from S3: ${e.message}`);
109
+ }
110
+ };
111
+
112
+ const download = (uri: string, filename: string, callback: () => void): void => {
113
+ request.head(uri, (err, res, body) => {
114
+ if (err) {
115
+ console.error(err);
116
+ return;
117
+ }
118
+ console.log('content-type:', res.headers['content-type']);
119
+ console.log('content-length:', res.headers['content-length']);
120
+
121
+ request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
122
+ });
123
+ };
124
+
125
+ const getPhotoFromUserImage = async (photoId: string, res: Express.Response): Promise<void> => {
126
+ try {
127
+ const params = {
128
+ Bucket: process.env.AWS_S3_BUCKET_NAME!,
129
+ Key: photoId,
130
+ };
131
+
132
+ await s3
133
+ .getObject(params)
134
+ .on('httpHeaders', function (statusCode, headers) {
135
+ res.set('Content-Length', headers['content-length']);
136
+ res.set('Content-Type', headers['content-type']);
137
+ this.response.httpResponse.createUnbufferedStream().pipe(res);
138
+ })
139
+ .send();
140
+ } catch (e) {
141
+ throw new Error(`Could not retrieve file from S3: ${e.message}`);
142
+ }
143
+ };
144
+
145
+ export default { uploadFile, uploadImage, getPhoto, getPhotoFromUserImage, getSignedFileUrl };
@@ -0,0 +1,51 @@
1
+ import path from "path";
2
+ import { fileURLToPath } from "url";
3
+ import { join } from "path";
4
+ import { existsSync, readdirSync } from "fs";
5
+ import i18next from "i18next";
6
+ import Backend, { setLocalesFolder } from "./saveMissingLocalJsonBackend";
7
+
8
+ import config from "@wirewire/openiot-api/src/config/config";
9
+
10
+ // Fix for __dirname in ES modules
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ export interface InitI18nOptions {
15
+ generatedPath?: string;
16
+ }
17
+
18
+ export function initI18n(options: InitI18nOptions = {}): typeof i18next {
19
+ const localesFolder = options.generatedPath
20
+ ? path.resolve(options.generatedPath)
21
+ : join(__dirname, "./generated");
22
+
23
+ setLocalesFolder(localesFolder);
24
+
25
+ const hasLocalesFolder = existsSync(localesFolder);
26
+
27
+ if (!i18next.isInitialized) {
28
+ i18next.use(Backend).init({
29
+ initImmediate: false, // setting initImmediate to false, will load the resources synchronously
30
+ fallbackLng: "de",
31
+ preload: hasLocalesFolder
32
+ ? readdirSync(localesFolder)
33
+ .filter((fileName) => path.extname(fileName) === ".json")
34
+ .map((fileName) => path.basename(fileName, ".json"))
35
+ : [],
36
+
37
+ debug: false,
38
+ saveMissing: config.env !== "production",
39
+ ns: ["api"],
40
+ defaultNS: "api",
41
+ keySeparator: false,
42
+ interpolation: {
43
+ escapeValue: false,
44
+ },
45
+ });
46
+ }
47
+
48
+ return i18next;
49
+ }
50
+
51
+ export default i18next;
@@ -0,0 +1,92 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ import type { Callback } from "./types"; // Assuming a `types.ts` file exists for type definitions
5
+
6
+ // Fix for __dirname in ES modules
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ let localesFolder = path.join(__dirname, "./generated");
11
+
12
+ export function setLocalesFolder(nextPath?: string): void {
13
+ localesFolder = nextPath
14
+ ? path.resolve(nextPath)
15
+ : path.join(__dirname, "./generated");
16
+ }
17
+
18
+ interface CreateMissingTranslationParams {
19
+ content?: string;
20
+ namespace: string;
21
+ language: string;
22
+ key: string;
23
+ }
24
+
25
+ async function createMissingTranslation({
26
+ content,
27
+ namespace,
28
+ language,
29
+ key,
30
+ }: CreateMissingTranslationParams): Promise<Response> {
31
+ const response = await fetch(
32
+ `${process.env.REACT_APP_WEB_BACKEND_URL}/translations/create-missing`,
33
+ {
34
+ method: "POST",
35
+ headers: {
36
+ "Content-Type": "application/json",
37
+ },
38
+ body: JSON.stringify({
39
+ key,
40
+ content: content || key,
41
+ namespace,
42
+ language,
43
+ secret: process.env.REACT_APP_TRANSLATION_SECRET,
44
+ }),
45
+ },
46
+ );
47
+ return response;
48
+ }
49
+
50
+ const backend = {
51
+ type: "backend",
52
+
53
+ read(language: string, namespace: string, callback: Callback): void {
54
+ const filePath = path.join(localesFolder, `${language}.json`);
55
+
56
+ try {
57
+ const data = fs.readFileSync(filePath, "utf8");
58
+ const jsonData = JSON.parse(data);
59
+
60
+ /* return resources */
61
+ callback(null, jsonData);
62
+ } catch (error) {
63
+ callback(error, null);
64
+ }
65
+ },
66
+
67
+ create(
68
+ languages: string[],
69
+ namespace: string,
70
+ key: string,
71
+ fallbackValue?: string,
72
+ ): void {
73
+ console.log(
74
+ "missing translation saved",
75
+ languages,
76
+ namespace,
77
+ key,
78
+ fallbackValue,
79
+ );
80
+
81
+ createMissingTranslation({
82
+ key,
83
+ content: fallbackValue || key,
84
+ namespace,
85
+ language: "en",
86
+ }).catch((error) =>
87
+ console.error("Error creating missing translation:", error),
88
+ );
89
+ },
90
+ };
91
+
92
+ export default backend;
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { default as usersRoute } from "../src/users/users.route";
2
+ export { default as accountsRoute } from "../src/accounts/accounts.route";
3
+ export { default as organizationsRoute } from "../src/organizations/organizations.route";
4
+ export { default as devicesRoute } from "../src/devices/devices.route";
5
+ export { default as devicesNotificationsRoute } from "./devicesNotifications/devicesNotifications.route";
6
+ export { default as pdfRoute } from "../src/pdf/pdf.route";
7
+ export { default as tokensRoute } from "../src/tokens/tokens.route";
@@ -0,0 +1,136 @@
1
+ import type { Request, Response } from "express";
2
+ import catchAsync from "../utils/catchAsync";
3
+ import devicesService from "../devices/devices.service";
4
+ import iotDevicesService from "./iotdevice.service";
5
+ import httpStatus from "http-status";
6
+ import ApiError from "../utils/ApiError";
7
+
8
+ import type { Device, ShadowUpdatePayload } from "./iotdevice.types"; // Example type imports
9
+
10
+ export const getIotDevices = catchAsync(async (req: Request, res: Response) => {
11
+ const iotDevices = await iotDevicesService.getDeviceStatusList();
12
+ res.send({ results: iotDevices });
13
+ });
14
+
15
+ export const getEvents = catchAsync(async (req: Request, res: Response) => {
16
+ const device = await devicesService.getById(req.params.deviceId);
17
+ const events = await iotDevicesService.getEvents({
18
+ ...req.query,
19
+ DeviceId: device.deviceId,
20
+ });
21
+ res.send({ ...events, device });
22
+ });
23
+
24
+ export const getDevice = catchAsync(async (req: Request, res: Response) => {
25
+ const events = await iotDevicesService.getDevice(req.body.deviceId);
26
+ res.send(events);
27
+ });
28
+
29
+ export const activateDevice = catchAsync(
30
+ async (req: Request, res: Response) => {
31
+ const events = await iotDevicesService.activateDevice(req.body.deviceId);
32
+ res.send(events);
33
+ },
34
+ );
35
+
36
+ export const pingDevice = catchAsync(async (req: Request, res: Response) => {
37
+ const events = await iotDevicesService.pingDevice(req.body.deviceId);
38
+ res.send(events);
39
+ });
40
+
41
+ export const shadowAlarmUpdate = catchAsync(
42
+ async (req: Request, res: Response) => {
43
+ const device = await devicesService.getById(req.params.deviceId);
44
+ const { shadowName, ...others } = req.body as ShadowUpdatePayload;
45
+ const shadow = await iotDevicesService.shadowAlarmUpdate(
46
+ device.deviceId,
47
+ others,
48
+ shadowName,
49
+ );
50
+ res.send({ device, shadow });
51
+ },
52
+ );
53
+
54
+ export const shadowAlarmGet = catchAsync(
55
+ async (req: Request, res: Response) => {
56
+ const device = await devicesService.getById(req.params.deviceId);
57
+ const shadow = await iotDevicesService.shadowAlarmGet(
58
+ device.deviceId,
59
+ req.body,
60
+ );
61
+ res.send({ device, shadow });
62
+ },
63
+ );
64
+
65
+ export const shadowAdmin = catchAsync(async (req: Request, res: Response) => {
66
+ const shadow = await iotDevicesService.shadowAlarmGet(
67
+ req.params.nrfId,
68
+ req.params.shadowName,
69
+ );
70
+ res.send(shadow);
71
+ });
72
+
73
+ export const getDeviceStatus = catchAsync(
74
+ async (req: Request, res: Response) => {
75
+ const events = await iotDevicesService.getDeviceStatus(req.params.deviceId);
76
+ res.send(events);
77
+ },
78
+ );
79
+
80
+ export const ledLightHint = catchAsync(async (req: Request, res: Response) => {
81
+ const device = await devicesService.getById(req.params.deviceId);
82
+ const shadow = await iotDevicesService.ledLightHint(
83
+ device.deviceId,
84
+ req.body,
85
+ );
86
+ res.send({ device, shadow });
87
+ });
88
+
89
+ export const resetDevice = catchAsync(async (req: Request, res: Response) => {
90
+ const device = await devicesService.getById(req.params.deviceId);
91
+ const shadow = await iotDevicesService.resetDevice(device.deviceId, req.body);
92
+ res.send({ device, shadow });
93
+ });
94
+
95
+ export const getEntry = catchAsync(async (req: Request, res: Response) => {
96
+ const iotDevice = await iotDevicesService.getDevice([req.params.deviceId]);
97
+ if (!iotDevice?.message?.[0]) {
98
+ throw new ApiError(httpStatus.NOT_FOUND, "IoT Device not found");
99
+ }
100
+ res.send(iotDevice.message[0]);
101
+ });
102
+
103
+ export const updateEntry = catchAsync(async (req: Request, res: Response) => {
104
+ const user = await iotDevicesService.updateById(req.params.stockId, req.body);
105
+ res.send(user);
106
+ });
107
+
108
+ export const deleteEntry = catchAsync(async (req: Request, res: Response) => {
109
+ const entry = await iotDevicesService.deleteById(req.params.stockId);
110
+ res.send(entry);
111
+ });
112
+
113
+ export const getApiStatus = catchAsync(async (req: Request, res: Response) => {
114
+ const events = await iotDevicesService.getApiStatus(req.params.kind);
115
+ if (!events) {
116
+ throw new ApiError(httpStatus.UNAUTHORIZED, "API unavailable");
117
+ }
118
+ res.send(events);
119
+ });
120
+
121
+ export default {
122
+ getEvents,
123
+ getIotDevices,
124
+ getDevice,
125
+ shadowAlarmGet,
126
+ shadowAdmin,
127
+ pingDevice,
128
+ getDeviceStatus,
129
+ ledLightHint,
130
+ shadowAlarmUpdate,
131
+ getEntry,
132
+ getApiStatus,
133
+ updateEntry,
134
+ resetDevice,
135
+ deleteEntry,
136
+ };
@@ -0,0 +1,32 @@
1
+ import mongoose, { Schema, Document, Model } from 'mongoose';
2
+ import { toJSON, paginate } from '../models/plugins/index';
3
+
4
+ interface IotDeviceMeta {
5
+ [key: string]: any;
6
+ }
7
+
8
+ export interface IotDevice extends Document {
9
+ description?: string;
10
+ meta?: IotDeviceMeta;
11
+ deviceId?: string;
12
+ }
13
+
14
+ const iotDeviceSchema: Schema<IotDevice> = new mongoose.Schema(
15
+ {
16
+ description: {
17
+ type: String,
18
+ },
19
+ meta: { type: Object },
20
+ deviceId: { type: String },
21
+ },
22
+ {
23
+ timestamps: true,
24
+ },
25
+ );
26
+
27
+ iotDeviceSchema.plugin(toJSON);
28
+ iotDeviceSchema.plugin(paginate);
29
+
30
+ export const IotDevices: Model<IotDevice> = mongoose.model<IotDevice>('IotDevice', iotDeviceSchema);
31
+
32
+ export default IotDevices;
@@ -0,0 +1,181 @@
1
+ import { Router } from 'express';
2
+ import buildRouterAndDocs from '../utils/buildRouterAndDocs';
3
+ import auth from '../middlewares/auth';
4
+ import { validateAdmin } from '../middlewares/validateAdmin';
5
+ import { validateDevice } from '../middlewares/validateDevice';
6
+ import type { RouteSpec } from '../types/routeSpec';
7
+
8
+ import {
9
+ getEventsSchema,
10
+ getDeviceSchema,
11
+ getEntrySchema,
12
+ updateEntrySchema,
13
+ pingDeviceSchema,
14
+ iotDevicesSchema,
15
+ shadowAlarmValidationSchema,
16
+ apiStatusRequestSchema,
17
+ // add other input schemas as needed
18
+ } from './iotdevice.validation';
19
+
20
+ import {
21
+ iotDeviceResponseSchema,
22
+ eventResponseSchema,
23
+ deviceResponseSchema,
24
+ shadowAlarmSchema,
25
+ pingResponseSchema,
26
+ deviceStatusSchema,
27
+ apiStatusSchema,
28
+ entryResponseSchema,
29
+ } from './iotdevice.schemas';
30
+
31
+ import {
32
+ getIotDevices,
33
+ getEvents,
34
+ getDevice,
35
+ shadowAlarmGet,
36
+ shadowAlarmUpdate,
37
+ shadowAdmin,
38
+ pingDevice,
39
+ getDeviceStatus,
40
+ getApiStatus,
41
+ getEntry,
42
+ updateEntry,
43
+ } from './iotdevice.controller';
44
+ import { request } from 'https';
45
+
46
+ export const iotdeviceRouteSpecs: RouteSpec[] = [
47
+ {
48
+ method: 'get',
49
+ path: '/',
50
+ validate: [auth('getUsers'), validateAdmin],
51
+ requestSchema: iotDevicesSchema,
52
+ responseSchema: iotDeviceResponseSchema.array(),
53
+ handler: getIotDevices,
54
+ summary: 'List all IoT devices',
55
+ description: 'Retrieves a list of all registered IoT devices.',
56
+ },
57
+ {
58
+ method: 'get',
59
+ path: '/events/:deviceId',
60
+ validate: [auth('getUsers'), validateDevice],
61
+ requestSchema: getEventsSchema,
62
+ responseSchema: eventResponseSchema.array(),
63
+ handler: getEvents,
64
+ summary: 'Get events for a device',
65
+ description: 'Fetches event records for the specified device by its ID.',
66
+ },
67
+ {
68
+ method: 'post',
69
+ path: '/devices',
70
+ validate: [auth('getUsers'), validateAdmin],
71
+ requestSchema: getDeviceSchema,
72
+ responseSchema: deviceResponseSchema,
73
+ handler: getDevice,
74
+ summary: 'Fetch a single device by criteria',
75
+ description: 'Retrieves a single IoT device matching the provided criteria.',
76
+ },
77
+ {
78
+ method: 'get',
79
+ path: '/device/shadowAlarmUpdate/:deviceId',
80
+ validate: [auth('getUsers'), validateAdmin],
81
+ requestSchema: getEntrySchema,
82
+ responseSchema: shadowAlarmSchema,
83
+ handler: shadowAlarmGet,
84
+ summary: 'Get shadow alarm settings',
85
+ description: 'Fetches the shadow alarm configuration for a specific device.',
86
+ },
87
+ {
88
+ method: 'post',
89
+ path: '/device/shadowAlarmUpdate/:deviceId',
90
+ validate: [auth('getUsers'), validateAdmin],
91
+ requestSchema: shadowAlarmSchema,
92
+ responseSchema: shadowAlarmSchema,
93
+ handler: shadowAlarmUpdate,
94
+ summary: 'Update shadow alarm settings',
95
+ description: 'Updates the shadow alarm configuration for a specific device.',
96
+ },
97
+ {
98
+ method: 'get',
99
+ path: '/shadow/:nrfId/:shadowName',
100
+ validate: [auth('getUsers'), validateAdmin],
101
+ requestSchema: shadowAlarmValidationSchema,
102
+ responseSchema: shadowAlarmSchema,
103
+ handler: shadowAdmin,
104
+ summary: 'Administer device shadow by nrfId and name',
105
+ description: 'Performs administrative operations on a device shadow identified by NRF ID and shadow name.',
106
+ },
107
+ {
108
+ method: 'post',
109
+ path: '/ledlight/:deviceId',
110
+ validate: [auth('getUsers'), validateAdmin],
111
+ responseSchema: pingResponseSchema,
112
+ handler: pingDevice,
113
+ summary: 'Ping device LED light',
114
+ description: 'Sends a ping to the device’s LED light to test its connectivity or response.',
115
+ },
116
+ {
117
+ method: 'post',
118
+ path: '/ping/:deviceId',
119
+ validate: [auth('getUsers'), validateAdmin],
120
+ requestSchema: pingDeviceSchema,
121
+ responseSchema: pingResponseSchema,
122
+ handler: pingDevice,
123
+ summary: 'Ping device',
124
+ description: 'Sends a ping command to the specified device to verify its availability.',
125
+ },
126
+ {
127
+ method: 'get',
128
+ path: '/getDeviceStatus/:deviceId',
129
+ validate: [auth('getUsers'), validateAdmin],
130
+ responseSchema: deviceStatusSchema,
131
+ handler: getDeviceStatus,
132
+ summary: 'Get current status of a device',
133
+ description: 'Retrieves the current operational status of the specified device.',
134
+ },
135
+ {
136
+ method: 'get',
137
+ path: '/status/:kind',
138
+ validate: [],
139
+ requestSchema: apiStatusRequestSchema,
140
+ responseSchema: apiStatusSchema,
141
+ handler: getApiStatus,
142
+ summary: 'Get API status by kind',
143
+ description: 'Retrieves the API status information for a given status kind.',
144
+ },
145
+ {
146
+ method: 'get',
147
+ path: '/:deviceId',
148
+ validate: [auth('getUsers'), validateDevice, validateAdmin],
149
+ requestSchema: getEntrySchema,
150
+ responseSchema: entryResponseSchema,
151
+ handler: getEntry,
152
+ summary: 'Get one entry for a device',
153
+ description: 'Fetches a single data entry for the specified device by ID.',
154
+ },
155
+ {
156
+ method: 'post',
157
+ path: '/:deviceId',
158
+ validate: [auth('manageUsers'), validateDevice, validateAdmin],
159
+ requestSchema: updateEntrySchema,
160
+ responseSchema: entryResponseSchema,
161
+ handler: updateEntry,
162
+ summary: 'Create or replace an entry for a device',
163
+ description: 'Creates or replaces a data entry for the specified device.',
164
+ },
165
+ {
166
+ method: 'patch',
167
+ path: '/:deviceId',
168
+ validate: [auth('manageUsers'), validateDevice, validateAdmin],
169
+ requestSchema: updateEntrySchema,
170
+ responseSchema: entryResponseSchema,
171
+ handler: updateEntry,
172
+ summary: 'Update an entry for a device',
173
+ description: 'Applies a partial update to an existing data entry for the specified device.',
174
+ },
175
+ ];
176
+
177
+ const router: Router = Router();
178
+
179
+ buildRouterAndDocs(router, iotdeviceRouteSpecs, '/iotdevice', ['IoTDevice']);
180
+
181
+ export default router;