@tmlmobilidade/export-data 20260107.1738.18 → 20260110.331.6

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/index.js CHANGED
@@ -17,6 +17,7 @@ import { exportValidationsByStop } from './tasks/apex-validations/validations-by
17
17
  import { exportValidationsRaw } from './tasks/apex-validations/validations-raw.js';
18
18
  import { exportHashedShapesGeoJSON } from './tasks/hashed-shapes/hashed-shapes-geojson.js';
19
19
  import { exportRidesRaw } from './tasks/rides/rides-raw.js';
20
+ import { exportSamsRaw } from './tasks/sams/sams-raw.js';
20
21
  import { exportVehicleEventsRaw } from './tasks/vehicle-events/vehicle-events-raw.js';
21
22
  import { exportTypeLabels, exportTypesWithoutFilters } from './types.js';
22
23
  import { initExportContext } from './utils/init-context.js';
@@ -32,6 +33,7 @@ import { ASCII_CM_SHORT } from '@tmlmobilidade/consts';
32
33
  // Greet the user
33
34
  console.log(ASCII_CM_SHORT.replace(/▒/g, '\x1b[33m▒\x1b[0m'));
34
35
  intro('Bem-vindo ao exportador de dados da CM!');
36
+ log.info(`A versão da aplicação é: ${context.app_version}`);
35
37
  log.info(`O ID desta exportação é: ${context._id}`);
36
38
  log.info(`Todos os resultados serão guardados aqui: ${context.output}`);
37
39
  //
@@ -116,6 +118,11 @@ import { ASCII_CM_SHORT } from '@tmlmobilidade/consts';
116
118
  task: async (message) => await exportHashedShapesGeoJSON({ context, hashedShapeIds, message }),
117
119
  title: exportTypeLabels['hashed-shapes-geojson'],
118
120
  },
121
+ {
122
+ enabled: exportTypes.includes('sams-raw'),
123
+ task: async (message) => await exportSamsRaw({ context, message }),
124
+ title: exportTypeLabels['sams-raw'],
125
+ },
119
126
  ]);
120
127
  //
121
128
  // Terminate the process
@@ -24,6 +24,9 @@ export async function promptExportTypes() {
24
24
  '4. HashedShapes': [
25
25
  { label: exportTypeLabels['hashed-shapes-geojson'], value: 'hashed-shapes-geojson' },
26
26
  ],
27
+ '5. SAMs': [
28
+ { label: exportTypeLabels['sams-raw'], value: 'sams-raw' },
29
+ ],
27
30
  },
28
31
  required: true,
29
32
  });
