@tmlmobilidade/export-data 20251229.1441.35

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 (39) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +100 -0
  3. package/dist/prompts/export-types.d.ts +2 -0
  4. package/dist/prompts/export-types.js +34 -0
  5. package/dist/prompts/filter-agency-ids.d.ts +1 -0
  6. package/dist/prompts/filter-agency-ids.js +25 -0
  7. package/dist/prompts/filter-dates.d.ts +5 -0
  8. package/dist/prompts/filter-dates.js +73 -0
  9. package/dist/prompts/filter-line-ids.d.ts +1 -0
  10. package/dist/prompts/filter-line-ids.js +25 -0
  11. package/dist/prompts/filter-pattern-ids.d.ts +1 -0
  12. package/dist/prompts/filter-pattern-ids.js +25 -0
  13. package/dist/prompts/filter-stop-ids.d.ts +1 -0
  14. package/dist/prompts/filter-stop-ids.js +26 -0
  15. package/dist/prompts/filter-types.d.ts +1 -0
  16. package/dist/prompts/filter-types.js +20 -0
  17. package/dist/prompts/filter-vehicle-ids.d.ts +1 -0
  18. package/dist/prompts/filter-vehicle-ids.js +25 -0
  19. package/dist/tasks/apex-validations/validations-by-line.d.ts +2 -0
  20. package/dist/tasks/apex-validations/validations-by-line.js +85 -0
  21. package/dist/tasks/apex-validations/validations-by-pattern.d.ts +5 -0
  22. package/dist/tasks/apex-validations/validations-by-pattern.js +87 -0
  23. package/dist/tasks/apex-validations/validations-by-stop-by-pattern.d.ts +5 -0
  24. package/dist/tasks/apex-validations/validations-by-stop-by-pattern.js +88 -0
  25. package/dist/tasks/apex-validations/validations-by-stop-by-trip.d.ts +5 -0
  26. package/dist/tasks/apex-validations/validations-by-stop-by-trip.js +88 -0
  27. package/dist/tasks/apex-validations/validations-by-stop.d.ts +5 -0
  28. package/dist/tasks/apex-validations/validations-by-stop.js +87 -0
  29. package/dist/tasks/apex-validations/validations-raw.d.ts +2 -0
  30. package/dist/tasks/apex-validations/validations-raw.js +64 -0
  31. package/dist/tasks/rides/rides-raw.d.ts +2 -0
  32. package/dist/tasks/rides/rides-raw.js +54 -0
  33. package/dist/tasks/vehicle-events/vehicle-events-raw.d.ts +2 -0
  34. package/dist/tasks/vehicle-events/vehicle-events-raw.js +64 -0
  35. package/dist/types.d.ts +31 -0
  36. package/dist/types.js +12 -0
  37. package/dist/utils/init-context.d.ts +2 -0
  38. package/dist/utils/init-context.js +31 -0
  39. package/package.json +54 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { promptExportTypes } from './prompts/export-types.js';
