@tmlmobilidade/controllers 20260617.1318.33 → 20260617.1731.32

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.
@@ -1,6 +1,7 @@
1
1
  /* * */
2
2
  import { HTTP_STATUS, HttpException } from '@tmlmobilidade/consts';
3
3
  import { agencies } from '@tmlmobilidade/interfaces';
4
+ import { Logger } from '@tmlmobilidade/logger';
4
5
  /* * */
5
6
  export class AgenciesSharedController {
6
7
  //
@@ -20,8 +21,20 @@ export class AgenciesSharedController {
20
21
  */
21
22
  static async getById(request, reply) {
22
23
  const agencyData = await agencies.findById(request.params.id);
23
- if (!agencyData)
24
- throw new HttpException(HTTP_STATUS.NOT_FOUND, 'Agency not found');
24
+ if (!agencyData) {
25
+ const error = new HttpException(HTTP_STATUS.NOT_FOUND, 'Agency not found');
26
+ Logger.issue({
27
+ context: {
28
+ action: 'getById',
29
+ feature: 'agencies',
30
+ request,
31
+ value: request.params.id,
32
+ },
33
+ level: 'error',
34
+ messageOrError: error,
35
+ });
36
+ throw error;
37
+ }
25
38
  reply.send({ data: agencyData, error: null, statusCode: HTTP_STATUS.OK });
26
39
  }
27
40
  }
@@ -1,6 +1,7 @@
1
1
  /* * */
2
2
  import { HTTP_STATUS, HttpException } from '@tmlmobilidade/consts';
3
3
  import { fileExports, files } from '@tmlmobilidade/interfaces';
4
+ import { Logger } from '@tmlmobilidade/logger';
4
5
  /* * */
5
6
  export class ExporterSharedController {
6
7
  //
@@ -22,16 +23,52 @@ export class ExporterSharedController {
22
23
  static async download(request, reply) {
23
24
  const { id } = request.params;
24
25
  const fileExport = await fileExports.findById(id);
25
- if (!fileExport)
26
- throw new HttpException(HTTP_STATUS.NOT_FOUND, 'File export not found');
26
+ if (!fileExport) {
27
+ const error = new HttpException(HTTP_STATUS.NOT_FOUND, 'File export not found');
28
+ Logger.issue({
29
+ context: {
30
+ action: 'download',
31
+ feature: 'exporter',
32
+ request,
33
+ value: id,
34
+ },
35
+ level: 'error',
36
+ messageOrError: error,
37
+ });
38
+ throw error;
39
+ }
27
40
  // Retrieve file data from database
28
41
  const foundFileData = await files.findById(fileExport.file_id);
29
- if (!foundFileData)
30
- throw new HttpException(HTTP_STATUS.NOT_FOUND, 'File not found');
42
+ if (!foundFileData) {
43
+ const error = new HttpException(HTTP_STATUS.NOT_FOUND, 'File not found');
44
+ Logger.issue({
45
+ context: {
46
+ action: 'download',
47
+ feature: 'exporter',
48
+ request,
49
+ value: id,
50
+ },
51
+ level: 'error',
52
+ messageOrError: error,
53
+ });
54
+ throw error;
55
+ }
31
56
  // Stream the file in the given URL to the client
32
57
  const storageServiceResponse = await fetch(foundFileData.url);
33
- if (!storageServiceResponse.ok || !storageServiceResponse.body)
34
- return reply.code(500).send('Could not fetch file.');
58
+ if (!storageServiceResponse.ok || !storageServiceResponse.body) {
59
+ const error = new HttpException(HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Could not fetch file');
60
+ Logger.issue({
61
+ context: {
62
+ action: 'download',
63
+ feature: 'exporter',
64
+ request,
65
+ value: id,
66
+ },
67
+ level: 'error',
68
+ messageOrError: error,
69
+ });
70
+ throw error;
71
+ }
35
72
  // Set headers and pipe the response body to the client
36
73
  reply.header('Content-Disposition', `attachment; filename="${foundFileData.name}"`);
37
74
  reply.header('Content-Type', foundFileData.type);
@@ -20,8 +20,18 @@ export class HashedTripsSharedController {
20
20
  // Detect which agency_ids the user has access to,
21
21
  // based on their permissions. If none, return an empty array.
22
22
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
23
- if (!ridesPermission['resources']?.agency_ids?.length)
23
+ if (!ridesPermission['resources']?.agency_ids?.length) {
24
+ Logger.issue({
25
+ context: {
26
+ action: 'getBatch',
27
+ feature: 'hashedTrips',
28
+ request,
29
+ },
30
+ level: 'info',
31
+ messageOrError: 'No agency_ids found in permissions',
32
+ });
24
33
  return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
34
+ }
25
35
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
26
36
  //
27
37
  // Get the rides batch using native MongoDB cursor
@@ -48,7 +58,7 @@ export class HashedTripsSharedController {
48
58
  //
49
59
  // Fetch the rides batch from the database
50
60
  const ridesBatch = await rides.aggregate(pipeline);
51
- Logger.info(`HashedTripsSharedController.getBatch - ridesBatch count: ${ridesBatch?.length ?? 0}`);
61
+ Logger.info({ message: `HashedTripsSharedController.getBatch - ridesBatch count: ${ridesBatch?.length ?? 0}` });
52
62
  //
53
63
  // From the given batch of hashed_trip_ids,
54
64
  // fetch the full HashedTrip documents with a single query.
@@ -73,7 +73,7 @@ export async function getOperationalLinesBatch(query) {
73
73
  const pipelineResult = await ridesCollection
74
74
  .aggregate(pipeline, { allowDiskUse: true })
75
75
  .toArray();
76
- Logger.info(`OperationalLinesController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}`);
76
+ Logger.info({ message: `OperationalLinesController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}` });
77
77
  //
78
78
  // Setup the final Map to keep track of the Operation Lines,
79
79
  // using the line_id as the key to avoid duplicates,
@@ -1,6 +1,7 @@
1
1
  /* * */
2
2
  import { getOperationalLinesBatch } from './batch.js';
3
3
  import { HTTP_STATUS } from '@tmlmobilidade/consts';
4
+ import { Logger } from '@tmlmobilidade/logger';
4
5
  import { GetOperationalLinesBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
5
6
  /* * */
6
7
  export class OperationalLinesSharedController {
@@ -17,8 +18,18 @@ export class OperationalLinesSharedController {
17
18
  // Detect which agency_ids the user has access to,
18
19
  // based on their permissions. If none, return an empty array.
19
20
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
20
- if (!ridesPermission['resources']?.agency_ids?.length)
21
+ if (!ridesPermission['resources']?.agency_ids?.length) {
22
+ Logger.issue({
23
+ context: {
24
+ action: 'getBatch',
25
+ feature: 'operationalLines',
26
+ request,
27
+ },
28
+ level: 'info',
29
+ messageOrError: 'No agency_ids found in permissions',
30
+ });
21
31
  return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
32
+ }
22
33
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
23
34
  //
24
35
  // Run the query
@@ -2,6 +2,7 @@
2
2
  import { ridesChangeStream } from './watch.js';
3
3
  import { HTTP_STATUS } from '@tmlmobilidade/consts';
4
4
  import { rides, ridesBatchAggregationPipeline } from '@tmlmobilidade/interfaces';
5
+ import { Logger } from '@tmlmobilidade/logger';
5
6
  import { normalizeRide } from '@tmlmobilidade/normalizers';
6
7
  import { GetRidesBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
7
8
  /* * */
@@ -21,8 +22,18 @@ export class RidesSharedController {
21
22
  // Detect which agency_ids the user has access to,
22
23
  // based on their permissions. If none, return an empty array.
23
24
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
24
- if (!ridesPermission['resources']?.agency_ids?.length)
25
+ if (!ridesPermission['resources']?.agency_ids?.length) {
26
+ Logger.issue({
27
+ context: {
28
+ action: 'getBatch',
29
+ feature: 'rides',
30
+ request,
31
+ },
32
+ level: 'info',
33
+ messageOrError: 'No agency_ids found in permissions',
34
+ });
25
35
  return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
36
+ }
26
37
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
27
38
  //
28
39
  // If search is provided, immediately try to find the ride by ID.
@@ -84,8 +95,19 @@ export class RidesSharedController {
84
95
  // Detect which agency_ids the user has access to,
85
96
  // based on their permissions. If none, return an empty array.
86
97
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
87
- if (!ridesPermission['resources']?.agency_ids?.length)
98
+ if (!ridesPermission['resources']?.agency_ids?.length) {
99
+ Logger.issue({
100
+ context: {
101
+ action: 'getRideById',
102
+ feature: 'rides',
103
+ request,
104
+ value: request.params['id'],
105
+ },
106
+ level: 'info',
107
+ messageOrError: 'No agency_ids found in permissions',
108
+ });
88
109
  return reply.send({ data: null, error: null, statusCode: HTTP_STATUS.OK });
110
+ }
89
111
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
90
112
  //
91
113
  // If search is provided, immediately try to find the ride by ID.
@@ -113,8 +135,19 @@ export class RidesSharedController {
113
135
  // Detect which agency_ids the user has access to,
114
136
  // based on their permissions. If none, return an empty array.
115
137
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
116
- if (!ridesPermission['resources']?.agency_ids?.length)
138
+ if (!ridesPermission['resources']?.agency_ids?.length) {
139
+ Logger.issue({
140
+ context: {
141
+ action: 'getRideByIds',
142
+ feature: 'rides',
143
+ request,
144
+ value: request.query['ids'],
145
+ },
146
+ level: 'info',
147
+ messageOrError: 'No agency_ids found in permissions',
148
+ });
117
149
  return reply.send({ data: null, error: null, statusCode: HTTP_STATUS.OK });
150
+ }
118
151
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
119
152
  //
120
153
  // If search is provided, immediately try to find the ride by ID.
@@ -73,7 +73,7 @@ export async function getOperationalStopsBatch(query) {
73
73
  const pipelineResult = await ridesCollection
74
74
  .aggregate(pipeline, { allowDiskUse: true })
75
75
  .toArray();
76
- Logger.info(`OperationalStopsController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}`);
76
+ Logger.info({ message: `OperationalStopsController.getBatch - pipeline result count: ${pipelineResult?.length ?? 0}` });
77
77
  //
78
78
  // Setup the final Map to keep track of the Operation Stops,
79
79
  // using the stop_id as the key to avoid duplicates,
@@ -1,6 +1,7 @@
1
1
  /* * */
2
2
  import { getOperationalStopsBatch } from './batch.js';
3
3
  import { HTTP_STATUS } from '@tmlmobilidade/consts';
4
+ import { Logger } from '@tmlmobilidade/logger';
4
5
  import { GetOperationalStopsBatchQuerySchema, PermissionCatalog } from '@tmlmobilidade/types';
5
6
  /* * */
6
7
  export class OperationalStopsSharedController {
@@ -17,8 +18,18 @@ export class OperationalStopsSharedController {
17
18
  // Detect which agency_ids the user has access to,
18
19
  // based on their permissions. If none, return an empty array.
19
20
  const ridesPermission = PermissionCatalog.get(request.permissions, scope, action);
20
- if (!ridesPermission['resources']?.agency_ids?.length)
21
+ if (!ridesPermission['resources']?.agency_ids?.length) {
22
+ Logger.issue({
23
+ context: {
24
+ action: 'getBatch',
25
+ feature: 'operationalStops',
26
+ request,
27
+ },
28
+ level: 'info',
29
+ messageOrError: 'No agency_ids found in permissions',
30
+ });
21
31
  return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
32
+ }
22
33
  const allowAllAgencies = ridesPermission['resources'].agency_ids.includes(PermissionCatalog.ALLOW_ALL_FLAG);
23
34
  //
24
35
  // Run the query
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/controllers",
3
- "version": "20260617.1318.33",
3
+ "version": "20260617.1731.32",
4
4
  "author": {
5
5
  "email": "iso@tmlmobilidade.pt",
6
6
  "name": "TML-ISO"