@@ -0,0 +1,2 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ export declare function exportSamsRaw({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,61 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { sams } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'sams-raw';
8
+ /* * */
9
+ export async function exportSamsRaw({ context, message }) {
10
+ //
11
+ message('A iniciar a exportação de SAMs em bruto...');
12
+ //
13
+ // Prepare the filter params
14
+ const filterQuery = {};
15
+ if (context.filters.agency_ids.length) {
16
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
17
+ }
18
+ //
19
+ // Setup a database stream to export data
20
+ message(`A iniciar ligação à base de dados...`);
21
+ const samsCollection = await sams.getCollection();
22
+ const stream = samsCollection.find(filterQuery).stream();
23
+ //
24
+ // Prepare the output directory and CSV writer
25
+ message(`A preparar a pasta para guardar os resultados...`);
26
+ if (!fs.existsSync(context.output))
27
+ fs.mkdirSync(context.output, { recursive: true });
28
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
29
+ //
30
+ // Export the data
31
+ let counter = 0;
32
+ message(`A aguardar o resultado da pesquisa...`);
33
+ for await (const doc of stream) {
34
+ const document = doc;
35
+ for (const analysisGroup of document.analysis) {
36
+ await csvWriter.write({
37
+ _id: document._id,
38
+ agency_id: document.agency_id,
39
+ apex_version: analysisGroup.apex_version ?? null,
40
+ device_id: analysisGroup.device_id ?? null,
41
+ end_time: analysisGroup.end_time ? Dates.fromUnixTimestamp(analysisGroup.end_time).iso : null,
42
+ first_transaction_ase_counter_value: analysisGroup.first_transaction_ase_counter_value ?? null,
43
+ first_transaction_id: analysisGroup.first_transaction_id ?? null,
44
+ first_transaction_type: analysisGroup.first_transaction_type ?? null,
45
+ last_transaction_ase_counter_value: analysisGroup.last_transaction_ase_counter_value ?? null,
46
+ last_transaction_id: analysisGroup.last_transaction_id ?? null,
47
+ last_transaction_type: analysisGroup.last_transaction_type ?? null,
48
+ start_time: analysisGroup.start_time ? Dates.fromUnixTimestamp(analysisGroup.start_time).iso : null,
49
+ transactions_expected: analysisGroup.transactions_expected ?? null,
50
+ transactions_found: analysisGroup.transactions_found ?? null,
51
+ transactions_missing: analysisGroup.transactions_missing ?? null,
52
+ vehicle_id: analysisGroup.vehicle_id ?? null,
53
+ });
54
+ }
55
+ if (counter % 1000 === 0)
56
+ message(`Processados ${counter} documentos até agora...`);
57
+ counter++;
58
+ }
59
+ await csvWriter.flush();
60
+ //
61
+ }
@@ -0,0 +1,18 @@
1
+ export interface SamExport {
2
+ _id: number;
3
+ agency_id: string;
4
+ apex_version: null | string;
5
+ device_id: null | string;
6
+ end_time: null | string;
7
+ first_transaction_ase_counter_value: null | number;
8
+ first_transaction_id: null | string;
9
+ first_transaction_type: null | string;
10
+ last_transaction_ase_counter_value: null | number;
11
+ last_transaction_id: null | string;
12
+ last_transaction_type: null | string;
13
+ start_time: null | string;
14
+ transactions_expected: null | number;
15
+ transactions_found: null | number;
16
+ transactions_missing: null | number;
17
+ vehicle_id: null | number;
18
+ }
@@ -0,0 +1,2 @@
1
+ /* * */
2
+ export {};
package/dist/types.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { type OperationalDate } from '@tmlmobilidade/types';
2
2
  export declare const exportTypeLabels: {
3
+ readonly 'hashed-shapes-geojson': "4.0. HashedShapes para GeoJSON";
3
4
  readonly 'rides-raw': "2.0. Rides em bruto (SLAs)";
5
+ readonly 'sams-raw': "5.0. SAMs em bruto (Sequencialidade)";
4
6
  readonly 'validations-by-line': "1.5. Validações por Line ID";
5
7
  readonly 'validations-by-pattern': "1.4. Validações por Pattern ID";
6
8
  readonly 'validations-by-stop': "1.3. Validações por Stop ID";
@@ -8,7 +10,6 @@ export declare const exportTypeLabels: {
8
10
  readonly 'validations-by-stop-by-trip': "1.1. Validações por Stop ID, por Trip ID";
9
11
  readonly 'validations-raw': "1.0. Validações em bruto";
10
12
  readonly 'vehicle-events-raw': "3.0. Vehicle Events em bruto";
11
- readonly 'hashed-shapes-geojson': "4.0. HashedShapes para GeoJSON";
12
13
  };
13
14
  export type ExportType = keyof typeof exportTypeLabels;
14
15
  /**
@@ -18,6 +19,7 @@ export type ExportType = keyof typeof exportTypeLabels;
18
19
  export declare const exportTypesWithoutFilters: ExportType[];
19
20
  export interface ExportContext {
20
21
  _id: string;
22
+ app_version: string;
21
23
  dates: {
22
24
  end: OperationalDate;
23
25
  start: OperationalDate;
package/dist/types.js CHANGED
@@ -1,8 +1,9 @@
1
- /* eslint-disable perfectionist/sort-objects */
2
1
  /* * */
3
2
  /* * */
4
3
  export const exportTypeLabels = {
4
+ 'hashed-shapes-geojson': '4.0. HashedShapes para GeoJSON',
5
5
  'rides-raw': '2.0. Rides em bruto (SLAs)',
6
+ 'sams-raw': '5.0. SAMs em bruto (Sequencialidade)',
6
7
  'validations-by-line': '1.5. Validações por Line ID',
7
8
  'validations-by-pattern': '1.4. Validações por Pattern ID',
8
9
  'validations-by-stop': '1.3. Validações por Stop ID',
@@ -10,7 +11,6 @@ export const exportTypeLabels = {
10
11
  'validations-by-stop-by-trip': '1.1. Validações por Stop ID, por Trip ID',
11
12
  'validations-raw': '1.0. Validações em bruto',
12
13
  'vehicle-events-raw': '3.0. Vehicle Events em bruto',
13
- 'hashed-shapes-geojson': '4.0. HashedShapes para GeoJSON',
14
14
  };
15
15
  /**
16
16
  * Export types that don't require filters or dates.
@@ -1,5 +1,7 @@
1
1
  /* * */
2
2
  import { generateRandomString } from '@tmlmobilidade/strings';
3
+ import { readFileSync } from 'node:fs';
4
+ import { findPackageJSON } from 'node:module';
3
5
  import path from 'node:path';
4
6
  /* * */
5
7
  export function initExportContext() {
@@ -8,6 +10,11 @@ export function initExportContext() {
8
10
  // Generate a random export ID
9
11
  const exportId = generateRandomString();
10
12
  //
13
+ // Get the app version from the package.json file
14
+ const pjsonPath = findPackageJSON('@tmlmobilidade/export-data', import.meta.url);
15
+ const pjsonFile = readFileSync(pjsonPath, 'utf-8');
16
+ const appVersion = JSON.parse(pjsonFile).version;
17
+ //
11
18
  // Setup the output path for the export by joining
12
19
  // the current working directory with the export ID
13
20
  const outputPath = path.join(process.cwd(), `export-${exportId}`);
@@ -15,6 +22,7 @@ export function initExportContext() {
15
22
  // Build and return the export context object
16
23
  return {
17
24
  _id: exportId,
25
+ app_version: appVersion,
18
26
  dates: {
19
27
  end: undefined,
20
28
  start: undefined,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/export-data",
3
3
  "description": "CLI tool to export data from GO.",
4
- "version": "20260107.1738.18",
4
+ "version": "20260110.331.6",
5
5
  "author": {
6
6
  "email": "iso@tmlmobilidade.pt",
7
7
  "name": "TML-ISO"