3
+ import { promptFilterByAgencyIds } from './prompts/filter-agency-ids.js';
4
+ import { promptFilterByDates } from './prompts/filter-dates.js';
5
+ import { promptFilterByLineIds } from './prompts/filter-line-ids.js';
6
+ import { promptFilterByPatternIds } from './prompts/filter-pattern-ids.js';
7
+ import { promptFilterByStopIds } from './prompts/filter-stop-ids.js';
8
+ import { promptFilterTypes } from './prompts/filter-types.js';
9
+ import { promptFilterByVehicleIds } from './prompts/filter-vehicle-ids.js';
10
+ import { exportValidationsByLine } from './tasks/apex-validations/validations-by-line.js';
11
+ import { exportValidationsByPattern } from './tasks/apex-validations/validations-by-pattern.js';
12
+ import { exportValidationsByStopByPattern } from './tasks/apex-validations/validations-by-stop-by-pattern.js';
13
+ import { exportValidationsByStopByTrip } from './tasks/apex-validations/validations-by-stop-by-trip.js';
14
+ import { exportValidationsByStop } from './tasks/apex-validations/validations-by-stop.js';
15
+ import { exportValidationsRaw } from './tasks/apex-validations/validations-raw.js';
16
+ import { exportRidesRaw } from './tasks/rides/rides-raw.js';
17
+ import { exportVehicleEventsRaw } from './tasks/vehicle-events/vehicle-events-raw.js';
18
+ import { exportTypeLabels } from './types.js';
19
+ import { initExportContext } from './utils/init-context.js';
20
+ import { intro, log, outro, tasks } from '@clack/prompts';
21
+ import { ASCII_CM_SHORT } from '@tmlmobilidade/consts';
22
+ /* * */
23
+ (async function main() {
24
+ //
25
+ //
26
+ // Initialize the export context
27
+ const context = initExportContext();
28
+ //
29
+ // Greet the user
30
+ console.log(ASCII_CM_SHORT);
31
+ intro('Bem-vindo ao exportador de dados da CM!');
32
+ log.info(`O ID desta exportação é: ${context._id}`);
33
+ log.info(`Todos os resultados serão guardados aqui: ${context.output}`);
34
+ //
35
+ // Request the export types and which filters to apply
36
+ const exportTypes = await promptExportTypes();
37
+ const filterTypes = await promptFilterTypes();
38
+ //
39
+ // For the selected filters, request the filter values
40
+ if (filterTypes.includes('agency-ids'))
41
+ context.filters.agency_ids = await promptFilterByAgencyIds();
42
+ if (filterTypes.includes('line-ids'))
43
+ context.filters.line_ids = await promptFilterByLineIds();
44
+ if (filterTypes.includes('pattern-ids'))
45
+ context.filters.pattern_ids = await promptFilterByPatternIds();
46
+ if (filterTypes.includes('stop-ids'))
47
+ context.filters.stop_ids = await promptFilterByStopIds();
48
+ if (filterTypes.includes('vehicle-ids'))
49
+ context.filters.vehicle_ids = await promptFilterByVehicleIds();
50
+ context.dates = await promptFilterByDates();
51
+ //
52
+ // Build the tasks array for the selected export types
53
+ await tasks([
54
+ {
55
+ enabled: exportTypes.includes('validations-raw'),
56
+ task: async (message) => await exportValidationsRaw({ context, message }),
57
+ title: exportTypeLabels['validations-raw'],
58
+ },
59
+ {
60
+ enabled: exportTypes.includes('validations-by-stop-by-trip'),
61
+ task: async (message) => await exportValidationsByStopByTrip({ context, message }),
62
+ title: exportTypeLabels['validations-by-stop-by-trip'],
63
+ },
64
+ {
65
+ enabled: exportTypes.includes('validations-by-stop-by-pattern'),
66
+ task: async (message) => await exportValidationsByStopByPattern({ context, message }),
67
+ title: exportTypeLabels['validations-by-stop-by-pattern'],
68
+ },
69
+ {
70
+ enabled: exportTypes.includes('validations-by-stop'),
71
+ task: async (message) => await exportValidationsByStop({ context, message }),
72
+ title: exportTypeLabels['validations-by-stop'],
73
+ },
74
+ {
75
+ enabled: exportTypes.includes('validations-by-pattern'),
76
+ task: async (message) => await exportValidationsByPattern({ context, message }),
77
+ title: exportTypeLabels['validations-by-pattern'],
78
+ },
79
+ {
80
+ enabled: exportTypes.includes('validations-by-line'),
81
+ task: async (message) => await exportValidationsByLine({ context, message }),
82
+ title: exportTypeLabels['validations-by-line'],
83
+ },
84
+ {
85
+ enabled: exportTypes.includes('rides-raw'),
86
+ task: async (message) => await exportRidesRaw({ context, message }),
87
+ title: exportTypeLabels['rides-raw'],
88
+ },
89
+ {
90
+ enabled: exportTypes.includes('vehicle-events-raw'),
91
+ task: async (message) => await exportVehicleEventsRaw({ context, message }),
92
+ title: exportTypeLabels['vehicle-events-raw'],
93
+ },
94
+ ]);
95
+ //
96
+ // Terminate the process
97
+ outro('Exportação terminada.');
98
+ process.exit(0);
99
+ //
100
+ })().catch(console.error);
@@ -0,0 +1,2 @@
1
+ import { type ExportType } from '../types.js';
2
+ export declare function promptExportTypes(): Promise<(ExportType)[]>;
@@ -0,0 +1,34 @@
1
+ /* * */
2
+ import { exportTypeLabels } from '../types.js';
3
+ import { cancel, groupMultiselect, isCancel } from '@clack/prompts';
4
+ /* * */
5
+ export async function promptExportTypes() {
6
+ //
7
+ const values = await groupMultiselect({
8
+ message: 'Escolhe os dados que queres exportar:',
9
+ options: {
10
+ '1. Validações APEX': [
11
+ { label: exportTypeLabels['validations-raw'], value: 'validations-raw' },
12
+ { label: exportTypeLabels['validations-by-stop-by-trip'], value: 'validations-by-stop-by-trip' },
13
+ { label: exportTypeLabels['validations-by-stop-by-pattern'], value: 'validations-by-stop-by-pattern' },
14
+ { label: exportTypeLabels['validations-by-stop'], value: 'validations-by-stop' },
15
+ { label: exportTypeLabels['validations-by-pattern'], value: 'validations-by-pattern' },
16
+ { label: exportTypeLabels['validations-by-line'], value: 'validations-by-line' },
17
+ ],
18
+ '2. Rides': [
19
+ { label: exportTypeLabels['rides-raw'], value: 'rides-raw' },
20
+ ],
21
+ '3. Vehicle Events': [
22
+ { label: exportTypeLabels['vehicle-events-raw'], value: 'vehicle-events-raw' },
23
+ ],
24
+ },
25
+ required: true,
26
+ });
27
+ if (isCancel(values)) {
28
+ cancel('Operação cancelada pelo utilizador.');
29
+ process.exit(0);
30
+ }
31
+ if (!values)
32
+ return [];
33
+ return values;
34
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterByAgencyIds(): Promise<string[]>;
@@ -0,0 +1,25 @@
1
+ /* * */
2
+ import { log, text } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterByAgencyIds() {
5
+ //
6
+ log.step('FILTRAR POR AGENCY ID:');
7
+ log.message('- Introduz os Agency IDs separados por vírgulas. Exemplo: 41,42,etc...');
8
+ log.message('- Se não introduzires nenhum Agency ID, este filtro não será aplicado.');
9
+ const value = await text({
10
+ message: 'Agency IDs:',
11
+ placeholder: '41,42,etc...',
12
+ validate(value) {
13
+ if (value.length === 0)
14
+ return;
15
+ const ids = value.replace(/,$/, '').split(',').map(id => id.trim());
16
+ const invalidIds = ids.filter(id => !/^\d{2}$/.test(id));
17
+ if (invalidIds.length > 0)
18
+ return `Estes IDs são inválidos: ${invalidIds.join(', ')}`;
19
+ return;
20
+ },
21
+ });
22
+ if (!value)
23
+ return [];
24
+ return value.split(',').map(id => id.trim());
25
+ }
@@ -0,0 +1,5 @@
1
+ import { type OperationalDate } from '@tmlmobilidade/types';
2
+ export declare function promptFilterByDates(): Promise<{
3
+ end: OperationalDate;
4
+ start: OperationalDate;
5
+ }>;
@@ -0,0 +1,73 @@
1
+ /* * */
2
+ import { cancel, isCancel, log, text } from '@clack/prompts';
3
+ import { validateOperationalDate } from '@tmlmobilidade/types';
4
+ /* * */
5
+ export async function promptFilterByDates() {
6
+ //
7
+ log.step('FILTRAR POR DATAS:');
8
+ log.message('- Introduz as datas operacionais no formato ano-mês-dia. Exemplo: 20250101 ou 2025-01-01');
9
+ log.message('- Devido ao enorme volume de dados, filtrar por datas é obrigatório.');
10
+ log.message('- A data de início não pode ser anterior a 1 Jan. 2024 (20240101).');
11
+ const startDate = await text({
12
+ initialValue: '20250101',
13
+ message: 'Data de Início:',
14
+ placeholder: '20240101 ou 2024-01-01',
15
+ validate(value) {
16
+ try {
17
+ if (value.length === 0)
18
+ return 'A data de início é obrigatória.';
19
+ const formattedValue = formatOperationalDateInput(value);
20
+ validateOperationalDate(formattedValue);
21
+ if (Number(formattedValue) < 20240101)
22
+ return 'A data de início não pode ser anterior a 2024-01-01.';
23
+ if (Number(formattedValue) > 20291231)
24
+ return 'A data de início não pode ser posterior a 2029-12-31.';
25
+ }
26
+ catch (error) {
27
+ return error.message;
28
+ }
29
+ },
30
+ });
31
+ if (isCancel(startDate)) {
32
+ cancel('Operação cancelada pelo utilizador.');
33
+ process.exit(0);
34
+ }
35
+ const endDate = await text({
36
+ initialValue: '20250102',
37
+ message: 'Data de Fim:',
38
+ placeholder: '20240101 ou 2024-01-01',
39
+ validate(value) {
40
+ try {
41
+ if (value.length === 0)
42
+ return 'A data de fim é obrigatória.';
43
+ const formattedValue = formatOperationalDateInput(value);
44
+ validateOperationalDate(formattedValue);
45
+ if (Number(formattedValue) < Number(startDate))
46
+ return 'A data de fim não pode ser anterior à data de início.';
47
+ if (Number(formattedValue) > 20291231)
48
+ return 'A data de fim não pode ser posterior a 2029-12-31.';
49
+ }
50
+ catch (error) {
51
+ return error.message;
52
+ }
53
+ },
54
+ });
55
+ if (isCancel(startDate)) {
56
+ cancel('Operação cancelada pelo utilizador.');
57
+ process.exit(0);
58
+ }
59
+ return {
60
+ end: validateOperationalDate(formatOperationalDateInput(endDate)),
61
+ start: validateOperationalDate(formatOperationalDateInput(startDate)),
62
+ };
63
+ }
64
+ /**
65
+ * This function formats the operational date
66
+ * string input by removing all non-numeric characters.
67
+ * @param value The input string representing an operational date.
68
+ * @returns The formatted operational date string containing only numeric characters.
69
+ */
70
+ function formatOperationalDateInput(value) {
71
+ // Remove all characters that are not numbers
72
+ return value.replaceAll(/[^0-9]/g, '');
73
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterByLineIds(): Promise<string[]>;
@@ -0,0 +1,25 @@
1
+ /* * */
2
+ import { log, text } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterByLineIds() {
5
+ //
6
+ log.step('FILTRAR POR LINE ID:');
7
+ log.message('- Introduz os Line IDs separados por vírgulas. Exemplo: 1001,1002,etc...');
8
+ log.message('- Se não introduzires nenhum Line ID, este filtro não será aplicado.');
9
+ const value = await text({
10
+ message: 'Line IDs:',
11
+ placeholder: '1001,1002,etc...',
12
+ validate(value) {
13
+ if (value.length === 0)
14
+ return;
15
+ const ids = value.replace(/,$/, '').split(',').map(id => id.trim());
16
+ const invalidIds = ids.filter(id => !/^\d{4}$/.test(id));
17
+ if (invalidIds.length > 0)
18
+ return `Estes IDs são inválidos: ${invalidIds.join(', ')}`;
19
+ return;
20
+ },
21
+ });
22
+ if (!value)
23
+ return [];
24
+ return value.split(',').map(id => id.trim());
25
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterByPatternIds(): Promise<string[]>;
@@ -0,0 +1,25 @@
1
+ /* * */
2
+ import { log, text } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterByPatternIds() {
5
+ //
6
+ log.step('FILTRAR POR PATTERN ID:');
7
+ log.message('- Introduz os Pattern IDs separados por vírgulas. Exemplo: 1001_0_1,1001_0_2,etc...');
8
+ log.message('- Se não introduzires nenhum Pattern ID, este filtro não será aplicado.');
9
+ const value = await text({
10
+ message: 'Pattern IDs:',
11
+ placeholder: '1001_0_1,1001_0_2,etc...',
12
+ validate(value) {
13
+ if (value.length === 0)
14
+ return;
15
+ const ids = value.replace(/,$/, '').split(',').map(id => id.trim());
16
+ const invalidIds = ids.filter(id => !/^\d{4}_\d_\d$/.test(id));
17
+ if (invalidIds.length > 0)
18
+ return `Estes IDs são inválidos: ${invalidIds.join(', ')}`;
19
+ return;
20
+ },
21
+ });
22
+ if (!value)
23
+ return [];
24
+ return value.split(',').map(id => id.trim());
25
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterByStopIds(): Promise<string[]>;
@@ -0,0 +1,26 @@
1
+ /* * */
2
+ import { log, text } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterByStopIds() {
5
+ //
6
+ log.step('FILTRAR POR STOP ID:');
7
+ log.message('- Introduz os Stop IDs separados por vírgulas. Exemplo: 010101,020202,etc...');
8
+ log.message('- Não te esqueças do zero à esquerda.');
9
+ log.message('- Se não introduzires nenhum Stop ID, este filtro não será aplicado.');
10
+ const value = await text({
11
+ message: 'Stop IDs:',
12
+ placeholder: '010101,020202,etc...',
13
+ validate(value) {
14
+ if (value.length === 0)
15
+ return;
16
+ const ids = value.replace(/,$/, '').split(',').map(id => id.trim());
17
+ const invalidIds = ids.filter(id => !/^\d{6}$/.test(id));
18
+ if (invalidIds.length > 0)
19
+ return `Estes IDs são inválidos: ${invalidIds.join(', ')}`;
20
+ return;
21
+ },
22
+ });
23
+ if (!value)
24
+ return [];
25
+ return value.split(',').map(id => id.trim());
26
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterTypes(): Promise<string[]>;
@@ -0,0 +1,20 @@
1
+ /* * */
2
+ import { multiselect } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterTypes() {
5
+ //
6
+ const values = await multiselect({
7
+ message: 'Escolhe os filtros que queres aplicar:',
8
+ options: [
9
+ { label: 'Operador (agency_id)', value: 'agency-ids' },
10
+ { label: 'Paragem (stop_id)', value: 'stop-ids' },
11
+ { label: 'Linha (line_id)', value: 'line-ids' },
12
+ { label: 'Pattern (pattern_id)', value: 'pattern-ids' },
13
+ { label: 'Veículo (vehicle_id)', value: 'vehicle-ids' },
14
+ ],
15
+ required: false,
16
+ });
17
+ if (!values)
18
+ return [];
19
+ return values;
20
+ }
@@ -0,0 +1 @@
1
+ export declare function promptFilterByVehicleIds(): Promise<number[]>;
@@ -0,0 +1,25 @@
1
+ /* * */
2
+ import { log, text } from '@clack/prompts';
3
+ /* * */
4
+ export async function promptFilterByVehicleIds() {
5
+ //
6
+ log.step('FILTRAR POR VEHICLE ID:');
7
+ log.message('- Introduz os Vehicle IDs separados por vírgulas. Exemplo: 1234,9876,etc...');
8
+ log.message('- Se não introduzires nenhum Vehicle ID, este filtro não será aplicado.');
9
+ const value = await text({
10
+ message: 'Vehicle IDs:',
11
+ placeholder: '1234,9876,etc...',
12
+ validate(value) {
13
+ if (value.length === 0)
14
+ return;
15
+ const ids = value.replace(/,$/, '').split(',').map(id => id.trim());
16
+ const invalidIds = ids.filter(id => !/^\d+$/.test(id));
17
+ if (invalidIds.length > 0)
18
+ return `Estes IDs são inválidos: ${invalidIds.join(', ')}`;
19
+ return;
20
+ },
21
+ });
22
+ if (!value)
23
+ return [];
24
+ return value.split(',').map(id => Number(id.trim()));
25
+ }
@@ -0,0 +1,2 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ export declare function exportValidationsByLine({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,85 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-by-line';
8
+ /* * */
9
+ export async function exportValidationsByLine({ context, message }) {
10
+ //
11
+ message('A iniciar a exportação de Validações APEX por Linha...');
12
+ //
13
+ // Prepare the filter params
14
+ const filterQuery = {
15
+ is_passenger: true,
16
+ };
17
+ filterQuery.created_at = {
18
+ $gte: Dates
19
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
20
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
21
+ .unix_timestamp,
22
+ $lt: Dates
23
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
24
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
25
+ .unix_timestamp,
26
+ };
27
+ if (context.filters.agency_ids.length) {
28
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
29
+ }
30
+ if (context.filters.line_ids.length) {
31
+ filterQuery.line_id = { $in: context.filters.line_ids };
32
+ }
33
+ if (context.filters.pattern_ids.length) {
34
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
35
+ }
36
+ if (context.filters.stop_ids.length) {
37
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
38
+ }
39
+ if (context.filters.vehicle_ids.length) {
40
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
41
+ }
42
+ //
43
+ // Setup a database stream to export data
44
+ message(`A iniciar ligação à base de dados...`);
45
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
46
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
47
+ //
48
+ // Prepare the output directory and CSV writer
49
+ message(`A preparar a pasta para guardar os resultados...`);
50
+ if (!fs.existsSync(context.output))
51
+ fs.mkdirSync(context.output, { recursive: true });
52
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
53
+ //
54
+ // Export the data
55
+ let counter = 0;
56
+ message(`A aguardar o resultado da pesquisa...`);
57
+ const result = {};
58
+ for await (const doc of stream) {
59
+ const document = doc;
60
+ //
61
+ // Prepare the result key
62
+ const operationalDate = Dates
63
+ .fromUnixTimestamp(document.created_at)
64
+ .operational_date;
65
+ const resultKey = `${operationalDate}:${document.line_id}`;
66
+ //
67
+ // Update the result with the current document
68
+ if (!result[resultKey]) {
69
+ result[resultKey] = {
70
+ date: operationalDate,
71
+ line_id: document.line_id,
72
+ validations: 0,
73
+ };
74
+ }
75
+ result[resultKey].validations += 1;
76
+ if (counter % 1000 === 0)
77
+ message(`Processados ${counter} documentos até agora...`);
78
+ counter++;
79
+ //
80
+ }
81
+ message(`A escrever os resultados no ficheiro CSV...`);
82
+ await csvWriter.write(Object.values(result));
83
+ await csvWriter.flush();
84
+ //
85
+ }
@@ -0,0 +1,5 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ /**
3
+ * Export Validations By Pattern data applying the given filters.
4
+ */
5
+ export declare function exportValidationsByPattern({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,87 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-by-pattern';
8
+ /**
9
+ * Export Validations By Pattern data applying the given filters.
10
+ */
11
+ export async function exportValidationsByPattern({ context, message }) {
12
+ //
13
+ message('A iniciar a exportação de Validações APEX por Pattern...');
14
+ //
15
+ // Prepare the filter params
16
+ const filterQuery = {
17
+ is_passenger: true,
18
+ };
19
+ filterQuery.created_at = {
20
+ $gte: Dates
21
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ $lt: Dates
25
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
26
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
27
+ .unix_timestamp,
28
+ };
29
+ if (context.filters.agency_ids.length) {
30
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
31
+ }
32
+ if (context.filters.line_ids.length) {
33
+ filterQuery.line_id = { $in: context.filters.line_ids };
34
+ }
35
+ if (context.filters.pattern_ids.length) {
36
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
37
+ }
38
+ if (context.filters.stop_ids.length) {
39
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
40
+ }
41
+ if (context.filters.vehicle_ids.length) {
42
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
43
+ }
44
+ //
45
+ // Setup a database stream to export data
46
+ message(`A iniciar ligação à base de dados...`);
47
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
48
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
49
+ //
50
+ // Prepare the output directory and CSV writer
51
+ message(`A preparar a pasta para guardar os resultados...`);
52
+ if (!fs.existsSync(context.output))
53
+ fs.mkdirSync(context.output, { recursive: true });
54
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
55
+ //
56
+ // Export the data
57
+ let counter = 0;
58
+ message(`A aguardar o resultado da pesquisa...`);
59
+ const result = {};
60
+ for await (const doc of stream) {
61
+ const document = doc;
62
+ //
63
+ // Prepare the result key
64
+ const operationalDate = Dates
65
+ .fromUnixTimestamp(document.created_at)
66
+ .operational_date;
67
+ const resultKey = `${operationalDate}:${document.pattern_id}`;
68
+ //
69
+ // Update the result with the current document
70
+ if (!result[resultKey]) {
71
+ result[resultKey] = {
72
+ date: operationalDate,
73
+ pattern_id: document.pattern_id,
74
+ validations: 0,
75
+ };
76
+ }
77
+ result[resultKey].validations += 1;
78
+ if (counter % 1000 === 0)
79
+ message(`Processados ${counter} documentos até agora...`);
80
+ counter++;
81
+ //
82
+ }
83
+ message(`A escrever os resultados no ficheiro CSV...`);
84
+ await csvWriter.write(Object.values(result));
85
+ await csvWriter.flush();
86
+ //
87
+ }
@@ -0,0 +1,5 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ /**
3
+ * Export Validations By Stop By Pattern data applying the given filters.
4
+ */
5
+ export declare function exportValidationsByStopByPattern({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,88 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-by-stop-by-pattern';
8
+ /**
9
+ * Export Validations By Stop By Pattern data applying the given filters.
10
+ */
11
+ export async function exportValidationsByStopByPattern({ context, message }) {
12
+ //
13
+ message('A iniciar a exportação de Validações APEX por Paragem e por Pattern...');
14
+ //
15
+ // Prepare the filter params
16
+ const filterQuery = {
17
+ is_passenger: true,
18
+ };
19
+ filterQuery.created_at = {
20
+ $gte: Dates
21
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ $lt: Dates
25
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
26
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
27
+ .unix_timestamp,
28
+ };
29
+ if (context.filters.agency_ids.length) {
30
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
31
+ }
32
+ if (context.filters.line_ids.length) {
33
+ filterQuery.line_id = { $in: context.filters.line_ids };
34
+ }
35
+ if (context.filters.pattern_ids.length) {
36
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
37
+ }
38
+ if (context.filters.stop_ids.length) {
39
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
40
+ }
41
+ if (context.filters.vehicle_ids.length) {
42
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
43
+ }
44
+ //
45
+ // Setup a database stream to export data
46
+ message(`A iniciar ligação à base de dados...`);
47
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
48
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
49
+ //
50
+ // Prepare the output directory and CSV writer
51
+ message(`A preparar a pasta para guardar os resultados...`);
52
+ if (!fs.existsSync(context.output))
53
+ fs.mkdirSync(context.output, { recursive: true });
54
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
55
+ //
56
+ // Export the data
57
+ let counter = 0;
58
+ message(`A aguardar o resultado da pesquisa...`);
59
+ const result = {};
60
+ for await (const doc of stream) {
61
+ const document = doc;
62
+ //
63
+ // Prepare the result key
64
+ const operationalDate = Dates
65
+ .fromUnixTimestamp(document.created_at)
66
+ .operational_date;
67
+ const resultKey = `${operationalDate}:${document.stop_id}:${document.pattern_id}`;
68
+ //
69
+ // Update the result with the current document
70
+ if (!result[resultKey]) {
71
+ result[resultKey] = {
72
+ date: operationalDate,
73
+ pattern_id: document.pattern_id,
74
+ stop_id: document.stop_id,
75
+ validations: 0,
76
+ };
77
+ }
78
+ result[resultKey].validations += 1;
79
+ if (counter % 1000 === 0)
80
+ message(`Processados ${counter} documentos até agora...`);
81
+ counter++;
82
+ //
83
+ }
84
+ message(`A escrever os resultados no ficheiro CSV...`);
85
+ await csvWriter.write(Object.values(result));
86
+ await csvWriter.flush();
87
+ //
88
+ }
@@ -0,0 +1,5 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ /**
3
+ * Export Validations By Stop By Trip data applying the given filters.
4
+ */
5
+ export declare function exportValidationsByStopByTrip({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,88 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-by-stop-by-trip';
8
+ /**
9
+ * Export Validations By Stop By Trip data applying the given filters.
10
+ */
11
+ export async function exportValidationsByStopByTrip({ context, message }) {
12
+ //
13
+ message('A iniciar a exportação de Validações APEX por Paragem e por Viagem...');
14
+ //
15
+ // Prepare the filter params
16
+ const filterQuery = {
17
+ is_passenger: true,
18
+ };
19
+ filterQuery.created_at = {
20
+ $gte: Dates
21
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ $lt: Dates
25
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
26
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
27
+ .unix_timestamp,
28
+ };
29
+ if (context.filters.agency_ids.length) {
30
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
31
+ }
32
+ if (context.filters.line_ids.length) {
33
+ filterQuery.line_id = { $in: context.filters.line_ids };
34
+ }
35
+ if (context.filters.pattern_ids.length) {
36
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
37
+ }
38
+ if (context.filters.stop_ids.length) {
39
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
40
+ }
41
+ if (context.filters.vehicle_ids.length) {
42
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
43
+ }
44
+ //
45
+ // Setup a database stream to export data
46
+ message(`A iniciar ligação à base de dados...`);
47
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
48
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
49
+ //
50
+ // Prepare the output directory and CSV writer
51
+ message(`A preparar a pasta para guardar os resultados...`);
52
+ if (!fs.existsSync(context.output))
53
+ fs.mkdirSync(context.output, { recursive: true });
54
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
55
+ //
56
+ // Export the data
57
+ let counter = 0;
58
+ message(`A aguardar o resultado da pesquisa...`);
59
+ const result = {};
60
+ for await (const doc of stream) {
61
+ const document = doc;
62
+ //
63
+ // Prepare the result key
64
+ const operationalDate = Dates
65
+ .fromUnixTimestamp(document.created_at)
66
+ .operational_date;
67
+ const resultKey = `${operationalDate}:${document.stop_id}:${document.trip_id}`;
68
+ //
69
+ // Update the result with the current document
70
+ if (!result[resultKey]) {
71
+ result[resultKey] = {
72
+ date: operationalDate,
73
+ stop_id: document.stop_id,
74
+ trip_id: document.trip_id,
75
+ validations: 0,
76
+ };
77
+ }
78
+ result[resultKey].validations += 1;
79
+ if (counter % 1000 === 0)
80
+ message(`Processados ${counter} documentos até agora...`);
81
+ counter++;
82
+ //
83
+ }
84
+ message(`A escrever os resultados no ficheiro CSV...`);
85
+ await csvWriter.write(Object.values(result));
86
+ await csvWriter.flush();
87
+ //
88
+ }
@@ -0,0 +1,5 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ /**
3
+ * Export Validations By Stop data applying the given filters.
4
+ */
5
+ export declare function exportValidationsByStop({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,87 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-by-stop';
8
+ /**
9
+ * Export Validations By Stop data applying the given filters.
10
+ */
11
+ export async function exportValidationsByStop({ context, message }) {
12
+ //
13
+ message('A iniciar a exportação de Validações APEX por Paragem...');
14
+ //
15
+ // Prepare the filter params
16
+ const filterQuery = {
17
+ is_passenger: true,
18
+ };
19
+ filterQuery.created_at = {
20
+ $gte: Dates
21
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ $lt: Dates
25
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
26
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
27
+ .unix_timestamp,
28
+ };
29
+ if (context.filters.agency_ids.length) {
30
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
31
+ }
32
+ if (context.filters.line_ids.length) {
33
+ filterQuery.line_id = { $in: context.filters.line_ids };
34
+ }
35
+ if (context.filters.pattern_ids.length) {
36
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
37
+ }
38
+ if (context.filters.stop_ids.length) {
39
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
40
+ }
41
+ if (context.filters.vehicle_ids.length) {
42
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
43
+ }
44
+ //
45
+ // Setup a database stream to export data
46
+ message(`A iniciar ligação à base de dados...`);
47
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
48
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
49
+ //
50
+ // Prepare the output directory and CSV writer
51
+ message(`A preparar a pasta para guardar os resultados...`);
52
+ if (!fs.existsSync(context.output))
53
+ fs.mkdirSync(context.output, { recursive: true });
54
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
55
+ //
56
+ // Export the data
57
+ let counter = 0;
58
+ message(`A aguardar o resultado da pesquisa...`);
59
+ const result = {};
60
+ for await (const doc of stream) {
61
+ const document = doc;
62
+ //
63
+ // Prepare the result key
64
+ const operationalDate = Dates
65
+ .fromUnixTimestamp(document.created_at)
66
+ .operational_date;
67
+ const resultKey = `${operationalDate}:${document.stop_id}`;
68
+ //
69
+ // Update the result with the current document
70
+ if (!result[resultKey]) {
71
+ result[resultKey] = {
72
+ date: operationalDate,
73
+ stop_id: document.stop_id,
74
+ validations: 0,
75
+ };
76
+ }
77
+ result[resultKey].validations += 1;
78
+ if (counter % 1000 === 0)
79
+ message(`Processados ${counter} documentos até agora...`);
80
+ counter++;
81
+ //
82
+ }
83
+ message(`A escrever os resultados no ficheiro CSV...`);
84
+ await csvWriter.write(Object.values(result));
85
+ await csvWriter.flush();
86
+ //
87
+ }
@@ -0,0 +1,2 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ export declare function exportValidationsRaw({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,64 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedApexValidations } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'validations-raw';
8
+ /* * */
9
+ export async function exportValidationsRaw({ context, message }) {
10
+ //
11
+ message('A iniciar a exportação de Validações APEX em bruto...');
12
+ //
13
+ // Prepare the filter params
14
+ const filterQuery = {};
15
+ filterQuery.created_at = {
16
+ $gte: Dates
17
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
18
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
19
+ .unix_timestamp,
20
+ $lt: Dates
21
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ };
25
+ if (context.filters.agency_ids.length) {
26
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
27
+ }
28
+ if (context.filters.line_ids.length) {
29
+ filterQuery.line_id = { $in: context.filters.line_ids };
30
+ }
31
+ if (context.filters.pattern_ids.length) {
32
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
33
+ }
34
+ if (context.filters.stop_ids.length) {
35
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
36
+ }
37
+ if (context.filters.vehicle_ids.length) {
38
+ filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
39
+ }
40
+ //
41
+ // Setup a database stream to export data
42
+ message(`A iniciar ligação à base de dados...`);
43
+ const simplifiedApexValidationsCollection = await simplifiedApexValidations.getCollection();
44
+ const stream = simplifiedApexValidationsCollection.find(filterQuery).stream();
45
+ //
46
+ // Prepare the output directory and CSV writer
47
+ message(`A preparar a pasta para guardar os resultados...`);
48
+ if (!fs.existsSync(context.output))
49
+ fs.mkdirSync(context.output, { recursive: true });
50
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
51
+ //
52
+ // Export the data
53
+ let counter = 0;
54
+ message(`A aguardar o resultado da pesquisa...`);
55
+ for await (const doc of stream) {
56
+ const document = doc;
57
+ await csvWriter.write(document);
58
+ if (counter % 1000 === 0)
59
+ message(`Processados ${counter} documentos até agora...`);
60
+ counter++;
61
+ }
62
+ await csvWriter.flush();
63
+ //
64
+ }
@@ -0,0 +1,2 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ export declare function exportRidesRaw({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,54 @@
1
+ /* * */
2
+ import { rides } from '@tmlmobilidade/interfaces';
3
+ import { CsvWriter } from '@tmlmobilidade/writers';
4
+ import fs from 'node:fs';
5
+ /* * */
6
+ const TASK_ID = 'rides-raw';
7
+ /* * */
8
+ export async function exportRidesRaw({ context, message }) {
9
+ //
10
+ message('A iniciar a exportação de Rides em bruto...');
11
+ //
12
+ // Prepare the filter params
13
+ const filterQuery = {};
14
+ filterQuery.operational_date = {
15
+ $gte: context.dates.start,
16
+ $lte: context.dates.end,
17
+ };
18
+ if (context.filters.agency_ids.length) {
19
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
20
+ }
21
+ if (context.filters.line_ids.length) {
22
+ filterQuery.line_id = { $in: context.filters.line_ids.map(Number) };
23
+ }
24
+ if (context.filters.pattern_ids.length) {
25
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
26
+ }
27
+ if (context.filters.vehicle_ids.length) {
28
+ filterQuery.vehicle_ids = { $in: context.filters.vehicle_ids };
29
+ }
30
+ //
31
+ // Setup a database stream to export data
32
+ message(`A iniciar ligação à base de dados...`);
33
+ const ridesCollection = await rides.getCollection();
34
+ const stream = ridesCollection.find(filterQuery).stream();
35
+ //
36
+ // Prepare the output directory and CSV writer
37
+ message(`A preparar a pasta para guardar os resultados...`);
38
+ if (!fs.existsSync(context.output))
39
+ fs.mkdirSync(context.output, { recursive: true });
40
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
41
+ //
42
+ // Export the data
43
+ let counter = 0;
44
+ message(`A aguardar o resultado da pesquisa...`);
45
+ for await (const doc of stream) {
46
+ const document = doc;
47
+ await csvWriter.write(document);
48
+ if (counter % 1000 === 0)
49
+ message(`Processados ${counter} documentos até agora...`);
50
+ counter++;
51
+ }
52
+ await csvWriter.flush();
53
+ //
54
+ }
@@ -0,0 +1,2 @@
1
+ import { type TaskProps } from '../../types.js';
2
+ export declare function exportVehicleEventsRaw({ context, message }: TaskProps): Promise<void>;
@@ -0,0 +1,64 @@
1
+ /* * */
2
+ import { Dates } from '@tmlmobilidade/dates';
3
+ import { simplifiedVehicleEvents } from '@tmlmobilidade/interfaces';
4
+ import { CsvWriter } from '@tmlmobilidade/writers';
5
+ import fs from 'node:fs';
6
+ /* * */
7
+ const TASK_ID = 'vehicle-events-raw';
8
+ /* * */
9
+ export async function exportVehicleEventsRaw({ context, message }) {
10
+ //
11
+ message('A iniciar a exportação de Vehicle Events em bruto...');
12
+ //
13
+ // Prepare the filter params
14
+ const filterQuery = {};
15
+ filterQuery.created_at = {
16
+ $gte: Dates
17
+ .fromOperationalDate(context.dates.start, 'Europe/Lisbon')
18
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
19
+ .unix_timestamp,
20
+ $lt: Dates
21
+ .fromOperationalDate(context.dates.end, 'Europe/Lisbon')
22
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 })
23
+ .unix_timestamp,
24
+ };
25
+ if (context.filters.agency_ids.length) {
26
+ filterQuery.agency_id = { $in: context.filters.agency_ids };
27
+ }
28
+ if (context.filters.line_ids.length) {
29
+ filterQuery.line_id = { $in: context.filters.line_ids };
30
+ }
31
+ if (context.filters.pattern_ids.length) {
32
+ filterQuery.pattern_id = { $in: context.filters.pattern_ids };
33
+ }
34
+ if (context.filters.stop_ids.length) {
35
+ filterQuery.stop_id = { $in: context.filters.stop_ids };
36
+ }
37
+ // if (context.filters.vehicle_ids.length) {
38
+ // filterQuery.vehicle_id = { $in: context.filters.vehicle_ids };
39
+ // }
40
+ //
41
+ // Setup a database stream to export data
42
+ message(`A iniciar ligação à base de dados...`);
43
+ const simplifiedVehicleEventsCollection = await simplifiedVehicleEvents.getCollection();
44
+ const stream = simplifiedVehicleEventsCollection.find(filterQuery).stream();
45
+ //
46
+ // Prepare the output directory and CSV writer
47
+ message(`A preparar a pasta para guardar os resultados...`);
48
+ if (!fs.existsSync(context.output))
49
+ fs.mkdirSync(context.output, { recursive: true });
50
+ const csvWriter = new CsvWriter('output', `${context.output}/${TASK_ID}-${context.dates.start}-${context.dates.end}.csv`, { batch_size: 100000, logs: false });
51
+ //
52
+ // Export the data
53
+ let counter = 0;
54
+ message(`A aguardar o resultado da pesquisa...`);
55
+ for await (const doc of stream) {
56
+ const document = doc;
57
+ await csvWriter.write(document);
58
+ if (counter % 1000 === 0)
59
+ message(`Processados ${counter} documentos até agora...`);
60
+ counter++;
61
+ }
62
+ await csvWriter.flush();
63
+ //
64
+ }
@@ -0,0 +1,31 @@
1
+ import { type OperationalDate } from '@tmlmobilidade/types';
2
+ export declare const exportTypeLabels: {
3
+ readonly 'rides-raw': "2.0. Rides em bruto (SLAs)";
4
+ readonly 'validations-by-line': "1.5. Validações por Line ID";
5
+ readonly 'validations-by-pattern': "1.4. Validações por Pattern ID";
6
+ readonly 'validations-by-stop': "1.3. Validações por Stop ID";
7
+ readonly 'validations-by-stop-by-pattern': "1.2. Validações por Stop ID, por Pattern ID";
8
+ readonly 'validations-by-stop-by-trip': "1.1. Validações por Stop ID, por Trip ID";
9
+ readonly 'validations-raw': "1.0. Validações em bruto";
10
+ readonly 'vehicle-events-raw': "3.0. Vehicle Events em bruto";
11
+ };
12
+ export type ExportType = keyof typeof exportTypeLabels;
13
+ export interface ExportContext {
14
+ _id: string;
15
+ dates: {
16
+ end: OperationalDate;
17
+ start: OperationalDate;
18
+ };
19
+ filters: {
20
+ agency_ids: string[];
21
+ line_ids: string[];
22
+ pattern_ids: string[];
23
+ stop_ids: string[];
24
+ vehicle_ids: number[];
25
+ };
26
+ output: string;
27
+ }
28
+ export interface TaskProps {
29
+ context: ExportContext;
30
+ message: (msg: string) => void;
31
+ }
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ /* * */
2
+ /* * */
3
+ export const exportTypeLabels = {
4
+ 'rides-raw': '2.0. Rides em bruto (SLAs)',
5
+ 'validations-by-line': '1.5. Validações por Line ID',
6
+ 'validations-by-pattern': '1.4. Validações por Pattern ID',
7
+ 'validations-by-stop': '1.3. Validações por Stop ID',
8
+ 'validations-by-stop-by-pattern': '1.2. Validações por Stop ID, por Pattern ID',
9
+ 'validations-by-stop-by-trip': '1.1. Validações por Stop ID, por Trip ID',
10
+ 'validations-raw': '1.0. Validações em bruto',
11
+ 'vehicle-events-raw': '3.0. Vehicle Events em bruto',
12
+ };
@@ -0,0 +1,2 @@
1
+ import { type ExportContext } from '../types.js';
2
+ export declare function initExportContext(): ExportContext;
@@ -0,0 +1,31 @@
1
+ /* * */
2
+ import { generateRandomString } from '@tmlmobilidade/strings';
3
+ import path from 'node:path';
4
+ /* * */
5
+ export function initExportContext() {
6
+ //
7
+ //
8
+ // Generate a random export ID
9
+ const exportId = generateRandomString();
10
+ //
11
+ // Setup the output path for the export by joining
12
+ // the current working directory with the export ID
13
+ const outputPath = path.join(process.cwd(), `export-${exportId}`);
14
+ //
15
+ // Build and return the export context object
16
+ return {
17
+ _id: exportId,
18
+ dates: {
19
+ end: undefined,
20
+ start: undefined,
21
+ },
22
+ filters: {
23
+ agency_ids: [],
24
+ line_ids: [],
25
+ pattern_ids: [],
26
+ stop_ids: [],
27
+ vehicle_ids: [],
28
+ },
29
+ output: outputPath,
30
+ };
31
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@tmlmobilidade/export-data",
3
+ "description": "CLI tool to export data from GO.",
4
+ "version": "20251229.1441.35",
5
+ "author": {
6
+ "email": "iso@tmlmobilidade.pt",
7
+ "name": "TML-ISO"
8
+ },
9
+ "license": "AGPL-3.0-or-later",
10
+ "keywords": [
11
+ "navegante",
12
+ "tmlmobilidade",
13
+ "public-transit",
14
+ "carrismetropolitana"
15
+ ],
16
+ "type": "module",
17
+ "files": [
18
+ "dist",
19
+ "template",
20
+ "README.md",
21
+ "LICENSE",
22
+ "CHANGELOG.md",
23
+ "package.json"
24
+ ],
25
+ "main": "./dist/index.js",
26
+ "exports": {
27
+ ".": "./dist/index.js"
28
+ },
29
+ "bin": {
30
+ "export-data": "./dist/index.js"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc && resolve-tspaths",
34
+ "dev": "dotenv-run -f ./.env -- tsx src/index.ts",
35
+ "lint": "eslint .",
36
+ "lint:fix": "eslint . --fix"
37
+ },
38
+ "dependencies": {
39
+ "@clack/prompts": "0.11.0",
40
+ "@tmlmobilidade/consts": "*",
41
+ "@tmlmobilidade/dates": "*",
42
+ "@tmlmobilidade/interfaces": "*",
43
+ "@tmlmobilidade/strings": "*",
44
+ "@tmlmobilidade/timer": "*",
45
+ "@tmlmobilidade/writers": "*"
46
+ },
47
+ "devDependencies": {
48
+ "@tmlmobilidade/tsconfig": "*",
49
+ "@tmlmobilidade/types": "*",
50
+ "@types/node": "25.0.3",
51
+ "resolve-tspaths": "0.8.23",
52
+ "typescript": "5.9.3"
53
+ }
54
+ }